diff --git a/patches/api/Add-more-fields-to-AsyncPreLoginEvent.patch b/patches/api/Add-more-fields-to-AsyncPreLoginEvent.patch index 5324dde1a5..e8a8798a7c 100644 --- a/patches/api/Add-more-fields-to-AsyncPreLoginEvent.patch +++ b/patches/api/Add-more-fields-to-AsyncPreLoginEvent.patch @@ -3,6 +3,8 @@ From: Aikar Date: Sun, 18 Mar 2018 11:43:30 -0400 Subject: [PATCH] Add more fields to AsyncPreLoginEvent +Co-authored-by: Connor Linfoot +Co-authored-by: MCMDEV diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/API-for-updating-recipes-on-clients.patch b/patches/server/API-for-updating-recipes-on-clients.patch index a3f466e3bb..0a7b99632e 100644 --- a/patches/server/API-for-updating-recipes-on-clients.patch +++ b/patches/server/API-for-updating-recipes-on-clients.patch @@ -12,13 +12,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public void reloadResources() { -+ // Paper start - split this method up into separate methods ++ // Paper start - API for updating recipes on clients + this.reloadAdvancementData(); + this.reloadTagData(); + this.reloadRecipeData(); + } + public void reloadAdvancementData() { -+ // Paper end ++ // Paper end - API for updating recipes on clients // CraftBukkit start /*Iterator iterator = this.advancements.values().iterator(); @@ -26,15 +26,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // CraftBukkit end -+ // Paper start ++ // Paper start - API for updating recipes on clients + } + public void reloadTagData() { -+ // Paper end ++ // Paper end - API for updating recipes on clients this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries))); -+ // Paper start ++ // Paper start - API for updating recipes on clients + } + public void reloadRecipeData() { -+ // Paper end ++ // Paper end - API for updating recipes on clients ClientboundUpdateRecipesPacket packetplayoutrecipeupdate = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes()); Iterator iterator1 = this.players.iterator(); @@ -46,7 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ReloadCommand.reload(this.console); } -+ // Paper start ++ // Paper start - API for updating recipes on clients + @Override + public void updateResources() { + this.playerList.reloadResources(); @@ -56,7 +56,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void updateRecipes() { + this.playerList.reloadRecipeData(); + } -+ // Paper end ++ // Paper end - API for updating recipes on clients + private void loadIcon() { this.icon = new CraftIconCache(null); @@ -65,13 +65,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean addRecipe(Recipe recipe) { -+ // Paper start ++ // Paper start - API for updating recipes on clients + return this.addRecipe(recipe, false); + } + + @Override + public boolean addRecipe(Recipe recipe, boolean resendRecipes) { -+ // Paper end ++ // Paper end - API for updating recipes on clients CraftRecipe toAdd; if (recipe instanceof CraftRecipe) { toAdd = (CraftRecipe) recipe; @@ -79,11 +79,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } toAdd.addToCraftingManager(); -+ // Paper start ++ // Paper start - API for updating recipes on clients + if (resendRecipes) { + this.playerList.reloadRecipeData(); + } -+ // Paper end ++ // Paper end - API for updating recipes on clients return true; } @@ -91,13 +91,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean removeRecipe(NamespacedKey recipeKey) { -+ // Paper start ++ // Paper start - API for updating recipes on clients + return this.removeRecipe(recipeKey, false); + } + + @Override + public boolean removeRecipe(NamespacedKey recipeKey, boolean resendRecipes) { -+ // Paper end ++ // Paper end - API for updating recipes on clients Preconditions.checkArgument(recipeKey != null, "recipeKey == null"); ResourceLocation mcKey = CraftNamespacedKey.toMinecraft(recipeKey); diff --git a/patches/server/Expose-clicked-BlockFace-during-BlockDamageEvent.patch b/patches/server/Add-BlockFace-to-BlockDamageEvent.patch similarity index 91% rename from patches/server/Expose-clicked-BlockFace-during-BlockDamageEvent.patch rename to patches/server/Add-BlockFace-to-BlockDamageEvent.patch index c49119956d..154e2f3ea9 100644 --- a/patches/server/Expose-clicked-BlockFace-during-BlockDamageEvent.patch +++ b/patches/server/Add-BlockFace-to-BlockDamageEvent.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: aerulion Date: Mon, 21 Aug 2023 04:36:07 +0200 -Subject: [PATCH] Expose clicked BlockFace during BlockDamageEvent +Subject: [PATCH] Add BlockFace to BlockDamageEvent diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return; } - org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f); -+ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, direction, this.player.getInventory().getSelected(), f >= 1.0f); // Paper - Expose BlockFace ++ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, direction, this.player.getInventory().getSelected(), f >= 1.0f); // Paper - Add BlockFace to BlockDamageEvent if (blockEvent.isCancelled()) { // Let the client know the block still exists @@ -26,14 +26,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 * BlockDamageEvent */ - public static BlockDamageEvent callBlockDamageEvent(ServerPlayer who, BlockPos pos, ItemStack itemstack, boolean instaBreak) { -+ public static BlockDamageEvent callBlockDamageEvent(ServerPlayer who, BlockPos pos, Direction direction, ItemStack itemstack, boolean instaBreak) { // Paper - Expose BlockFace ++ public static BlockDamageEvent callBlockDamageEvent(ServerPlayer who, BlockPos pos, Direction direction, ItemStack itemstack, boolean instaBreak) { // Paper - Add BlockFace to BlockDamageEvent Player player = who.getBukkitEntity(); CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); Block blockClicked = CraftBlock.at(who.level(), pos); - BlockDamageEvent event = new BlockDamageEvent(player, blockClicked, itemInHand, instaBreak); -+ BlockDamageEvent event = new BlockDamageEvent(player, blockClicked, CraftBlock.notchToBlockFace(direction), itemInHand, instaBreak); // Paper - Expose BlockFace ++ BlockDamageEvent event = new BlockDamageEvent(player, blockClicked, CraftBlock.notchToBlockFace(direction), itemInHand, instaBreak); // Paper - Add BlockFace to BlockDamageEvent player.getServer().getPluginManager().callEvent(event); return event; diff --git a/patches/server/Add-Listing-API-for-Player.patch b/patches/server/Add-Listing-API-for-Player.patch index 6ca22cbff7..70ff39b92f 100644 --- a/patches/server/Add-Listing-API-for-Player.patch +++ b/patches/server/Add-Listing-API-for-Player.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.actions = EnumSet.of(action); this.entries = List.of(new ClientboundPlayerInfoUpdatePacket.Entry(player)); } -+ // Paper start ++ // Paper start - Add Listing API for Player + public ClientboundPlayerInfoUpdatePacket(EnumSet actions, List entries) { + this.actions = actions; + this.entries = entries; @@ -22,14 +22,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.actions = actions; + this.entries = List.of(entry); + } -+ // Paper end ++ // Paper end - Add Listing API for Player public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection players) { EnumSet enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME); return new ClientboundPlayerInfoUpdatePacket(enumSet, players); } -+ // Paper start ++ // Paper start - Add Listing API for Player + public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection players, ServerPlayer forPlayer) { + final EnumSet enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME); + final List entries = new java.util.ArrayList<>(players.size()); @@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + EnumSet enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED); + return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, listed)); + } -+ // Paper end ++ // Paper end - Add Listing API for Player + public ClientboundPlayerInfoUpdatePacket(FriendlyByteBuf buf) { this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class); @@ -60,18 +60,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static record Entry(UUID profileId, @Nullable GameProfile profile, boolean listed, int latency, GameType gameMode, @Nullable Component displayName, @Nullable RemoteChatSession.Data chatSession) { Entry(ServerPlayer player) { - this(player.getUUID(), player.getGameProfile(), true, player.connection.latency(), player.gameMode.getGameModeForPlayer(), player.getTabListDisplayName(), Optionull.map(player.getChatSession(), RemoteChatSession::asData)); -+ // Paper start - add listed ++ // Paper start - Add Listing API for Player + this(player, true); + } + Entry(ServerPlayer player, boolean listed) { + this(player.getUUID(), player.getGameProfile(), listed, player.connection.latency(), player.gameMode.getGameModeForPlayer(), player.getTabListDisplayName(), Optionull.map(player.getChatSession(), RemoteChatSession::asData)); -+ // Paper end - add listed + } -+ // Paper start + Entry(UUID profileId, boolean listed) { + this(profileId, null, listed, 0, GameType.DEFAULT_MODE, null, null); } -+ // Paper end ++ // Paper end - Add Listing API for Player } static class EntryBuilder { @@ -84,22 +82,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start - sendAll above replaced with this loop - ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); -+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper ++ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player final List onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - use single player info update packet for (int i = 0; i < this.players.size(); ++i) { ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { -+ // Paper start ++ // Paper start - Add Listing API for Player + if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) { -+ // Paper end ++ // Paper end - Add Listing API for Player entityplayer1.connection.send(packet); -+ // Paper start ++ // Paper start - Add Listing API for Player + } else { + entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false)); + } -+ // Paper end ++ // Paper end - Add Listing API for Player } if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - don't include joining player @@ -108,7 +106,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start - use single player info update packet if (!onlinePlayers.isEmpty()) { - player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers)); -+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); ++ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player } // Paper end player.sentListPacket = true; @@ -120,7 +118,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final ConversationTracker conversationTracker = new ConversationTracker(); private final Set channels = new HashSet(); private final Map>> invertedVisibilityEntities = new HashMap<>(); -+ private final Set unlistedEntities = new HashSet<>(); // Paper ++ private final Set unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player private static final WeakHashMap> pluginWeakReferences = new WeakHashMap<>(); private int hash = 0; private double health = 20; @@ -129,7 +127,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // Paper end - this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer))); -+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer), this.getHandle())); // Paper ++ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer), this.getHandle())); // Paper - Add Listing API for Player if (original != null) otherPlayer.setUUID(original); // Paper - uuid override } @@ -137,7 +135,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return (entity != null) ? this.canSee(entity) : false; // If we can't find it, we can't see it } -+ // Paper start ++ // Paper start - Add Listing API for Player + @Override + public boolean isListed(Player other) { + return !this.unlistedEntities.contains(other.getUniqueId()); @@ -172,7 +170,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return false; + } + } -+ // Paper end ++ // Paper end - Add Listing API for Player + @Override public Map serialize() { diff --git a/patches/server/Add-PlayerPickItemEvent.patch b/patches/server/Add-PlayerPickItemEvent.patch index da8add7e2a..ee60f1e4d8 100644 --- a/patches/server/Add-PlayerPickItemEvent.patch +++ b/patches/server/Add-PlayerPickItemEvent.patch @@ -13,6 +13,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return; } - this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed + // Paper end ++ // Paper start - Add PlayerPickItemEvent + Player bukkitPlayer = this.player.getBukkitEntity(); + int targetSlot = this.player.getInventory().getSuitableHotbarSlot(); + int sourceSlot = packet.getSlot(); @@ -21,9 +23,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!event.callEvent()) return; + + this.player.getInventory().pickSlot(event.getSourceSlot(), event.getTargetSlot()); - // Paper end ++ // Paper end - Add PlayerPickItemEvent 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)); diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/player/Inventory.java @@ -39,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public void pickSlot(int slot, int targetSlot) { + this.selected = targetSlot; -+ // Paper end ++ // Paper end - Add PlayerPickItemEvent ItemStack itemstack = (ItemStack) this.items.get(this.selected); this.items.set(this.selected, (ItemStack) this.items.get(slot)); diff --git a/patches/server/Add-setting-for-proxy-online-mode-status.patch b/patches/server/Add-setting-for-proxy-online-mode-status.patch index e830cdc57c..09adab8b69 100644 --- a/patches/server/Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server/Add-setting-for-proxy-online-mode-status.patch @@ -5,6 +5,23 @@ Subject: [PATCH] Add setting for proxy online mode status TODO: Add isProxyOnlineMode check to Metrics +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + public boolean enforceSecureProfile() { + DedicatedServerProperties dedicatedserverproperties = this.getProperties(); + +- return dedicatedserverproperties.enforceSecureProfile && dedicatedserverproperties.onlineMode && this.services.canValidateProfileKeys(); ++ // Paper start - Add setting for proxy online mode status ++ return dedicatedserverproperties.enforceSecureProfile ++ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() ++ && this.services.canValidateProfileKeys(); ++ // Paper end - Add setting for proxy online mode status + } + + @Override diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java @@ -15,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (!org.apache.commons.lang3.StringUtils.isBlank(name)) // Paper - Don't lookup a profile with a blank name) + if (!org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name -+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL ++ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) // Paper - Add setting for proxy online mode status repository.findProfilesByNames(new String[]{name}, profilelookupcallback); GameProfile gameprofile = (GameProfile) atomicreference.get(); @@ -24,7 +41,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private static boolean usesAuthentication() { - return GameProfileCache.usesAuthentication; -+ return io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode(); // Paper ++ return io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode(); // Paper - Add setting for proxy online mode status } public void add(GameProfile profile) { @@ -38,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (server.usesAuthentication() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. + if (server.usesAuthentication() || -+ (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting ++ (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Add setting for proxy online mode status server.getProfileRepository().findProfilesByNames(astring, callback); } else { String[] astring1 = astring; @@ -51,7 +68,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 GameProfile profile = null; // Only fetch an online UUID in online mode - if (this.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. -+ if (this.getOnlineMode() || io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) { // Paper - Handle via setting ++ if (this.getOnlineMode() || io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) { // Paper - Add setting for proxy online mode status // This is potentially blocking :( profile = this.console.getProfileCache().get(name).orElse(null); } diff --git a/patches/server/Add-slot-sanity-checks-in-container-clicks.patch b/patches/server/Add-slot-sanity-checks-in-container-clicks.patch index 7be1ff03ca..da061b36f8 100644 --- a/patches/server/Add-slot-sanity-checks-in-container-clicks.patch +++ b/patches/server/Add-slot-sanity-checks-in-container-clicks.patch @@ -12,12 +12,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 break; case SWAP: if ((packet.getButtonNum() >= 0 && packet.getButtonNum() < 9) || packet.getButtonNum() == 40) { -+ // Paper start ++ // Paper start - Add slot sanity checks to container clicks + if (packet.getSlotNum() < 0) { + action = InventoryAction.NOTHING; + break; + } -+ // Paper end ++ // Paper end - Add slot sanity checks to container clicks click = (packet.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY; Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum()); if (clickedSlot.mayPickup(this.player)) { @@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.resetQuickCraft(); } } else if (this.quickcraftStatus == 1) { -+ if (slotIndex < 0) return; // Paper ++ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks slot = (Slot) this.slots.get(slotIndex); itemstack = this.getCarried(); if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { @@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 int j2; if (actionType == ClickType.SWAP && (button >= 0 && button < 9 || button == 40)) { -+ if (slotIndex < 0) return; // Paper ++ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks ItemStack itemstack4 = playerinventory.getItem(button); slot = (Slot) this.slots.get(slotIndex); diff --git a/patches/server/Add-titleOverride-to-InventoryOpenEvent.patch b/patches/server/Add-titleOverride-to-InventoryOpenEvent.patch index ab47d06d23..440c669b0b 100644 --- a/patches/server/Add-titleOverride-to-InventoryOpenEvent.patch +++ b/patches/server/Add-titleOverride-to-InventoryOpenEvent.patch @@ -12,18 +12,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.nextContainerCounter(); AbstractContainerMenu container = factory.createMenu(this.containerCounter, this.getInventory(), this); -+ Component title = null; // Paper ++ Component title = null; // Paper - Add titleOverride to InventoryOpenEvent // CraftBukkit start - Inventory open hook if (container != null) { container.setTitle(factory.getDisplayName()); boolean cancelled = false; - container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled); -+ // Paper start ++ // Paper start - Add titleOverride to InventoryOpenEvent + final com.mojang.datafixers.util.Pair result = CraftEventFactory.callInventoryOpenEventWithTitle(this, container, cancelled); + container = result.getSecond(); + title = PaperAdventure.asVanilla(result.getFirst()); -+ // Paper end ++ // Paper end - Add titleOverride to InventoryOpenEvent if (container == null && !cancelled) { // Let pre-cancelled events fall through // SPIGOT-5263 - close chest if cancelled if (factory instanceof Container) { @@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start this.containerMenu = container; - if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper -+ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper ++ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper - Add titleOverride to InventoryOpenEvent // CraftBukkit end this.initMenu(container); return OptionalInt.of(this.containerCounter); @@ -45,16 +45,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 AbstractContainerMenu container = new CraftContainer(inventory, player, player.nextContainerCounter()); - container = CraftEventFactory.callInventoryOpenEvent(player, container); -+ // Paper start ++ // Paper start - Add titleOverride to InventoryOpenEvent + final com.mojang.datafixers.util.Pair result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container); + container = result.getSecond(); -+ // Paper end ++ // Paper end - Add titleOverride to InventoryOpenEvent if (container == null) return; //String title = container.getBukkitView().getTitle(); // Paper - comment net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(container.getBukkitView().getTitle()); // Paper -+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper ++ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper @@ -63,10 +63,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Trigger an INVENTORY_OPEN event - container = CraftEventFactory.callInventoryOpenEvent(player, container); -+ // Paper start ++ // Paper start - Add titleOverride to InventoryOpenEvent + final com.mojang.datafixers.util.Pair result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container); + container = result.getSecond(); -+ // Paper end ++ // Paper end - Add titleOverride to InventoryOpenEvent if (container == null) { return; } @@ -74,7 +74,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 //String title = inventory.getTitle(); // Paper - comment net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper -+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper ++ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper player.containerMenu = container; @@ -87,21 +87,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container) { - return CraftEventFactory.callInventoryOpenEvent(player, container, false); -+ // Paper start ++ // Paper start - Add titleOverride to InventoryOpenEvent + return callInventoryOpenEventWithTitle(player, container).getSecond(); + } + public static com.mojang.datafixers.util.Pair callInventoryOpenEventWithTitle(ServerPlayer player, AbstractContainerMenu container) { + return CraftEventFactory.callInventoryOpenEventWithTitle(player, container, false); -+ // Paper end ++ // Paper end - Add titleOverride to InventoryOpenEvent } + @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - use method that acknowledges title overrides public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) { -+ // Paper start ++ // Paper start - Add titleOverride to InventoryOpenEvent + return callInventoryOpenEventWithTitle(player, container, cancelled).getSecond(); + } + public static com.mojang.datafixers.util.Pair callInventoryOpenEventWithTitle(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) { -+ // Paper end ++ // Paper end - Add titleOverride to InventoryOpenEvent if (player.containerMenu != player.inventoryMenu) { // fire INVENTORY_CLOSE if one already open player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper } @@ -110,11 +110,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (event.isCancelled()) { container.transferTo(player.containerMenu, craftPlayer); - return null; -+ return com.mojang.datafixers.util.Pair.of(null, null); // Paper - title override ++ return com.mojang.datafixers.util.Pair.of(null, null); // Paper - Add titleOverride to InventoryOpenEvent } - return container; -+ return com.mojang.datafixers.util.Pair.of(event.titleOverride(), container); // Paper - title override ++ return com.mojang.datafixers.util.Pair.of(event.titleOverride(), container); // Paper - Add titleOverride to InventoryOpenEvent } public static ItemStack callPreCraftEvent(Container matrix, Container resultInventory, ItemStack result, InventoryView lastCraftView, boolean isRepair) { diff --git a/patches/server/Add-whitelist-events.patch b/patches/server/Add-whitelist-events.patch index c0a6bb047e..ec6d0b23de 100644 --- a/patches/server/Add-whitelist-events.patch +++ b/patches/server/Add-whitelist-events.patch @@ -30,5 +30,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + super.remove(profile); + } -+ // Paper end ++ // Paper end - Add whitelist events } diff --git a/patches/server/Allow-trident-custom-damage.patch b/patches/server/Allow-trident-custom-damage.patch index ae30dd8712..0cb4968bf9 100644 --- a/patches/server/Allow-trident-custom-damage.patch +++ b/patches/server/Allow-trident-custom-damage.patch @@ -4,19 +4,6 @@ Date: Tue, 12 Jul 2022 18:01:14 +0200 Subject: [PATCH] Allow trident custom damage -diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -0,0 +0,0 @@ public abstract class AbstractArrow extends Projectile { - public AbstractArrow.Pickup pickup; - public int shakeTime; - public int life; -- private double baseDamage; -+ protected double baseDamage; // Paper - private -> protected - public int knockback; - public SoundEvent soundEvent; - @Nullable diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java @@ -25,12 +12,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public ThrownTrident(EntityType type, Level world) { super(type, world, ThrownTrident.DEFAULT_ARROW_STACK); -+ this.baseDamage = net.minecraft.world.item.TridentItem.BASE_DAMAGE; // Paper ++ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage } public ThrownTrident(Level world, LivingEntity owner, ItemStack stack) { super(EntityType.TRIDENT, owner, world, stack); -+ this.baseDamage = net.minecraft.world.item.TridentItem.BASE_DAMAGE; // Paper ++ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(stack)); this.entityData.set(ThrownTrident.ID_FOIL, stack.hasFoil()); } @@ -39,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected void onHitEntity(EntityHitResult entityHitResult) { Entity entity = entityHitResult.getEntity(); - float f = 8.0F; -+ float f = (float) this.baseDamage; // Paper ++ float f = (float) this.getBaseDamage(); // Paper - Allow trident custom damage if (entity instanceof LivingEntity) { LivingEntity entityliving = (LivingEntity) entity; diff --git a/patches/server/Cache-map-ids-on-item-frames.patch b/patches/server/Cache-map-ids-on-item-frames.patch index 6edea7d51f..1e510b2fce 100644 --- a/patches/server/Cache-map-ids-on-item-frames.patch +++ b/patches/server/Cache-map-ids-on-item-frames.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.level.paperConfig().maps.itemFrameCursorUpdateInterval > 0 && this.tickCount % this.level.paperConfig().maps.itemFrameCursorUpdateInterval == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks // Paper - Make item frame map cursor update interval configurable - Integer integer = MapItem.getMapId(itemstack); -+ Integer integer = entityitemframe.cachedMapId; // Paper ++ Integer integer = entityitemframe.cachedMapId; // Paper - Perf: Cache map ids on item frames MapItemSavedData worldmap = MapItem.getSavedData(integer, this.level); if (worldmap != null) { @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static final int NUM_ROTATIONS = 8; public float dropChance; public boolean fixed; -+ public Integer cachedMapId; // Paper ++ public Integer cachedMapId; // Paper - Perf: Cache map ids on item frames public ItemFrame(EntityType type, Level world) { super(type, world); @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } private void onItemChanged(ItemStack stack) { -+ this.cachedMapId = MapItem.getMapId(stack); // Paper ++ this.cachedMapId = MapItem.getMapId(stack); // Paper - Perf: Cache map ids on item frames if (!stack.isEmpty() && stack.getFrame() != this) { stack.setEntityRepresentation(this); } diff --git a/patches/server/Call-BlockRedstoneEvents-for-lecterns.patch b/patches/server/Call-BlockRedstoneEvents-for-lecterns.patch index 0f188e7927..a486597510 100644 --- a/patches/server/Call-BlockRedstoneEvents-for-lecterns.patch +++ b/patches/server/Call-BlockRedstoneEvents-for-lecterns.patch @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + } -+ // Paper end ++ // Paper end - call BlockRedstoneEvents for lecterns world.setBlock(pos, (BlockState) state.setValue(LecternBlock.POWERED, powered), 3); LecternBlock.updateBelow(world, pos, state); } diff --git a/patches/server/Configurable-Region-Compression-Format.patch b/patches/server/Configurable-Region-Compression-Format.patch index 4157d2444d..7571cfbbc0 100644 --- a/patches/server/Configurable-Region-Compression-Format.patch +++ b/patches/server/Configurable-Region-Compression-Format.patch @@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return stream; })); + -+ // Paper Start - Configurable region compression format ++ // Paper start - Configurable region compression format + public static RegionFileVersion getCompressionFormat() { + return switch (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.compressionFormat) { + case GZIP -> VERSION_GZIP; @@ -39,7 +39,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + case NONE -> VERSION_NONE; + }; + } -+ // Paper End ++ // Paper end - Configurable region compression format + private final int id; private final RegionFileVersion.StreamWrapper inputWrapper; diff --git a/patches/server/Configurable-entity-tracking-range-by-Y-coordinate.patch b/patches/server/Configurable-entity-tracking-range-by-Y-coordinate.patch index a5cf45ba8d..966452b86c 100644 --- a/patches/server/Configurable-entity-tracking-range-by-Y-coordinate.patch +++ b/patches/server/Configurable-entity-tracking-range-by-Y-coordinate.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); -+ // Paper start - check Y ++ // Paper start - Configurable entity tracking range by Y + if (flag && level.paperConfig().entities.trackingRangeY.enabled) { + double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1); + if (rangeY != -1) { @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + flag = vec3d_dy * vec3d_dy <= rangeY * rangeY; + } + } -+ // Paper end - check Y ++ // Paper end - Configurable entity tracking range by Y // CraftBukkit start - respect vanish API if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { diff --git a/patches/server/Configure-sniffer-egg-hatch-time.patch b/patches/server/Configure-sniffer-egg-hatch-time.patch index 1a4cc7aa8e..e0941e0d4d 100644 --- a/patches/server/Configure-sniffer-egg-hatch-time.patch +++ b/patches/server/Configure-sniffer-egg-hatch-time.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start private void rescheduleTick(ServerLevel world, BlockPos pos) { - int baseDelay = hatchBoost(world, pos) ? BOOSTED_HATCH_TIME_TICKS : REGULAR_HATCH_TIME_TICKS; -+ int baseDelay = hatchBoost(world, pos) ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); ++ int baseDelay = hatchBoost(world, pos) ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper - Configure sniffer egg hatch time world.scheduleTick(pos, this, (baseDelay / 3) + world.random.nextInt(RANDOM_HATCH_OFFSET_TICKS)); // reschedule to avoid being stuck here and behave like the other calls (see #onPlace) } diff --git a/patches/server/Deep-clone-unhandled-nbt-tags.patch b/patches/server/Deep-clone-unhandled-nbt-tags.patch index cfe289872f..d103734127 100644 --- a/patches/server/Deep-clone-unhandled-nbt-tags.patch +++ b/patches/server/Deep-clone-unhandled-nbt-tags.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private CompoundTag internalTag; - final Map unhandledTags = new TreeMap(); // Visible for testing only // Paper -+ Map unhandledTags = new TreeMap(); // Visible for testing only // Paper // Paper - remove final ++ Map unhandledTags = new TreeMap(); // Visible for testing only // Paper // Paper - Deep clone unhandled nbt tags; remove final private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftMetaItem.DATA_TYPE_REGISTRY); private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - Deep clone unhandled nbt tags + meta.unhandledTags.forEach((key, tag) -> this.unhandledTags.put(key, tag.copy())); + this.persistentDataContainer.putAll(meta.persistentDataContainer.getTagsCloned()); -+ // Paper end ++ // Paper end - Deep clone unhandled nbt tags this.internalTag = meta.internalTag; if (this.internalTag != null) { diff --git a/patches/server/Determine-lava-and-water-fluid-explosion-resistance-.patch b/patches/server/Determine-lava-and-water-fluid-explosion-resistance-.patch index 69a075738e..763d10e685 100644 --- a/patches/server/Determine-lava-and-water-fluid-explosion-resistance-.patch +++ b/patches/server/Determine-lava-and-water-fluid-explosion-resistance-.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override protected float getExplosionResistance() { - return 100.0F; -+ return Blocks.LAVA.getExplosionResistance(); // Paper ++ return Blocks.LAVA.getExplosionResistance(); // Paper - Get explosion resistance from actual block } @Override @@ -30,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override protected float getExplosionResistance() { - return 100.0F; -+ return Blocks.WATER.getExplosionResistance(); // Paper ++ return Blocks.WATER.getExplosionResistance(); // Paper - Get explosion resistance from actual block } @Override diff --git a/patches/server/Do-crystal-portal-proximity-check-before-entity-look.patch b/patches/server/Do-crystal-portal-proximity-check-before-entity-look.patch index 275c5c9c7d..7d29489006 100644 --- a/patches/server/Do-crystal-portal-proximity-check-before-entity-look.patch +++ b/patches/server/Do-crystal-portal-proximity-check-before-entity-look.patch @@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (enderdragonbattle != null) { - enderdragonbattle.tryRespawn(); -+ enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - pass placed end crystal position to pre-check proximity to portal ++ enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - Perf: Do crystal-portal proximity check before entity lookup } } @@ -41,12 +41,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public boolean tryRespawn() { // CraftBukkit - return boolean -+ // Paper start - pass null (indicating no placed end crystal involved) by default ++ // Paper start - Perf: Do crystal-portal proximity check before entity lookup + return this.tryRespawn(null); + } + + public boolean tryRespawn(@Nullable BlockPos placedEndCrystalPos) { // placedEndCrystalPos is null if the tryRespawn() call was not caused by a placed end crystal -+ // Paper end ++ // Paper end - Perf: Do crystal-portal proximity check before entity lookup if (this.dragonKilled && this.respawnStage == null) { BlockPos blockposition = this.portalLocation; @@ -54,7 +54,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 blockposition = this.portalLocation; } -+ // Paper start - check placed end crystal to portal proximity before attempting to respawn dragon ++ // Paper start - Perf: Do crystal-portal proximity check before entity lookup + if (placedEndCrystalPos != null) { + // The end crystal must be 0 or 1 higher than the portal origin + int dy = placedEndCrystalPos.getY() - blockposition.getY(); @@ -68,7 +68,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return false; + } + } -+ // Paper end ++ // Paper end - Perf: Do crystal-portal proximity check before entity lookup + List list = Lists.newArrayList(); BlockPos blockposition1 = blockposition.above(1); diff --git a/patches/server/Don-t-check-if-we-can-see-non-visible-entities.patch b/patches/server/Don-t-check-if-we-can-see-non-visible-entities.patch index da52622099..b9333db420 100644 --- a/patches/server/Don-t-check-if-we-can-see-non-visible-entities.patch +++ b/patches/server/Don-t-check-if-we-can-see-non-visible-entities.patch @@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end - check Y + // Paper end - Configurable entity tracking range by Y // CraftBukkit start - respect vanish API - if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { diff --git a/patches/server/Don-t-tab-complete-namespaced-commands-if-send-names.patch b/patches/server/Don-t-tab-complete-namespaced-commands-if-send-names.patch index a37f391b75..b35fd82657 100644 --- a/patches/server/Don-t-tab-complete-namespaced-commands-if-send-names.patch +++ b/patches/server/Don-t-tab-complete-namespaced-commands-if-send-names.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!org.spigotmc.SpigotConfig.sendNamespaced && suggestions.getRange().getStart() <= 1) { + suggestions.getList().removeIf(suggestion -> suggestion.getText().contains(":")); + } -+ // Paper end ++ // Paper end - Don't tab-complete namespaced commands if send-namespaced is false // Paper start - Brigadier API com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, command); suggestEvent.setCancelled(suggestions.isEmpty()); diff --git a/patches/server/Expand-Pose-API.patch b/patches/server/Expand-Pose-API.patch index a95695e16e..813da891b5 100644 --- a/patches/server/Expand-Pose-API.patch +++ b/patches/server/Expand-Pose-API.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @javax.annotation.Nullable private UUID originWorld; public boolean freezeLocked = false; // Paper - Freeze Tick Lock API -+ public boolean fixedPose = false; // Paper ++ public boolean fixedPose = false; // Paper - Expand Pose API public void setOrigin(@javax.annotation.Nonnull Location location) { this.origin = location.toVector(); @@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void onClientRemoval() {} public void setPose(net.minecraft.world.entity.Pose pose) { -+ if (this.fixedPose) return; // Paper ++ if (this.fixedPose) return; // Paper - Expand Pose API // CraftBukkit start if (pose == this.getPose()) { return; diff --git a/patches/server/ExperienceOrb-should-call-EntitySpawnEvent.patch b/patches/server/ExperienceOrb-should-call-EntitySpawnEvent.patch index 9ca95e1f0b..e3a04d5d50 100644 --- a/patches/server/ExperienceOrb-should-call-EntitySpawnEvent.patch +++ b/patches/server/ExperienceOrb-should-call-EntitySpawnEvent.patch @@ -13,10 +13,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) { double radius = world.spigotConfig.expMerge; - if (radius > 0) { -+ // Paper start - Call EntitySpawnEvent for ExperienceOrb entities. ++ // Paper start - Call EntitySpawnEvent for ExperienceOrb entities + event = CraftEventFactory.callEntitySpawnEvent(entity); + if (radius > 0 && !event.isCancelled() && !entity.isRemoved()) { -+ // Paper end ++ // Paper end - Call EntitySpawnEvent for ExperienceOrb entities // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics final int maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue; final boolean mergeUnconditionally = world.paperConfig().entities.behavior.experienceMergeMaxValue <= 0; diff --git a/patches/server/Expose-hand-during-BlockCanBuildEvent.patch b/patches/server/Expose-hand-in-BlockCanBuildEvent.patch similarity index 94% rename from patches/server/Expose-hand-during-BlockCanBuildEvent.patch rename to patches/server/Expose-hand-in-BlockCanBuildEvent.patch index 1692342128..f6f5563982 100644 --- a/patches/server/Expose-hand-during-BlockCanBuildEvent.patch +++ b/patches/server/Expose-hand-in-BlockCanBuildEvent.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: The456gamer Date: Mon, 21 Aug 2023 14:13:42 +0100 -Subject: [PATCH] Expose hand during BlockCanBuildEvent +Subject: [PATCH] Expose hand in BlockCanBuildEvent diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); -+ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - expose hand ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent context.getLevel().getCraftServer().getPluginManager().callEvent(event); return event.isBuildable(); @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); -+ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - expose hand ++ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent context.getLevel().getCraftServer().getPluginManager().callEvent(event); return (event.isBuildable()) ? iblockdata1 : null; diff --git a/patches/server/Fire-entity-death-event-for-ender-dragon.patch b/patches/server/Fire-entity-death-event-for-ender-dragon.patch index 0b6e9b1560..18d2fe6365 100644 --- a/patches/server/Fire-entity-death-event-for-ender-dragon.patch +++ b/patches/server/Fire-entity-death-event-for-ender-dragon.patch @@ -12,14 +12,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void kill() { -+ // Paper start ++ // Paper start - Fire entity death event + this.silentDeath = true; + org.bukkit.event.entity.EntityDeathEvent deathEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this); + if (deathEvent.isCancelled()) { + this.silentDeath = false; // Reset to default if event was cancelled + return; + } -+ // Paper end ++ // Paper end - Fire entity death event + this.remove(Entity.RemovalReason.KILLED); this.gameEvent(GameEvent.ENTITY_DIE); diff --git a/patches/server/Fix-NPE-on-Boat-getStatus.patch b/patches/server/Fix-NPE-on-Boat-getStatus.patch index 03913bcaf5..5b53d219b3 100644 --- a/patches/server/Fix-NPE-on-Boat-getStatus.patch +++ b/patches/server/Fix-NPE-on-Boat-getStatus.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Status getStatus() { -+ // Paper start ++ // Paper start - Fix NPE on Boat getStatus + final net.minecraft.world.entity.vehicle.Boat handle = this.getHandle(); + if (handle.status == null) { + if (handle.valid && !handle.updatingSectionStatus) { @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return Status.NOT_IN_WORLD; + } + } -+ // Paper end ++ // Paper end - Fix NPE on Boat getStatus return CraftBoat.boatStatusFromNms(this.getHandle().status); } diff --git a/patches/server/Implement-PlayerFailMoveEvent.patch b/patches/server/Implement-PlayerFailMoveEvent.patch index 1697aec17c..837d5809b8 100644 --- a/patches/server/Implement-PlayerFailMoveEvent.patch +++ b/patches/server/Implement-PlayerFailMoveEvent.patch @@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet()); + return; + } -+ // Paper end ++ // Paper end - Add fail move event } // Paper end @@ -52,7 +52,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot()); + return; + } -+ // Paper end ++ // Paper end - Add fail move event } } } @@ -68,7 +68,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (event.getLogWarning()) ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString()); + } -+ // Paper end ++ // Paper end - Add fail move event } // Paper start - optimise out extra getCubes @@ -84,7 +84,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + teleportBack = false; + } + } -+ // Paper end ++ // Paper end - Add fail move event } // else: no collision at all detected, why do we care? } if (!this.player.noPhysics && !this.player.isSleeping() && teleportBack) { // Paper end - optimise out extra getCubes @@ -103,7 +103,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + event.callEvent(); + return event; + } -+ // Paper end ++ // Paper end - Add fail move event // Paper start - optimise out extra getCubes private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) { final List collisionsBB = new java.util.ArrayList<>(); diff --git a/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch b/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch index 4ccf8da729..8f48530d30 100644 --- a/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch +++ b/patches/server/Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch @@ -80,11 +80,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ // Paper start - mob count backoff ++ // Paper start - per player mob count backoff + if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) { + world.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(blockposition_mutableblockposition.getX() >> 4, blockposition_mutableblockposition.getZ() >> 4, group); + } -+ // Paper end - mob count backoff ++ // Paper end - per player mob count backoff if (doSpawning == PreSpawnStatus.ABORT) { return j; // Paper } diff --git a/patches/server/Make-Amethyst-throw-both-Spread-and-Grow-Events.patch b/patches/server/Make-Amethyst-throw-both-Spread-and-Grow-Events.patch index 3e0edad602..f91d7b57c4 100644 --- a/patches/server/Make-Amethyst-throw-both-Spread-and-Grow-Events.patch +++ b/patches/server/Make-Amethyst-throw-both-Spread-and-Grow-Events.patch @@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } else { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, blockposition1, iblockdata2); + } -+ // Paper end ++ // Paper end - Have Amethyst throw both spread and grow events } } diff --git a/patches/server/More-DragonBattle-API.patch b/patches/server/More-DragonBattle-API.patch index 4879c74868..d2b939a4b5 100644 --- a/patches/server/More-DragonBattle-API.patch +++ b/patches/server/More-DragonBattle-API.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.gateways.clear(); } -+ // Paper start ++ // Paper start - More DragonBattle API + public boolean spawnNewGatewayIfPossible() { + if (!this.gateways.isEmpty()) { + this.spawnNewGateway(); @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + return endCrystals; + } -+ // Paper end ++ // Paper end - More DragonBattle API + private void spawnNewGateway() { if (!this.gateways.isEmpty()) { @@ -46,7 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private DragonRespawnAnimation toNMSRespawnPhase(RespawnPhase phase) { return (phase != RespawnPhase.NONE) ? DragonRespawnAnimation.values()[phase.ordinal()] : null; } -+ // Paper start ++ // Paper start - More DragonBattle API + @Override + public int getGatewayCount() { + return EndDragonFight.GATEWAY_COUNT - this.handle.gateways.size(); @@ -87,5 +87,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + return java.util.Collections.unmodifiableList(enderCrystals); + } -+ // Paper end ++ // Paper end - More DragonBattle API } diff --git a/patches/server/Optimise-nearby-player-retrieval.patch b/patches/server/Optimise-nearby-player-retrieval.patch index f50e37ded7..45d3c3df88 100644 --- a/patches/server/Optimise-nearby-player-retrieval.patch +++ b/patches/server/Optimise-nearby-player-retrieval.patch @@ -127,6 +127,73 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +@@ -0,0 +0,0 @@ public class PlayerSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- List list = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((player) -> { +- return entity.closerThan(player, 16.0D); +- }).sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList()); ++ // Paper start - Perf: optimise nearby player retrieval & remove streams from hot code ++ io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = world.chunkSource.chunkMap.getNearbyPlayers(); ++ net.minecraft.world.phys.Vec3 entityPos = entity.position(); ++ com.destroystokyo.paper.util.maplist.ReferenceList nearby = nearbyPlayers.getPlayersByChunk( ++ entity.chunkPosition().x, ++ entity.chunkPosition().z, ++ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL_REALLY_SMALL ++ ); ++ ++ List players = new java.util.ArrayList<>(nearby == null ? 0 : nearby.size()); ++ if (nearby != null) { ++ Object[] rawData = nearby.getRawData(); ++ for (int index = 0, len = nearby.size(); index < len; ++index) { ++ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) rawData[index]; ++ if (player.isSpectator()) { ++ continue; ++ } ++ if (player.distanceToSqr(entityPos.x, entityPos.y, entityPos.z) >= (16.0 * 16.0)) { ++ continue; ++ } ++ players.add(player); ++ } ++ } ++ players.sort(Comparator.comparingDouble(entity::distanceToSqr)); + Brain brain = entity.getBrain(); +- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list); +- List list2 = list.stream().filter((player) -> { +- return isEntityTargetable(entity, player); +- }).collect(Collectors.toList()); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0)); +- Optional optional = list2.stream().filter((player) -> { +- return isEntityAttackable(entity, player); +- }).findFirst(); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional); ++ ++ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); ++ ++ Player firstTargetable = null; ++ Player firstAttackable = null; ++ for (Player player : players) { ++ if (firstTargetable == null && Sensor.isEntityTargetable(entity, player)) { ++ firstTargetable = player; ++ } ++ if (firstAttackable == null && Sensor.isEntityAttackable(entity, player)) { ++ firstAttackable = player; ++ } ++ ++ if (firstAttackable != null && firstTargetable != null) { ++ break; ++ } ++ } ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, firstTargetable); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, Optional.ofNullable(firstAttackable)); ++ // Paper end - Perf: optimise nearby player retrieval & remove streams from hot code + } + } diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java diff --git a/patches/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch index 98105a3370..5b75adc6eb 100644 --- a/patches/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ b/patches/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -3,7 +3,6 @@ From: Aikar Date: Tue, 4 Aug 2020 22:24:15 +0200 Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections -1.17 Update: Please do this k thx bb I utilized the IDE to convert streams to non streams code, so shouldn't be any risk of behavior change. Only did minor optimization of the generated code set to remove unnecessary things. diff --git a/patches/server/Optimize-nearest-structure-border-iteration.patch b/patches/server/Optimize-nearest-structure-border-iteration.patch index 909d5286b5..9c95ed5e31 100644 --- a/patches/server/Optimize-nearest-structure-border-iteration.patch +++ b/patches/server/Optimize-nearest-structure-border-iteration.patch @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (flag1 || flag2) { + // if (flag1 || flag2) { + if (true) { -+ // Paper end ++ // Paper end - iterate over border chunks instead of entire square chunk area int l1 = centerChunkX + i1 * j1; int i2 = centerChunkZ + i1 * k1; ChunkPos chunkcoordintpair = placement.getPotentialStructureChunk(seed, l1, i2); diff --git a/patches/server/Properly-handle-BlockBreakEvent-isDropItems.patch b/patches/server/Properly-handle-BlockBreakEvent-isDropItems.patch index a98cd52cc4..afa54a360f 100644 --- a/patches/server/Properly-handle-BlockBreakEvent-isDropItems.patch +++ b/patches/server/Properly-handle-BlockBreakEvent-isDropItems.patch @@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items - block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1); + if (flag && flag1/* && event.isDropItems() */) { // CraftBukkit - Check if block should drop items // Paper - fix drops not preventing stats/food exhaustion -+ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems(), false); // Paper ++ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems(), false); // Paper - fix drops not preventing stats/food exhaustion } // return true; // CraftBukkit @@ -33,8 +33,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override - public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(world, player, pos, state, blockEntity, tool); -+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper -+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper ++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion ++ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion if (!world.isClientSide && blockEntity instanceof BeehiveBlockEntity) { BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) blockEntity; @@ -46,18 +46,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.defaultBlockState(); } -+ @io.papermc.paper.annotation.DoNotUse // Paper - method below allows better control of item drops ++ @io.papermc.paper.annotation.DoNotUse // Paper - fix drops not preventing stats/food exhaustion public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { -+ // Paper start ++ // Paper start - fix drops not preventing stats/food exhaustion + this.playerDestroy(world, player, pos, state, blockEntity, tool, true, true); + } + public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { -+ // Paper end ++ // Paper end - fix drops not preventing stats/food exhaustion player.awardStat(Stats.BLOCK_MINED.get(this)); player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent -+ if (includeDrops) { // Paper ++ if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion Block.dropResources(state, world, pos, blockEntity, player, tool); -+ } // Paper ++ } // Paper - fix drops not preventing stats/food exhaustion } public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {} @@ -71,8 +71,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override - public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool); -+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper -+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper ++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion ++ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion } protected static void preventDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) { @@ -86,8 +86,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override - public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(world, player, pos, state, blockEntity, tool); -+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper -+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper ++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion ++ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion // Paper start this.afterDestroy(world, pos, tool); } @@ -101,8 +101,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override - public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) { - super.playerDestroy(world, player, pos, state, blockEntity, tool); -+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper -+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper ++ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion ++ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion this.decreaseEggs(world, pos, state); } diff --git a/patches/server/Properly-handle-experience-dropping-on-block-break.patch b/patches/server/Properly-handle-experience-dropping-on-block-break.patch index bda0098818..9f5b3f83b0 100644 --- a/patches/server/Properly-handle-experience-dropping-on-block-break.patch +++ b/patches/server/Properly-handle-experience-dropping-on-block-break.patch @@ -61,10 +61,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike { player.awardStat(Stats.BLOCK_MINED.get(this)); player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent - if (includeDrops) { // Paper + if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion - Block.dropResources(state, world, pos, blockEntity, player, tool); + Block.dropResources(state, world, pos, blockEntity, player, tool, dropExp); // Paper - Properly handle xp dropping - } // Paper + } // Paper - fix drops not preventing stats/food exhaustion } diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java diff --git a/patches/server/Remove-some-streams-from-structures.patch b/patches/server/Remove-some-streams-from-structures.patch deleted file mode 100644 index 30a17bfd21..0000000000 --- a/patches/server/Remove-some-streams-from-structures.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Mon, 29 Jun 2020 17:03:06 -0400 -Subject: [PATCH] Remove some streams from structures - -This showed up a lot in the spark profiler, should have a low-medium performance improvement. - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java -@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker { - int j = pos.getMinBlockZ(); - ObjectList objectList = new ObjectArrayList<>(10); - ObjectList objectList2 = new ObjectArrayList<>(32); -- world.startsForStructure(pos, (structure) -> { -+ // Paper start - replace for each -+ for (net.minecraft.world.level.levelgen.structure.StructureStart start : world.startsForStructure(pos, (structure) -> { - return structure.terrainAdaptation() != TerrainAdjustment.NONE; -- }).forEach((start) -> { -+ })) { // Paper end - TerrainAdjustment terrainAdjustment = start.getStructure().terrainAdaptation(); - - for(StructurePiece structurePiece : start.getPieces()) { -@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker { - } - - for(JigsawJunction jigsawJunction : poolElementStructurePiece.getJunctions()) { -- int i = jigsawJunction.getSourceX(); -- int j = jigsawJunction.getSourceZ(); -- if (i > i - 12 && j > j - 12 && i < i + 15 + 12 && j < j + 15 + 12) { -+ // Paper start - decompile fix -+ int i2 = jigsawJunction.getSourceX(); -+ int j2 = jigsawJunction.getSourceZ(); -+ if (i2 > i - 12 && j2 > j - 12 && i2 < i + 15 + 12 && j2 < j + 15 + 12) { -+ // Paper end - objectList2.add(jigsawJunction); - } - } -@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker { - } - } - -- }); -+ } // Paper - return new Beardifier(objectList.iterator(), objectList2.iterator()); - } - diff --git a/patches/server/Remove-streams-for-villager-AI.patch b/patches/server/Remove-streams-for-villager-AI.patch deleted file mode 100644 index a77b074426..0000000000 --- a/patches/server/Remove-streams-for-villager-AI.patch +++ /dev/null @@ -1,210 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 27 Aug 2020 20:51:40 -0700 -Subject: [PATCH] Remove streams for villager AI - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java -@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl - if (this.hasRequiredMemories(entity)) { - this.status = Behavior.Status.RUNNING; - this.orderPolicy.apply(this.behaviors); -- this.runningPolicy.apply(this.behaviors.stream(), world, entity, time); -+ this.runningPolicy.apply(this.behaviors.entries, world, entity, time); // Paper - Remove streams - return true; - } else { - return false; -@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl - - @Override - public final void tickOrStop(ServerLevel world, E entity, long time) { -- this.behaviors.stream().filter((task) -> { -- return task.getStatus() == Behavior.Status.RUNNING; -- }).forEach((task) -> { -- task.tickOrStop(world, entity, time); -- }); -+ // Paper start - Remove streams -+ for (BehaviorControl task : this.behaviors) { -+ if (task.getStatus() == Behavior.Status.RUNNING) { -+ task.tickOrStop(world, entity, time); -+ } -+ } -+ // Paper end - Remove streams - if (this.behaviors.stream().noneMatch((task) -> { - return task.getStatus() == Behavior.Status.RUNNING; - })) { -@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl - @Override - public final void doStop(ServerLevel world, E entity, long time) { - this.status = Behavior.Status.STOPPED; -- this.behaviors.stream().filter((task) -> { -- return task.getStatus() == Behavior.Status.RUNNING; -- }).forEach((task) -> { -- task.doStop(world, entity, time); -- }); -+ // Paper start - Remove streams -+ for (BehaviorControl behavior : this.behaviors) { -+ if (behavior.getStatus() == Behavior.Status.RUNNING) { -+ behavior.doStop(world, entity, time); -+ } -+ } -+ // Paper end - Remove streams - this.exitErasedMemories.forEach(entity.getBrain()::eraseMemory); - } - -@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl - public static enum RunningPolicy { - RUN_ONE { - @Override -- public void apply(Stream> tasks, ServerLevel world, E entity, long time) { -- tasks.filter((task) -> { -- return task.getStatus() == Behavior.Status.STOPPED; -- }).filter((task) -> { -- return task.tryStart(world, entity, time); -- }).findFirst(); -+ // Paper start - Remove streams -+ public void apply(List>> tasks, ServerLevel world, E entity, long time) { -+ for (ShufflingList.WeightedEntry> task : tasks) { -+ final BehaviorControl behavior = task.getData(); -+ if (behavior.getStatus() == Behavior.Status.STOPPED && behavior.tryStart(world, entity, time)) { -+ break; -+ } -+ } -+ // Paper end - Remove streams - } - }, - TRY_ALL { - @Override -- public void apply(Stream> tasks, ServerLevel world, E entity, long time) { -- tasks.filter((task) -> { -- return task.getStatus() == Behavior.Status.STOPPED; -- }).forEach((task) -> { -- task.tryStart(world, entity, time); -- }); -+ // Paper start - Remove streams -+ public void apply(List>> tasks, ServerLevel world, E entity, long time) { -+ for (ShufflingList.WeightedEntry> task : tasks) { -+ final BehaviorControl behavior = task.getData(); -+ if (behavior.getStatus() == Behavior.Status.STOPPED) { -+ behavior.tryStart(world, entity, time); -+ } -+ } -+ // Paper end - Remove streams - } - }; - -- public abstract void apply(Stream> tasks, ServerLevel world, E entity, long time); -+ public abstract void apply(List>> tasks, ServerLevel world, E entity, long time); // Paper - Remove streams - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java -@@ -0,0 +0,0 @@ import java.util.stream.Stream; - import net.minecraft.util.RandomSource; - - public class ShufflingList implements Iterable { -- protected final List> entries; -+ public final List> entries; // Paper - public - private final RandomSource random = RandomSource.create(); - private final boolean isUnsafe; // Paper - -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -@@ -0,0 +0,0 @@ public class NearestItemSensor extends Sensor { - protected void doTick(ServerLevel world, Mob entity) { - Brain brain = entity.getBrain(); - List list = world.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(32.0D, 16.0D, 32.0D), (itemEntity) -> { -- return true; -+ return itemEntity.closerThan(entity, MAX_DISTANCE_TO_WANTED_ITEM) && entity.wantsToPickUp(itemEntity.getItem()); // Paper - move predicate into getEntities - }); -- list.sort(Comparator.comparingDouble(entity::distanceToSqr)); -+ list.sort((e1, e2) -> Double.compare(entity.distanceToSqr(e1), entity.distanceToSqr(e2))); // better to take the sort perf hit than using line of sight more than we need to. -+ // Paper start - Remove streams - // Paper start - remove streams in favour of lists - ItemEntity nearest = null; -- for (ItemEntity entityItem : list) { -- if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 32.0D) && entity.hasLineOfSight(entityItem)) { -+ for (int i = 0; i < list.size(); i++) { -+ ItemEntity entityItem = list.get(i); -+ if (entity.hasLineOfSight(entityItem)) { -+ // Paper end - Remove streams - nearest = entityItem; - break; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -@@ -0,0 +0,0 @@ public class PlayerSensor extends Sensor { - - @Override - protected void doTick(ServerLevel world, LivingEntity entity) { -- List players = new java.util.ArrayList<>(world.players()); -- players.removeIf(player -> !EntitySelector.NO_SPECTATORS.test(player) || !entity.closerThan(player, 16.0D)); -- players.sort(Comparator.comparingDouble(entity::distanceTo)); -+ // Paper start - remove streams -+ io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = world.chunkSource.chunkMap.getNearbyPlayers(); -+ net.minecraft.world.phys.Vec3 entityPos = entity.position(); -+ com.destroystokyo.paper.util.maplist.ReferenceList nearby = nearbyPlayers.getPlayersByChunk( -+ entity.chunkPosition().x, -+ entity.chunkPosition().z, -+ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL_REALLY_SMALL -+ ); -+ -+ List players = new java.util.ArrayList<>(nearby == null ? 0 : nearby.size()); -+ if (nearby != null) { -+ Object[] rawData = nearby.getRawData(); -+ for (int index = 0, len = nearby.size(); index < len; ++index) { -+ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer)rawData[index]; -+ if (player.isSpectator()) { -+ continue; -+ } -+ if (player.distanceToSqr(entityPos.x, entityPos.y, entityPos.z) >= (16.0 * 16.0)) { -+ continue; -+ } -+ players.add((Player)player); -+ } -+ } -+ players.sort((e1, e2) -> Double.compare(entity.distanceToSqr(e1), entity.distanceToSqr(e2))); - Brain brain = entity.getBrain(); - - brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); - -- Player nearest = null, nearestTargetable = null; -- for (Player player : players) { -- if (Sensor.isEntityTargetable(entity, player)) { -- if (nearest == null) nearest = player; -- if (Sensor.isEntityAttackable(entity, player)) { -- nearestTargetable = player; -- break; // Both variables are assigned, no reason to loop further -- } -+ Player firstTargetable = null; -+ Player firstAttackable = null; -+ for (int index = 0, len = players.size(); index < len; ++index) { -+ Player player = players.get(index); -+ if (firstTargetable == null && isEntityTargetable(entity, player)) { -+ firstTargetable = player; -+ } -+ if (firstAttackable == null && isEntityAttackable(entity, player)) { -+ firstAttackable = player; -+ } -+ -+ if (firstAttackable != null && firstTargetable != null) { -+ break; - } - } -- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, nearestTargetable); -- // Paper end -+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, firstTargetable); -+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, Optional.ofNullable(firstAttackable)); -+ // Paper end - remove streams - } - } diff --git a/patches/server/Remove-streams-from-SensorNearest.patch b/patches/server/Remove-streams-from-SensorNearest.patch deleted file mode 100644 index afbe279aee..0000000000 --- a/patches/server/Remove-streams-from-SensorNearest.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Bjarne Koll -Date: Wed, 3 Mar 2021 12:48:48 +0100 -Subject: [PATCH] Remove streams from SensorNearest - -The behavioural nearby sensors are validated every tick on the entities -that registered the respective sensors and are therefore a good subject -to performance improvements. - -More specifically this commit replaces the Stream#filter usage with -ArrayList#removeIf as the removeIf method on an array list is heavily -optimized towards a single internal array re-allocation without any -further overhead on the removeIf call. - -The only negative of this change is the rather agressive diff these -patches introduce as the methods are basically being reimplemented -compared to the previous stream-based implementation. - -See: https://nipafx.dev/java-stream-performance/ - -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -@@ -0,0 +0,0 @@ public class NearestItemSensor extends Sensor { - return true; - }); - list.sort(Comparator.comparingDouble(entity::distanceToSqr)); -- Optional optional = list.stream().filter((itemEntity) -> { -- return entity.wantsToPickUp(itemEntity.getItem()); -- }).filter((itemEntity) -> { -- return itemEntity.closerThan(entity, 32.0D); -- }).filter(entity::hasLineOfSight).findFirst(); -- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); -+ // Paper start - remove streams in favour of lists -+ ItemEntity nearest = null; -+ for (ItemEntity entityItem : list) { -+ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 32.0D) && entity.hasLineOfSight(entityItem)) { -+ nearest = entityItem; -+ break; -+ } -+ } -+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -@@ -0,0 +0,0 @@ public class PlayerSensor extends Sensor { - - @Override - protected void doTick(ServerLevel world, LivingEntity entity) { -- List list = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((player) -> { -- return entity.closerThan(player, 16.0D); -- }).sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList()); -+ List players = new java.util.ArrayList<>(world.players()); -+ players.removeIf(player -> !EntitySelector.NO_SPECTATORS.test(player) || !entity.closerThan(player, 16.0D)); -+ players.sort(Comparator.comparingDouble(entity::distanceTo)); - Brain brain = entity.getBrain(); -- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list); -- List list2 = list.stream().filter((player) -> { -- return isEntityTargetable(entity, player); -- }).collect(Collectors.toList()); -- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0)); -- Optional optional = list2.stream().filter((player) -> { -- return isEntityAttackable(entity, player); -- }).findFirst(); -- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional); -+ -+ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); -+ -+ Player nearest = null, nearestTargetable = null; -+ for (Player player : players) { -+ if (Sensor.isEntityTargetable(entity, player)) { -+ if (nearest == null) nearest = player; -+ if (Sensor.isEntityAttackable(entity, player)) { -+ nearestTargetable = player; -+ break; // Both variables are assigned, no reason to loop further -+ } -+ } -+ } -+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, nearestTargetable); -+ // Paper end - } - } diff --git a/patches/server/Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/Remove-streams-from-classes-related-villager-gossip.patch deleted file mode 100644 index c0ae3bba9f..0000000000 --- a/patches/server/Remove-streams-from-classes-related-villager-gossip.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Wed, 1 Jul 2020 18:01:49 -0400 -Subject: [PATCH] Remove streams from classes related villager gossip - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -0,0 +0,0 @@ public class GossipContainer { - }); - } - -+ // Paper start - Remove streams from reputation -+ private List decompress() { -+ List list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); -+ for (Map.Entry entry : this.gossips.entrySet()) { -+ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) { -+ if (cur.weightedValue() != 0) { -+ list.add(cur); -+ } -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - private Collection selectGossipsForTransfer(RandomSource random, int count) { -- List list = this.unpack().toList(); -+ List list = this.decompress(); // Paper - Remove streams from reputation - if (list.isEmpty()) { - return Collections.emptyList(); - } else { -@@ -0,0 +0,0 @@ public class GossipContainer { - } - - public T store(DynamicOps ops) { -- return GossipContainer.GossipEntry.LIST_CODEC.encodeStart(ops, this.unpack().toList()).resultOrPartial((error) -> { -+ return GossipContainer.GossipEntry.LIST_CODEC.encodeStart(ops, this.decompress()).resultOrPartial((error) -> { - LOGGER.warn("Failed to serialize gossips: {}", (Object)error); - }).orElseGet(ops::emptyList); - } -@@ -0,0 +0,0 @@ public class GossipContainer { - final Object2IntMap entries = new Object2IntOpenHashMap<>(); - - public int weightedValue(Predicate gossipTypeFilter) { -- return this.entries.object2IntEntrySet().stream().filter((entry) -> { -- return gossipTypeFilter.test(entry.getKey()); -- }).mapToInt((entry) -> { -- return entry.getIntValue() * (entry.getKey()).weight; -- }).sum(); -+ // Paper start - Remove streams from reputation -+ int weight = 0; -+ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { -+ if (gossipTypeFilter.test(entry.getKey())) { -+ weight += entry.getIntValue() * entry.getKey().weight; -+ } -+ } -+ return weight; -+ } -+ -+ public List decompress(UUID uuid) { -+ List list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); -+ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { -+ list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue())); -+ } -+ return list; -+ // Paper end - } - - public Stream unpack(UUID target) { diff --git a/patches/server/Remove-streams-from-hot-code.patch b/patches/server/Remove-streams-from-hot-code.patch new file mode 100644 index 0000000000..19518bdb37 --- /dev/null +++ b/patches/server/Remove-streams-from-hot-code.patch @@ -0,0 +1,244 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josh Roy <10731363+JRoy@users.noreply.github.com> +Date: Wed, 1 Jul 2020 18:01:49 -0400 +Subject: [PATCH] Remove streams from hot code + +Co-authored-by: Bjarne Koll +Co-authored-by: Spottedleaf + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl + if (this.hasRequiredMemories(entity)) { + this.status = Behavior.Status.RUNNING; + this.orderPolicy.apply(this.behaviors); +- this.runningPolicy.apply(this.behaviors.stream(), world, entity, time); ++ this.runningPolicy.apply(this.behaviors, world, entity, time); // Paper - Perf: Remove streams from hot code + return true; + } else { + return false; +@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl + + @Override + public final void tickOrStop(ServerLevel world, E entity, long time) { +- this.behaviors.stream().filter((task) -> { +- return task.getStatus() == Behavior.Status.RUNNING; +- }).forEach((task) -> { +- task.tickOrStop(world, entity, time); +- }); ++ // Paper start - Perf: Remove streams from hot code ++ for (final BehaviorControl task : this.behaviors) { ++ if (task.getStatus() == Behavior.Status.RUNNING) { ++ task.tickOrStop(world, entity, time); ++ } ++ } ++ // Paper end - Perf: Remove streams from hot code + if (this.behaviors.stream().noneMatch((task) -> { + return task.getStatus() == Behavior.Status.RUNNING; + })) { +@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl + @Override + public final void doStop(ServerLevel world, E entity, long time) { + this.status = Behavior.Status.STOPPED; +- this.behaviors.stream().filter((task) -> { +- return task.getStatus() == Behavior.Status.RUNNING; +- }).forEach((task) -> { +- task.doStop(world, entity, time); +- }); +- this.exitErasedMemories.forEach(entity.getBrain()::eraseMemory); ++ // Paper start - Perf: Remove streams from hot code ++ for (final BehaviorControl task : this.behaviors) { ++ if (task.getStatus() == Behavior.Status.RUNNING) { ++ task.doStop(world, entity, time); ++ } ++ } ++ for (final MemoryModuleType exitErasedMemory : this.exitErasedMemories) { ++ entity.getBrain().eraseMemory(exitErasedMemory); ++ } ++ // Paper end - Perf: Remove streams from hot code + } + + @Override +@@ -0,0 +0,0 @@ public class GateBehavior implements BehaviorControl + + public static enum RunningPolicy { + RUN_ONE { ++ // Paper start - Perf: Remove streams from hot code + @Override +- public void apply(Stream> tasks, ServerLevel world, E entity, long time) { +- tasks.filter((task) -> { +- return task.getStatus() == Behavior.Status.STOPPED; +- }).filter((task) -> { +- return task.tryStart(world, entity, time); +- }).findFirst(); ++ public void apply(ShufflingList> tasks, ServerLevel world, E entity, long time) { ++ for (final BehaviorControl task : tasks) { ++ if (task.getStatus() == Behavior.Status.STOPPED && task.tryStart(world, entity, time)) { ++ break; ++ } ++ } ++ // Paper end - Perf: Remove streams from hot code + } + }, + TRY_ALL { ++ // Paper start - Perf: Remove streams from hot code + @Override +- public void apply(Stream> tasks, ServerLevel world, E entity, long time) { +- tasks.filter((task) -> { +- return task.getStatus() == Behavior.Status.STOPPED; +- }).forEach((task) -> { +- task.tryStart(world, entity, time); +- }); ++ public void apply(ShufflingList> tasks, ServerLevel world, E entity, long time) { ++ for (final BehaviorControl task : tasks) { ++ if (task.getStatus() == Behavior.Status.STOPPED) { ++ task.tryStart(world, entity, time); ++ } ++ } ++ // Paper end - Perf: Remove streams from hot code + } + }; + +- public abstract void apply(Stream> tasks, ServerLevel world, E entity, long time); ++ public abstract void apply(ShufflingList> tasks, ServerLevel world, E entity, long time); // Paper - Perf: Remove streams from hot code + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -0,0 +0,0 @@ public class GossipContainer { + }); + } + ++ // Paper start - Perf: Remove streams from hot code ++ private List decompress() { ++ List list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); ++ for (Map.Entry entry : this.gossips.entrySet()) { ++ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) { ++ if (cur.weightedValue() != 0) { ++ list.add(cur); ++ } ++ } ++ } ++ return list; ++ } ++ // Paper end - Perf: Remove streams from hot code ++ + private Collection selectGossipsForTransfer(RandomSource random, int count) { +- List list = this.unpack().toList(); ++ List list = this.decompress(); // Paper - Perf: Remove streams from hot code + if (list.isEmpty()) { + return Collections.emptyList(); + } else { +@@ -0,0 +0,0 @@ public class GossipContainer { + } + + public T store(DynamicOps ops) { +- return GossipContainer.GossipEntry.LIST_CODEC.encodeStart(ops, this.unpack().toList()).resultOrPartial((error) -> { ++ return GossipContainer.GossipEntry.LIST_CODEC.encodeStart(ops, this.decompress()).resultOrPartial((error) -> { // Paper - Perf: Remove streams from hot code + LOGGER.warn("Failed to serialize gossips: {}", (Object)error); + }).orElseGet(ops::emptyList); + } +@@ -0,0 +0,0 @@ public class GossipContainer { + final Object2IntMap entries = new Object2IntOpenHashMap<>(); + + public int weightedValue(Predicate gossipTypeFilter) { +- return this.entries.object2IntEntrySet().stream().filter((entry) -> { +- return gossipTypeFilter.test(entry.getKey()); +- }).mapToInt((entry) -> { +- return entry.getIntValue() * (entry.getKey()).weight; +- }).sum(); ++ // Paper start - Perf: Remove streams from hot code ++ int weight = 0; ++ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { ++ if (gossipTypeFilter.test(entry.getKey())) { ++ weight += entry.getIntValue() * entry.getKey().weight; ++ } ++ } ++ return weight; ++ } ++ ++ public List decompress(UUID uuid) { ++ List list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); ++ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { ++ list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue())); ++ } ++ return list; ++ // Paper end - Perf: Remove streams from hot code + } + + public Stream unpack(UUID target) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +@@ -0,0 +0,0 @@ public class NearestItemSensor extends Sensor { + protected void doTick(ServerLevel world, Mob entity) { + Brain brain = entity.getBrain(); + List list = world.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(32.0D, 16.0D, 32.0D), (itemEntity) -> { +- return true; ++ return itemEntity.closerThan(entity, MAX_DISTANCE_TO_WANTED_ITEM) && entity.wantsToPickUp(itemEntity.getItem()); // Paper - Perf: Move predicate into getEntities + }); + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); +- Optional optional = list.stream().filter((itemEntity) -> { +- return entity.wantsToPickUp(itemEntity.getItem()); +- }).filter((itemEntity) -> { +- return itemEntity.closerThan(entity, 32.0D); +- }).filter(entity::hasLineOfSight).findFirst(); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); ++ // Paper start - Perf: remove streams from hot code ++ ItemEntity nearest = null; ++ for (ItemEntity entityItem : list) { ++ if (entity.hasLineOfSight(entityItem)) { // Paper - Perf: Move predicate into getEntities ++ nearest = entityItem; ++ break; ++ } ++ } ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); ++ // Paper end - Perf: remove streams from hot code + } + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java +@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker { + int j = pos.getMinBlockZ(); + ObjectList objectList = new ObjectArrayList<>(10); + ObjectList objectList2 = new ObjectArrayList<>(32); +- world.startsForStructure(pos, (structure) -> { ++ // Paper start - Perf: Remove streams from hot code ++ for (net.minecraft.world.level.levelgen.structure.StructureStart start : world.startsForStructure(pos, (structure) -> { + return structure.terrainAdaptation() != TerrainAdjustment.NONE; +- }).forEach((start) -> { ++ })) { // Paper end - Perf: Remove streams from hot code + TerrainAdjustment terrainAdjustment = start.getStructure().terrainAdaptation(); + + for(StructurePiece structurePiece : start.getPieces()) { +@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker { + } + + for(JigsawJunction jigsawJunction : poolElementStructurePiece.getJunctions()) { +- int i = jigsawJunction.getSourceX(); +- int j = jigsawJunction.getSourceZ(); +- if (i > i - 12 && j > j - 12 && i < i + 15 + 12 && j < j + 15 + 12) { ++ // Paper start - decompile fix ++ int i2 = jigsawJunction.getSourceX(); ++ int j2 = jigsawJunction.getSourceZ(); ++ if (i2 > i - 12 && j2 > j - 12 && i2 < i + 15 + 12 && j2 < j + 15 + 12) { ++ // Paper end - decompile fix + objectList2.add(jigsawJunction); + } + } +@@ -0,0 +0,0 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker { + } + } + +- }); ++ } // Paper - Perf: Remove streams from hot code + return new Beardifier(objectList.iterator(), objectList2.iterator()); + } + diff --git a/patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch b/patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch index a3aeca8dbd..01c7f1b1af 100644 --- a/patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch +++ b/patches/server/Skip-POI-finding-if-stuck-in-vehicle.patch @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return false; } else { mutableLong.setValue(time + 20L + (long)world.getRandom().nextInt(20)); -+ if (entity.getNavigation().isStuck()) mutableLong.add(200); // Paper - Wait an additional 10s to check again if they're stuck ++ if (entity.getNavigation().isStuck()) mutableLong.add(200); // Paper - Perf: Wait an additional 10s to check again if they're stuck PoiManager poiManager = world.getPoiManager(); long2ObjectMap.long2ObjectEntrySet().removeIf((entry) -> { return !entry.getValue().isStillValid(time); diff --git a/patches/server/Use-correct-source-for-mushroom-block-spread-event.patch b/patches/server/Use-correct-source-for-mushroom-block-spread-event.patch index 474efa09bb..8a26dcff82 100644 --- a/patches/server/Use-correct-source-for-mushroom-block-spread-event.patch +++ b/patches/server/Use-correct-source-for-mushroom-block-spread-event.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1); -+ final BlockPos sourcePos = pos; // Paper ++ final BlockPos sourcePos = pos; // Paper - Use correct source for mushroom block spread event for (int j = 0; j < 4; ++j) { if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) { @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition2, state, 2); // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, sourcePos, blockposition2, state, 2); // CraftBukkit // Paper ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, sourcePos, blockposition2, state, 2); // CraftBukkit // Paper - Use correct source for mushroom block spread event } } diff --git a/patches/server/fix-secure-profile-with-proxy-online-mode.patch b/patches/server/fix-secure-profile-with-proxy-online-mode.patch deleted file mode 100644 index b5d87c41f0..0000000000 --- a/patches/server/fix-secure-profile-with-proxy-online-mode.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: NonSwag -Date: Sun, 8 Oct 2023 09:55:56 +0200 -Subject: [PATCH] fix secure profile with proxy online mode - - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - public boolean enforceSecureProfile() { - DedicatedServerProperties dedicatedserverproperties = this.getProperties(); - -- return dedicatedserverproperties.enforceSecureProfile && dedicatedserverproperties.onlineMode && this.services.canValidateProfileKeys(); -+ // Paper start - fix secure profile with proxy online mode -+ return dedicatedserverproperties.enforceSecureProfile -+ && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() -+ && this.services.canValidateProfileKeys(); -+ // Paper end - fix secure profile with proxy online mode - } - - @Override