diff --git a/Spigot-Server-Patches/0545-Brand-support.patch b/Spigot-Server-Patches/0545-Brand-support.patch deleted file mode 100644 index 93b631e8b3..0000000000 --- a/Spigot-Server-Patches/0545-Brand-support.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DigitalRegent -Date: Sat, 11 Apr 2020 13:10:58 +0200 -Subject: [PATCH] Brand support - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; - import com.mojang.brigadier.ParseResults; - import com.mojang.brigadier.StringReader; -+import io.netty.buffer.Unpooled; - import io.netty.util.concurrent.Future; - import io.netty.util.concurrent.GenericFutureListener; - import it.unimi.dsi.fastutil.ints.Int2ShortMap; -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.NetworkManager; -+import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.ChatMessageType; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - -+ private String clientBrandName = null; // Paper - Brand name -+ - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { - this.minecraftServer = minecraftserver; - this.networkManager = networkmanager; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final MinecraftKey CUSTOM_REGISTER = new MinecraftKey("register"); - private static final MinecraftKey CUSTOM_UNREGISTER = new MinecraftKey("unregister"); - -+ private static final MinecraftKey MINECRAFT_BRAND = new MinecraftKey("brand"); // Paper - Brand support -+ - @Override - public void a(PacketPlayInCustomPayload packetplayincustompayload) { - PlayerConnectionUtils.ensureMainThread(packetplayincustompayload, this, this.player.getWorldServer()); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - try { - byte[] data = new byte[packetplayincustompayload.data.readableBytes()]; - packetplayincustompayload.data.readBytes(data); -+ -+ // Paper start - Brand support -+ if (packetplayincustompayload.tag.equals(MINECRAFT_BRAND)) { -+ try { -+ this.clientBrandName = new PacketDataSerializer(Unpooled.copiedBuffer(data)).readUTF(256); -+ } catch (StringIndexOutOfBoundsException ex) { -+ this.clientBrandName = "illegal"; -+ } -+ } -+ // Paper end - server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - } - -+ // Paper start - brand support -+ public String getClientBrandName() { -+ return clientBrandName; -+ } -+ // Paper end -+ - public final boolean isDisconnected() { - return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper end - }; - -+ // Paper start - brand support -+ @Override -+ public String getClientBrandName() { -+ return getHandle().playerConnection != null ? getHandle().playerConnection.getClientBrandName() : null; -+ } -+ // Paper end -+ - public Player.Spigot spigot() - { - return spigot; diff --git a/Spigot-Server-Patches/API-to-get-a-BlockState-without-a-snapshot.patch b/Spigot-Server-Patches/API-to-get-a-BlockState-without-a-snapshot.patch deleted file mode 100644 index 3037240c80..0000000000 --- a/Spigot-Server-Patches/API-to-get-a-BlockState-without-a-snapshot.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Nov 2017 21:08:22 -0500 -Subject: [PATCH] API to get a BlockState without a snapshot - -This allows you to get a BlockState without creating a snapshot, operating -on the real tile entity. - -This is useful for where performance is needed - -also Avoid NPE during CraftBlockEntityState load if could not get TE - -If Tile Entity was null, correct Sign to return empty lines instead of null - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public TileEntity(TileEntityTypes tileentitytypes) { - this.position = BlockPosition.ZERO; - this.tileType = tileentitytypes; -+ persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init - } - - // Paper start -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - this.position = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - // CraftBukkit start - read container -- this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); -+ this.persistentDataContainer.clear(); // Paper - clear instead of reinit - - net.minecraft.nbt.NBTBase persistentDataTag = nbttagcompound.get("PublicBukkitValues"); - if (persistentDataTag instanceof NBTTagCompound) { -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - } - - // CraftBukkit start - add method -+ // Paper start - public InventoryHolder getOwner() { -+ return getOwner(true); -+ } -+ public InventoryHolder getOwner(boolean useSnapshot) { -+ // Paper end - if (world == null) return null; - // Spigot start - org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - return null; - } - // Spigot end -- org.bukkit.block.BlockState state = block.getState(); -+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper - if (state instanceof InventoryHolder) return (InventoryHolder) state; - return null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - - @Override - public BlockState getState() { -+ // Paper start - allow disabling the use of snapshots -+ return getState(true); -+ } -+ public BlockState getState(boolean useSnapshot) { -+ boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT; -+ CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot; -+ try { -+ return getState0(); -+ } finally { -+ CraftBlockEntityState.DISABLE_SNAPSHOT = prev; -+ } -+ } -+ public BlockState getState0() { -+ // Paper end - Material material = getType(); - - switch (material) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockState - this.tileEntity = tileEntityClass.cast(world.getHandle().getTileEntity(this.getPosition())); - Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); - -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - -+ public final boolean snapshotDisabled; // Paper -+ public static boolean DISABLE_SNAPSHOT = false; // Paper -+ - public CraftBlockEntityState(Material material, T tileEntity) { - super(material); - - this.tileEntityClass = (Class) tileEntity.getClass(); - this.tileEntity = tileEntity; -- -+ // Paper start -+ this.snapshotDisabled = DISABLE_SNAPSHOT; -+ if (DISABLE_SNAPSHOT) { -+ this.snapshot = this.tileEntity; -+ } else { -+ this.snapshot = this.createSnapshot(this.tileEntity); -+ } - // copy tile entity data: -- this.snapshot = this.createSnapshot(tileEntity); -- this.load(snapshot); -+ if(this.snapshot != null) { -+ this.load(this.snapshot); -+ } -+ // Paper end - } - - private T createSnapshot(T tileEntity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java -@@ -0,0 +0,0 @@ public final class CraftPersistentDataContainer implements PersistentDataContain - public Map serialize() { - return (Map) CraftNBTTagConfigSerializer.serialize(toTagCompound()); - } -+ -+ // Paper start -+ public void clear() { -+ this.customDataTags.clear(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Ability-to-apply-mending-to-XP-API.patch b/Spigot-Server-Patches/Ability-to-apply-mending-to-XP-API.patch deleted file mode 100644 index 6cd559b4cb..0000000000 --- a/Spigot-Server-Patches/Ability-to-apply-mending-to-XP-API.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Dec 2017 17:36:49 -0500 -Subject: [PATCH] Ability to apply mending to XP API - -This allows plugins that give players the ability to apply the experience -points to the Item Mending formula, which will repair an item instead -of giving the player experience points. - -Both an API To standalone mend, and apply mending logic to .giveExp has been added. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - } - } - -+ public final int durToXp(int i) { return b(i); } // Paper OBFHELPER - private int b(int i) { - return i / 2; - } - -+ public final int xpToDur(int i) { return c(i); } // Paper OBFHELPER - private int c(int i) { - return i * 2; - } -diff --git a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentManager.java -@@ -0,0 +0,0 @@ public class EnchantmentManager { - return getEnchantmentLevel(Enchantments.CHANNELING, itemstack) > 0; - } - -- @Nullable -- public static Entry b(Enchantment enchantment, EntityLiving entityliving) { -+ public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, EntityLiving entityliving) { Entry entry = b(enchantment, entityliving); return entry != null ? entry.getValue() : ItemStack.NULL_ITEM; } // Paper - OBFHELPER -+ @Nullable public static Entry b(Enchantment enchantment, EntityLiving entityliving) { - return a(enchantment, entityliving, (itemstack) -> { - return true; - }); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.server.players.WhiteListEntry; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.ai.attributes.AttributeMapBase; - import net.minecraft.world.entity.ai.attributes.AttributeModifiable; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; -+import net.minecraft.world.item.enchantment.EnchantmentManager; -+import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return GameMode.getByValue(getHandle().playerInteractManager.getGameMode().getId()); - } - -+ // Paper start - @Override -- public void giveExp(int exp) { -+ public int applyMending(int amount) { -+ EntityPlayer handle = getHandle(); -+ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties -+ net.minecraft.world.item.ItemStack itemstack = EnchantmentManager.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); -+ if (!itemstack.isEmpty() && itemstack.getItem().usesDurability()) { -+ -+ EntityExperienceOrb orb = EntityTypes.EXPERIENCE_ORB.create(handle.world); -+ orb.value = amount; -+ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; -+ orb.setPositionRaw(handle.locX(), handle.locY(), handle.locZ()); -+ -+ int i = Math.min(orb.xpToDur(amount), itemstack.getDamage()); -+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); -+ i = event.getRepairAmount(); -+ orb.dead = true; -+ if (!event.isCancelled()) { -+ amount -= orb.durToXp(i); -+ itemstack.setDamage(itemstack.getDamage() - i); -+ } -+ } -+ return amount; -+ } -+ -+ @Override -+ public void giveExp(int exp, boolean applyMending) { -+ if (applyMending) { -+ exp = this.applyMending(exp); -+ } -+ // Paper end - getHandle().giveExp(exp); - } - diff --git a/Spigot-Server-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Spigot-Server-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch deleted file mode 100644 index 960d694ea2..0000000000 --- a/Spigot-Server-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 11:45:57 -0400 -Subject: [PATCH] Ability to change PlayerProfile in AsyncPreLoginEvent - -This will allow you to change the players name or skin on login. - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.exceptions.AuthenticationUnavailableException; - import java.math.BigInteger; -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - // CraftBukkit start - import net.minecraft.network.chat.ChatComponentText; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import org.bukkit.Bukkit; - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - java.util.UUID uniqueId = i.getId(); - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); -+ // Paper start -+ PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); -+ profile = asyncEvent.getPlayerProfile(); -+ profile.complete(); -+ i = CraftPlayerProfile.asAuthlibCopy(profile); -+ playerName = i.getName(); -+ uniqueId = i.getId(); -+ // Paper end - - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); diff --git a/Spigot-Server-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Spigot-Server-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch deleted file mode 100644 index ffff74d637..0000000000 --- a/Spigot-Server-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 15 Aug 2018 01:16:34 -0400 -Subject: [PATCH] Ability to get Tile Entities from a chunk without snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -0,0 +0,0 @@ package org.bukkit.craftbukkit; - import com.google.common.base.Preconditions; - import com.google.common.base.Predicates; - import java.lang.ref.WeakReference; -+import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.List; - import java.util.function.Predicate; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; -@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { - - @Override - public BlockState[] getTileEntities() { -+ // Paper start -+ return getTileEntities(true); -+ } -+ -+ @Override -+ public BlockState[] getTileEntities(boolean useSnapshot) { - if (!isLoaded()) { - getWorld().getChunkAt(x, z); // Transient load for this tick - } -+ // Paper end - int index = 0; - net.minecraft.world.level.chunk.Chunk chunk = getHandle(); - -@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { - } - - BlockPosition position = (BlockPosition) obj; -- entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); -+ entities[index++] = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); // Paper -+ } -+ -+ return entities; -+ } -+ -+ // Paper start -+ @Override -+ public Collection getTileEntities(Predicate blockPredicate, boolean useSnapshot) { -+ Preconditions.checkNotNull(blockPredicate, "blockPredicate"); -+ if (!isLoaded()) { -+ getWorld().getChunkAt(x, z); // Transient load for this tick -+ } -+ net.minecraft.world.level.chunk.Chunk chunk = getHandle(); -+ -+ List entities = new ArrayList<>(); -+ -+ for (BlockPosition position : chunk.tileEntities.keySet()) { -+ Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -+ if (blockPredicate.test(block)) { -+ entities.add(block.getState(useSnapshot)); -+ } - } - - return entities; - } -+ // Paper end - - @Override - public boolean isLoaded() { diff --git a/Spigot-Server-Patches/Add-API-for-quit-reason.patch b/Spigot-Server-Patches/Add-API-for-quit-reason.patch deleted file mode 100644 index 6cf5722d11..0000000000 --- a/Spigot-Server-Patches/Add-API-for-quit-reason.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:19:52 +0100 -Subject: [PATCH] Add API for quit reason - - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - this.u = true; - if (this.channel.isOpen()) { -+ EntityPlayer player = this.getPlayer(); // Paper - if (throwable instanceof TimeoutException) { - NetworkManager.LOGGER.debug("Timeout", throwable); -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper - this.close(new ChatMessage("disconnect.timeout")); - } else { - ChatMessage chatmessage = new ChatMessage("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); - -+ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper - if (flag) { - NetworkManager.LOGGER.debug("Failed to sent packet", throwable); - this.sendPacket(new PacketPlayOutKickDisconnect(chatmessage), (future) -> { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - - boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event - - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - -+ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper - this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { - this.networkManager.close(ichatbasecomponent); - }); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName())), entityplayer.quitReason); // Paper - quit reason - if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - diff --git a/Spigot-Server-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch b/Spigot-Server-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch deleted file mode 100644 index 4cf77321e6..0000000000 --- a/Spigot-Server-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Wed, 21 Dec 2016 11:47:25 -0600 -Subject: [PATCH] Add API methods to control if armour stands can move - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.ai.control.ControllerLook; - import net.minecraft.world.entity.ai.control.ControllerMove; - import net.minecraft.world.entity.ai.control.EntityAIBodyControl; - import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalFloat; - import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; - import net.minecraft.world.entity.ai.navigation.Navigation; - import net.minecraft.world.entity.ai.navigation.NavigationAbstract; -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.ai.sensing.EntitySenses; - import net.minecraft.world.entity.decoration.EntityHanging; - import net.minecraft.world.entity.decoration.EntityLeash; - import net.minecraft.world.entity.item.EntityItem; -+import net.minecraft.world.entity.monster.EntityBlaze; -+import net.minecraft.world.entity.monster.EntityEnderman; - import net.minecraft.world.entity.monster.IMonster; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.EntitySize; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.EnumMainHand; -+import net.minecraft.world.entity.EnumMoveType; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityArrow; - import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - public Vector3f rightArmPose; - public Vector3f leftLegPose; - public Vector3f rightLegPose; -+ public boolean canMove = true; // Paper - - public EntityArmorStand(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - private EntitySize s(boolean flag) { - return flag ? EntityArmorStand.bp : (this.isBaby() ? EntityArmorStand.bq : this.getEntityType().l()); - } -+ -+ // Paper start -+ @Override -+ public void move(EnumMoveType moveType, Vec3D vec3d) { -+ if (this.canMove) { -+ super.move(moveType, vec3d); -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -0,0 +0,0 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean hasEquipmentLock(EquipmentSlot equipmentSlot, LockType lockType) { - return (getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getSlotFlag() + lockType.ordinal() * 8)) != 0; - } -+ // Paper start -+ @Override -+ public boolean canMove() { -+ return getHandle().canMove; -+ } -+ -+ @Override -+ public void setCanMove(boolean move) { -+ getHandle().canMove = move; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch deleted file mode 100644 index 2d75b4559a..0000000000 --- a/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Wed, 2 Jan 2019 00:35:43 -0600 -Subject: [PATCH] Add APIs to replace OfflinePlayer#getLastPlayed - -Currently OfflinePlayer#getLastPlayed could more accurately be described -as "OfflinePlayer#getLastTimeTheirDataWasSaved". - -The API doc says it should return the last time the server "witnessed" -the player, whilst also saying it should return the last time they -logged in. The current implementation does neither. - -Given this interesting contradiction in the API documentation and the -current defacto implementation, I've elected to deprecate (with no -intent to remove) and replace it with two new methods, clearly named and -documented as to their purpose. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int ping; - public boolean viewingCredits; - private int containerUpdateDelay; // Paper -+ public long loginTime; // Paper - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { -+ entityplayer.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = entityplayer.getProfile(); - UserCache usercache = this.server.getUserCache(); - GameProfile gameprofile1 = usercache.getProfile(gameprofile.getId()); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -@@ -0,0 +0,0 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa - return getData() != null; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastLogin(); -+ -+ NBTTagCompound data = getPaperData(); -+ -+ if (data != null) { -+ if (data.hasKey("LastLogin")) { -+ return data.getLong("LastLogin"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ @Override -+ public long getLastSeen() { -+ Player player = getPlayer(); -+ if (player != null) return player.getLastSeen(); -+ -+ NBTTagCompound data = getPaperData(); -+ -+ if (data != null) { -+ if (data.hasKey("LastSeen")) { -+ return data.getLong("LastSeen"); -+ } else { -+ // if the player file cannot provide accurate data, this is probably the closest we can approximate -+ File file = getDataFile(); -+ return file.lastModified(); -+ } -+ } else { -+ return 0; -+ } -+ } -+ -+ private NBTTagCompound getPaperData() { -+ NBTTagCompound result = getData(); -+ -+ if (result != null) { -+ if (!result.hasKey("Paper")) { -+ result.set("Paper", new NBTTagCompound()); -+ } -+ result = result.getCompound("Paper"); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public Location getBedSpawnLocation() { - NBTTagCompound data = getData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; - private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit -+ private long lastSaveTime; - // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - this.firstPlayed = firstPlayed; - } - -+ // Paper start -+ @Override -+ public long getLastLogin() { -+ return getHandle().loginTime; -+ } -+ -+ @Override -+ public long getLastSeen() { -+ return isOnline() ? System.currentTimeMillis() : this.lastSaveTime; -+ } -+ // Paper end -+ - public void readExtraData(NBTTagCompound nbttagcompound) { - hasPlayedBefore = true; - if (nbttagcompound.hasKey("bukkit")) { -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setExtraData(NBTTagCompound nbttagcompound) { -+ this.lastSaveTime = System.currentTimeMillis(); // Paper -+ - if (!nbttagcompound.hasKey("bukkit")) { - nbttagcompound.set("bukkit", new NBTTagCompound()); - } -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - data.setLong("firstPlayed", getFirstPlayed()); - data.setLong("lastPlayed", System.currentTimeMillis()); - data.setString("lastKnownName", handle.getName()); -+ -+ // Paper start - persist for use in offline save data -+ if (!nbttagcompound.hasKey("Paper")) { -+ nbttagcompound.set("Paper", new NBTTagCompound()); -+ } -+ -+ NBTTagCompound paper = nbttagcompound.getCompound("Paper"); -+ paper.setLong("LastLogin", handle.loginTime); -+ paper.setLong("LastSeen", System.currentTimeMillis()); -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Spigot-Server-Patches/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch deleted file mode 100644 index 952dab9008..0000000000 --- a/Spigot-Server-Patches/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alvinn8 <42838560+Alvinn8@users.noreply.github.com> -Date: Fri, 8 Jan 2021 20:31:13 +0100 -Subject: [PATCH] Add Adventure message to PlayerAdvancementDoneEvent - - -diff --git a/src/main/java/net/minecraft/advancements/Advancement.java b/src/main/java/net/minecraft/advancements/Advancement.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/advancements/Advancement.java -+++ b/src/main/java/net/minecraft/advancements/Advancement.java -@@ -0,0 +0,0 @@ public class Advancement { - return this.parent; - } - -+ public final @Nullable AdvancementDisplay getAdvancementDisplay() { return this.c(); } // Paper - OBFHELPER - @Nullable - public AdvancementDisplay c() { - return this.display; -@@ -0,0 +0,0 @@ public class Advancement { - return this.requirements; - } - -+ public final IChatBaseComponent getChatComponent() { return this.j(); } // Paper - OBFHELPER - public IChatBaseComponent j() { - return this.chatComponent; - } -diff --git a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -+++ b/src/main/java/net/minecraft/advancements/AdvancementDisplay.java -@@ -0,0 +0,0 @@ public class AdvancementDisplay { - return this.b; - } - -+ public final AdvancementFrameType getFrameType() { return this.e(); } // Paper - OBFHELPER - public AdvancementFrameType e() { - return this.e; - } - -+ public final boolean shouldAnnounceToChat() { return this.i(); } // Paper - OBFHELPER - public boolean i() { - return this.g; - } -diff --git a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -+++ b/src/main/java/net/minecraft/advancements/AdvancementFrameType.java -@@ -0,0 +0,0 @@ public enum AdvancementFrameType { - this.g = new ChatMessage("advancements.toast." + s); - } - -+ public final String getId() { return this.a(); } // Paper - OBFHELPER - public String a() { - return this.d; - } -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.GameRules; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class AdvancementDataPlayer { - -@@ -0,0 +0,0 @@ public class AdvancementDataPlayer { - this.j.add(advancement); - flag = true; - if (!flag1 && advancementprogress.isDone()) { -- this.player.world.getServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ boolean announceToChat = advancement.getAdvancementDisplay() != null && advancement.getAdvancementDisplay().shouldAnnounceToChat(); -+ net.kyori.adventure.text.Component message = announceToChat ? PaperAdventure.asAdventure(new ChatMessage("chat.type.advancement." + advancement.getAdvancementDisplay().getFrameType().getId(), this.player.getScoreboardDisplayName(), advancement.getChatComponent())) : null; -+ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); -+ this.player.world.getServer().getPluginManager().callEvent(event); -+ message = event.message(); -+ // Paper end - advancement.d().a(this.player); -- if (advancement.c() != null && advancement.c().i() && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { -- this.e.sendMessage(new ChatMessage("chat.type.advancement." + advancement.c().e().a(), new Object[]{this.player.getScoreboardDisplayName(), advancement.j()}), ChatMessageType.SYSTEM, SystemUtils.b); -+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent -+ if (message != null && this.player.world.getGameRules().getBoolean(GameRules.ANNOUNCE_ADVANCEMENTS)) { -+ this.e.sendMessage(PaperAdventure.asVanilla(message), ChatMessageType.SYSTEM, SystemUtils.getNullUUID()); -+ // Paper end - } - } - } diff --git a/Spigot-Server-Patches/Add-ArmorStand-Item-Meta.patch b/Spigot-Server-Patches/Add-ArmorStand-Item-Meta.patch deleted file mode 100644 index 1e178065fb..0000000000 --- a/Spigot-Server-Patches/Add-ArmorStand-Item-Meta.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sat, 27 Jan 2018 17:04:14 -0500 -Subject: [PATCH] Add ArmorStand Item Meta - -This is adds basic item meta for armor stands. It does not add all -possible metadata however. - -There are armor, hand, and equipment types, as well as position data -that can also be added here. This initial addition should serve a -starting point for future additions in this area. - -Fixes GH-559 - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmorStand.java -@@ -0,0 +0,0 @@ import org.bukkit.configuration.serialization.DelegateDeserialization; - import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey; - - @DelegateDeserialization(CraftMetaItem.SerializableMeta.class) --public class CraftMetaArmorStand extends CraftMetaItem { -+public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper - - static final ItemMetaKey ENTITY_TAG = new ItemMetaKey("EntityTag", "entity-tag"); -+ // Paper start -+ static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible"); -+ static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate"); -+ static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms"); -+ static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small"); -+ static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker"); -+ -+ private boolean invisible; -+ private boolean noBasePlate; -+ private boolean showArms; -+ private boolean small; -+ private boolean marker; -+ // Paper end - NBTTagCompound entityTag; - - CraftMetaArmorStand(CraftMetaItem meta) { -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - CraftMetaArmorStand armorStand = (CraftMetaArmorStand) meta; -+ // Paper start -+ this.invisible = armorStand.invisible; -+ this.noBasePlate = armorStand.noBasePlate; -+ this.showArms = armorStand.showArms; -+ this.small = armorStand.small; -+ this.marker = armorStand.marker; -+ // Paper end - this.entityTag = armorStand.entityTag; - } - -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - if (tag.hasKey(ENTITY_TAG.NBT)) { - entityTag = tag.getCompound(ENTITY_TAG.NBT); -+ -+ // Paper start -+ if (entityTag.hasKey(INVISIBLE.NBT)) { -+ invisible = entityTag.getBoolean(INVISIBLE.NBT); -+ } -+ -+ if (entityTag.hasKey(NO_BASE_PLATE.NBT)) { -+ noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); -+ } -+ -+ if (entityTag.hasKey(SHOW_ARMS.NBT)) { -+ showArms = entityTag.getBoolean(SHOW_ARMS.NBT); -+ } -+ -+ if (entityTag.hasKey(SMALL.NBT)) { -+ small = entityTag.getBoolean(SMALL.NBT); -+ } -+ -+ if (entityTag.hasKey(MARKER.NBT)) { -+ marker = entityTag.getBoolean(MARKER.NBT); -+ } -+ // Paper end - } - } - - CraftMetaArmorStand(Map map) { - super(map); -+ -+ // Paper start -+ boolean invis = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); -+ boolean noBase = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); -+ boolean showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); -+ boolean small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); -+ boolean marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); -+ -+ this.invisible = invis; -+ this.noBasePlate = noBase; -+ this.showArms = showArms; -+ this.small = small; -+ this.marker = marker; -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - void applyToItem(NBTTagCompound tag) { - super.applyToItem(tag); - -+ // Paper start -+ if (!isArmorStandEmpty() && entityTag == null) { -+ entityTag = new NBTTagCompound(); -+ } -+ -+ if (isInvisible()) { -+ entityTag.setBoolean(INVISIBLE.NBT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ entityTag.setBoolean(NO_BASE_PLATE.NBT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ entityTag.setBoolean(SHOW_ARMS.NBT, showArms); -+ } -+ -+ if (isSmall()) { -+ entityTag.setBoolean(SMALL.NBT, small); -+ } -+ -+ if (isMarker()) { -+ entityTag.setBoolean(MARKER.NBT, marker); -+ } -+ // Paper end -+ - if (entityTag != null) { - tag.set(ENTITY_TAG.NBT, entityTag); - } -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - } - - boolean isArmorStandEmpty() { -- return !(entityTag != null); -+ return !(isInvisible() || hasNoBasePlate() || shouldShowArms() || isSmall() || isMarker() || entityTag != null); - } - - @Override -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - if (meta instanceof CraftMetaArmorStand) { - CraftMetaArmorStand that = (CraftMetaArmorStand) meta; - -- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; -+ // Paper start -+ return invisible == that.invisible && -+ noBasePlate == that.noBasePlate && -+ showArms == that.showArms && -+ small == that.small && -+ marker == that.marker; -+ // Paper end - } - return true; - } -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - final int original; - int hash = original = super.applyHash(); - -- if (entityTag != null) { -- hash = 73 * hash + entityTag.hashCode(); -- } -+ // Paper start -+ hash += entityTag != null ? 73 * hash + entityTag.hashCode() : 0; -+ hash += isInvisible() ? 61 * hash + 1231 : 0; -+ hash += hasNoBasePlate() ? 61 * hash + 1231 : 0; -+ hash += shouldShowArms() ? 61 * hash + 1231 : 0; -+ hash += isSmall() ? 61 * hash + 1231 : 0; -+ hash += isMarker() ? 61 * hash + 1231 : 0; -+ // Paper end - - return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; - } -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - Builder serialize(Builder builder) { - super.serialize(builder); - -+ // Paper start -+ if (isInvisible()) { -+ builder.put(INVISIBLE.BUKKIT, invisible); -+ } -+ -+ if (hasNoBasePlate()) { -+ builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); -+ } -+ -+ if (shouldShowArms()) { -+ builder.put(SHOW_ARMS.BUKKIT, showArms); -+ } -+ -+ if (isSmall()) { -+ builder.put(SMALL.BUKKIT, small); -+ } -+ -+ if (isMarker()) { -+ builder.put(MARKER.BUKKIT, marker); -+ } -+ // Paper end -+ - return builder; - } - -@@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - - return clone; - } -+ -+ // Paper start -+ @Override -+ public boolean isInvisible() { -+ return invisible; -+ } -+ -+ @Override -+ public boolean hasNoBasePlate() { -+ return noBasePlate; -+ } -+ -+ @Override -+ public boolean shouldShowArms() { -+ return showArms; -+ } -+ -+ @Override -+ public boolean isSmall() { -+ return small; -+ } -+ -+ @Override -+ public boolean isMarker() { -+ return marker; -+ } -+ -+ @Override -+ public void setInvisible(boolean invisible) { -+ this.invisible = invisible; -+ } -+ -+ @Override -+ public void setNoBasePlate(boolean noBasePlate) { -+ this.noBasePlate = noBasePlate; -+ } -+ -+ @Override -+ public void setShowArms(boolean showArms) { -+ this.showArms = showArms; -+ } -+ -+ @Override -+ public void setSmall(boolean small) { -+ this.small = small; -+ } -+ -+ @Override -+ public void setMarker(boolean marker) { -+ this.marker = marker; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaCrossbow.CHARGED.NBT, - CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, - CraftMetaSuspiciousStew.EFFECTS.NBT, -+ // Paper start -+ CraftMetaArmorStand.ENTITY_TAG.NBT, -+ CraftMetaArmorStand.INVISIBLE.NBT, -+ CraftMetaArmorStand.NO_BASE_PLATE.NBT, -+ CraftMetaArmorStand.SHOW_ARMS.NBT, -+ CraftMetaArmorStand.SMALL.NBT, -+ CraftMetaArmorStand.MARKER.NBT, -+ // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, - CraftMetaCompass.LODESTONE_TRACKED.NBT -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -0,0 +0,0 @@ public class ItemMetaTest extends AbstractTestingBase { - final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta(); - meta.entityTag = new NBTTagCompound(); - meta.entityTag.setBoolean("Small", true); -+ meta.setInvisible(true); // Paper - cleanStack.setItemMeta(meta); - return cleanStack; - } diff --git a/Spigot-Server-Patches/Add-BeaconEffectEvent.patch b/Spigot-Server-Patches/Add-BeaconEffectEvent.patch deleted file mode 100644 index 33bffdc9aa..0000000000 --- a/Spigot-Server-Patches/Add-BeaconEffectEvent.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 23:30:53 -0600 -Subject: [PATCH] Add BeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.AxisAlignedBB; - import org.bukkit.craftbukkit.potion.CraftPotionUtil; - import org.bukkit.potion.PotionEffect; - // CraftBukkit end -+// Paper start -+import org.bukkit.craftbukkit.event.CraftEventFactory; -+import org.bukkit.entity.Player; -+import com.destroystokyo.paper.event.block.BeaconEffectEvent; -+// Paper end - - public class TileEntityBeacon extends TileEntity implements ITileInventory, ITickable { - -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - } - - private void applyEffect(List list, MobEffectList effects, int i, int b0) { -+ // Paper - BeaconEffectEvent -+ applyEffect(list, effects, i, b0, true); -+ } -+ -+ private void applyEffect(List list, MobEffectList effects, int i, int b0, boolean isPrimary) { -+ // Paper - BeaconEffectEvent - { - Iterator iterator = list.iterator(); - - EntityHuman entityhuman; - -+ // Paper start - BeaconEffectEvent -+ org.bukkit.block.Block block = world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); -+ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffect(effects, i, b0, true, true)); -+ // Paper end -+ - while (iterator.hasNext()) { - entityhuman = (EntityHuman) iterator.next(); -- entityhuman.addEffect(new MobEffect(effects, i, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ -+ // Paper start - BeaconEffectEvent -+ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (Player) entityhuman.getBukkitEntity(), isPrimary); -+ if (CraftEventFactory.callEvent(event).isCancelled()) continue; -+ entityhuman.addEffect(new MobEffect(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); -+ // Paper end - } - } - } -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - int i = getLevel(); - List list = getHumansInRange(); - -- applyEffect(list, this.primaryEffect, i, b0); -+ applyEffect(list, this.primaryEffect, i, b0, true); // Paper - BeaconEffectEvent - - if (hasSecondaryEffect()) { -- applyEffect(list, this.secondaryEffect, i, 0); -+ applyEffect(list, this.secondaryEffect, i, 0, false); // Paper - BeaconEffectEvent - } - } - diff --git a/Spigot-Server-Patches/Add-BellRevealRaiderEvent.patch b/Spigot-Server-Patches/Add-BellRevealRaiderEvent.patch deleted file mode 100644 index f509bdbf63..0000000000 --- a/Spigot-Server-Patches/Add-BellRevealRaiderEvent.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Wed, 26 May 2021 17:09:07 -0400 -Subject: [PATCH] Add BellRevealRaiderEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.particles.Particles; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; -@@ -0,0 +0,0 @@ public class TileEntityBell extends TileEntity implements ITickable { - } - - private void b(EntityLiving entityliving) { -+ if (!new io.papermc.paper.event.block.BellRevealRaiderEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, position)), entityliving.getBukkitEntity()).callEvent()) return; // Paper - BellRevealRaiderEvent - entityliving.addEffect(new MobEffect(MobEffects.GLOWING, 60)); - } - } diff --git a/Spigot-Server-Patches/Add-BellRingEvent.patch b/Spigot-Server-Patches/Add-BellRingEvent.patch deleted file mode 100644 index cbacd7cccf..0000000000 --- a/Spigot-Server-Patches/Add-BellRingEvent.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Eearslya Sleiarion -Date: Sun, 23 Aug 2020 13:04:02 +0200 -Subject: [PATCH] Add BellRingEvent - -Add a new event, BellRingEvent, to trigger whenever a player rings a -village bell. Passes along the bell block and the player who rang it. - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBell.java b/src/main/java/net/minecraft/world/level/block/BlockBell.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBell.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBell.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.BellRingEvent; -+ - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.StatisticList; -@@ -0,0 +0,0 @@ public class BlockBell extends BlockTileEntity { - boolean flag1 = !flag || this.a(iblockdata, enumdirection, movingobjectpositionblock.getPos().y - (double) blockposition.getY()); - - if (flag1) { -- boolean flag2 = this.a(world, blockposition, enumdirection); -+ boolean flag2 = this.handleBellRing(world, blockposition, enumdirection, entityhuman); // Paper - - if (flag2 && entityhuman != null) { - entityhuman.a(StatisticList.BELL_RING); -@@ -0,0 +0,0 @@ public class BlockBell extends BlockTileEntity { - } - - public boolean a(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection) { -+ // Paper start - add ringer param -+ return this.handleBellRing(world, blockposition, enumdirection, null); -+ } -+ public boolean handleBellRing(World world, BlockPosition blockposition, @Nullable EnumDirection enumdirection, @Nullable Entity ringer) { -+ // Paper end - TileEntity tileentity = world.getTileEntity(blockposition); - - if (!world.isClientSide && tileentity instanceof TileEntityBell) { -@@ -0,0 +0,0 @@ public class BlockBell extends BlockTileEntity { - enumdirection = (EnumDirection) world.getType(blockposition).get(BlockBell.a); - } - -+ if (!new BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, blockposition)), ringer == null ? null : ringer.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent - ((TileEntityBell) tileentity).a(enumdirection); - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_BELL_USE, SoundCategory.BLOCKS, 2.0F, 1.0F); - return true; diff --git a/Spigot-Server-Patches/Add-Block-isValidTool.patch b/Spigot-Server-Patches/Add-Block-isValidTool.patch deleted file mode 100644 index 4e4985df4f..0000000000 --- a/Spigot-Server-Patches/Add-Block-isValidTool.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 6 Jul 2020 12:44:31 -0700 -Subject: [PATCH] Add Block#isValidTool - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - } - return speed; - } -+ -+ public boolean isValidTool(ItemStack itemStack) { -+ return getDrops(itemStack).size() != 0; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Add-Channel-initialization-listeners.patch b/Spigot-Server-Patches/Add-Channel-initialization-listeners.patch deleted file mode 100644 index a549544f8f..0000000000 --- a/Spigot-Server-Patches/Add-Channel-initialization-listeners.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -Date: Thu, 29 Apr 2021 21:19:33 +0200 -Subject: [PATCH] Add Channel initialization listeners - - -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListener.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

-+ * This is not officially supported API and we make no guarantees to the existence or state of this interface. -+ */ -+@FunctionalInterface -+public interface ChannelInitializeListener { -+ -+ void afterInitChannel(@NonNull Channel channel); -+} -diff --git a/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/network/ChannelInitializeListenerHolder.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.network; -+ -+import io.netty.channel.Channel; -+import net.kyori.adventure.key.Key; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+import java.util.Collections; -+import java.util.HashMap; -+import java.util.Map; -+ -+/** -+ * Internal API to register channel initialization listeners. -+ *

-+ * This is not officially supported API and we make no guarantees to the existence or state of this class. -+ */ -+public final class ChannelInitializeListenerHolder { -+ -+ private static final Map LISTENERS = new HashMap<>(); -+ private static final Map IMMUTABLE_VIEW = Collections.unmodifiableMap(LISTENERS); -+ -+ private ChannelInitializeListenerHolder() { -+ } -+ -+ /** -+ * Registers whether an initialization listener is registered under the given key. -+ * -+ * @param key key -+ * @return whether an initialization listener is registered under the given key -+ */ -+ public static boolean hasListener(@NonNull Key key) { -+ return LISTENERS.containsKey(key); -+ } -+ -+ /** -+ * Registers a channel initialization listener called after ServerConnection is initialized. -+ * -+ * @param key key -+ * @param listener initialization listeners -+ */ -+ public static void addListener(@NonNull Key key, @NonNull ChannelInitializeListener listener) { -+ LISTENERS.put(key, listener); -+ } -+ -+ /** -+ * Removes and returns an initialization listener registered by the given key if present. -+ * -+ * @param key key -+ * @return removed initialization listener if present -+ */ -+ public static @Nullable ChannelInitializeListener removeListener(@NonNull Key key) { -+ return LISTENERS.remove(key); -+ } -+ -+ /** -+ * Returns an immutable map of registered initialization listeners. -+ * -+ * @return immutable map of registered initialization listeners -+ */ -+ public static @NonNull Map getListeners() { -+ return IMMUTABLE_VIEW; -+ } -+ -+ /** -+ * Calls the registered listeners with the given channel. -+ * -+ * @param channel channel -+ */ -+ public static void callListeners(@NonNull Channel channel) { -+ for (ChannelInitializeListener listener : LISTENERS.values()) { -+ listener.afterInitChannel(channel); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -0,0 +0,0 @@ public class ServerConnection { - pending.add((NetworkManager) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); -+ io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - } - }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit - } diff --git a/Spigot-Server-Patches/Add-CraftMagicNumbers.isSupportedApiVersion.patch b/Spigot-Server-Patches/Add-CraftMagicNumbers.isSupportedApiVersion.patch deleted file mode 100644 index 39ef9e26a9..0000000000 --- a/Spigot-Server-Patches/Add-CraftMagicNumbers.isSupportedApiVersion.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BlackHole -Date: Sun, 15 Dec 2019 19:12:39 +0100 -Subject: [PATCH] Add CraftMagicNumbers.isSupportedApiVersion() - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { - return new com.destroystokyo.paper.PaperVersionFetcher(); - } -+ -+ @Override -+ public boolean isSupportedApiVersion(String apiVersion) { -+ return apiVersion != null && SUPPORTED_API.contains(apiVersion); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/Spigot-Server-Patches/Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch deleted file mode 100644 index 0fa32aa370..0000000000 --- a/Spigot-Server-Patches/Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 08:25:40 -0400 -Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues - -Add -Ddebug.entities=true to your JVM flags to gain more information - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } else { - PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = new PlayerChunkMap.EntityTracker(entity, i, j, entitytypes.isDeltaTracking()); - -+ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); - playerchunkmap_entitytracker.track(this.world.getPlayers()); - if (entity instanceof EntityPlayer) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (playerchunkmap_entitytracker1 != null) { - playerchunkmap_entitytracker1.a(); - } -- -+ entity.tracker = null; // Paper - We're no longer tracked - } - - protected void g() { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ private static Throwable getAddToWorldStackTrace(Entity entity) { -+ return new Throwable(entity + " Added to world at " + new java.util.Date()); -+ } - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -- if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper -+ // Paper start -+ if (entity.valid) { -+ MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -+ -+ if (DEBUG_ENTITIES) { -+ Throwable thr = entity.addedToWorldStack; -+ if (thr == null) { -+ MinecraftServer.LOGGER.error("Double add entity has no add stacktrace"); -+ } else { -+ MinecraftServer.LOGGER.error("Double add stacktrace: ", thr); -+ } -+ } -+ return true; -+ } -+ // Paper end - if (entity.dead) { -+ // Paper start -+ if (DEBUG_ENTITIES) { -+ new Throwable("Tried to add entity " + entity + " but it was marked as removed already").printStackTrace(); // CraftBukkit -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; - } else if (this.isUUIDTaken(entity)) { -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -- this.entitiesByUUID.put(entity.getUniqueID(), entity); -+ if (DEBUG_ENTITIES) { -+ entity.addedToWorldStack = getAddToWorldStackTrace(entity); -+ } -+ -+ Entity old = this.entitiesByUUID.put(entity.getUniqueID(), entity); -+ if (old != null && old.getId() != entity.getId() && old.valid) { -+ Logger logger = LogManager.getLogger(); -+ logger.error("Overwrote an existing entity " + old + " with " + entity); -+ if (DEBUG_ENTITIES) { -+ if (old.addedToWorldStack != null) { -+ old.addedToWorldStack.printStackTrace(); -+ } else { -+ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); -+ } -+ entity.addedToWorldStack.printStackTrace(); -+ } -+ } -+ - this.getChunkProvider().addEntity(entity); - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof EntityDrowned) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -+ PlayerChunkMap.EntityTracker tracker; // Paper -+ public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { - bukkitEntity = CraftEntity.getEntity(world.getServer(), this); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean pvpMode; - public boolean keepSpawnInMemory = true; - public org.bukkit.generator.ChunkGenerator generator; -+ public static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; diff --git a/Spigot-Server-Patches/Add-Destroy-Speed-API.patch b/Spigot-Server-Patches/Add-Destroy-Speed-API.patch deleted file mode 100644 index cbe2771a5c..0000000000 --- a/Spigot-Server-Patches/Add-Destroy-Speed-API.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Ineusia -Date: Mon, 26 Oct 2020 11:48:06 -0500 -Subject: [PATCH] Add Destroy Speed API - -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - public String getTranslationKey() { - return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); - } -+ -+ @Override -+ public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { -+ net.minecraft.world.item.ItemStack nmsItemStack; -+ if (itemStack instanceof CraftItemStack) { -+ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); -+ } else { -+ nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ } -+ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().getBlockData()); -+ if (speed > 1.0F && considerEnchants) { -+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentManager.getEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.DIG_SPEED, nmsItemStack); -+ if (enchantLevel > 0) { -+ speed += enchantLevel * enchantLevel + 1; -+ } -+ } -+ return speed; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch b/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch deleted file mode 100644 index 205a6d63ae..0000000000 --- a/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Wed, 8 Aug 2018 15:30:52 -0400 -Subject: [PATCH] Add Early Warning Feature to WatchDog - -Detect when the server has been hung for a long duration, and start printing -thread dumps at an interval until the point of crash. - -This will help diagnose what was going on in that time before the crash. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; - import org.spigotmc.SpigotConfig; -+import org.spigotmc.WatchdogThread; - - public class PaperConfig { - -@@ -0,0 +0,0 @@ public class PaperConfig { - } - } - -+ public static int watchdogPrintEarlyWarningEvery = 5000; -+ public static int watchdogPrintEarlyWarningDelay = 10000; -+ private static void watchdogEarlyWarning() { -+ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); -+ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); -+ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); -+ } -+ - public static int tabSpamIncrement = 1; - public static int tabSpamLimit = 500; - private static void tabSpamLimiters() { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable -+ // Paper start -+ Logger log = Bukkit.getServer().getLogger(); -+ long currentTime = monotonicMillis(); -+ if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) - { -- Logger log = Bukkit.getServer().getLogger(); -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ // Don't spam early warning dumps -+ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -+ if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ lastEarlyWarning = currentTime; -+ if (isLongTimeout) { -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - } - } - // Paper end -+ } else -+ { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); -+ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); -+ } -+ // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // -+ // Paper start - Only print full dump on long timeouts -+ if ( isLongTimeout ) -+ { - log.log( Level.SEVERE, "Entire Thread Dump:" ); - ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); - for ( ThreadInfo thread : threads ) - { - dumpThread( thread, log ); - } -+ } else { -+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); -+ } -+ -+ - log.log( Level.SEVERE, "------------------------------" ); - -+ if ( isLongTimeout ) -+ { - if ( restart && !MinecraftServer.getServer().hasStopped() ) - { - RestartCommand.restart(); - } - break; -+ } // Paper end - } - - try - { -- sleep( 10000 ); -+ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout - } catch ( InterruptedException ex ) - { - interrupt(); diff --git a/Spigot-Server-Patches/Add-ElderGuardianAppearanceEvent.patch b/Spigot-Server-Patches/Add-ElderGuardianAppearanceEvent.patch deleted file mode 100644 index 1d599bfd64..0000000000 --- a/Spigot-Server-Patches/Add-ElderGuardianAppearanceEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Fri, 19 Mar 2021 23:39:09 -0400 -Subject: [PATCH] Add ElderGuardianAppearanceEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityGuardianElder.java -@@ -0,0 +0,0 @@ public class EntityGuardianElder extends EntityGuardian { - while (iterator.hasNext()) { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - -+ if (new io.papermc.paper.event.entity.ElderGuardianAppearanceEvent(getBukkitEntity(), entityplayer.getBukkitEntity()).callEvent()) { // Paper - Add Guardian Appearance Event - if (!entityplayer.hasEffect(mobeffectlist) || entityplayer.getEffect(mobeffectlist).getAmplifier() < 2 || entityplayer.getEffect(mobeffectlist).getDuration() < 1200) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.k, this.isSilent() ? 0.0F : 1.0F)); - entityplayer.addEffect(new MobEffect(mobeffectlist, 6000, 2), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit - } -+ } // Paper - Add Guardian Appearance Event - } - } - diff --git a/Spigot-Server-Patches/Add-EntityBlockStorage-clearEntities.patch b/Spigot-Server-Patches/Add-EntityBlockStorage-clearEntities.patch deleted file mode 100644 index eba70612e7..0000000000 --- a/Spigot-Server-Patches/Add-EntityBlockStorage-clearEntities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 18:12:29 -0400 -Subject: [PATCH] Add EntityBlockStorage#clearEntities() - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeehive.java -@@ -0,0 +0,0 @@ public class TileEntityBeehive extends TileEntity implements ITickable { - return this.bees.size(); - } - -+ // Paper start - Add EntityBlockStorage clearEntities -+ public void clearBees() { -+ this.bees.clear(); -+ } -+ // Paper end - public static int a(IBlockData iblockdata) { - return (Integer) iblockdata.get(BlockBeehive.b); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java -@@ -0,0 +0,0 @@ public class CraftBeehive extends CraftBlockEntityState imple - - getSnapshot().addBee(((CraftBee) entity).getHandle(), false); - } -+ // Paper start - Add EntityBlockStorage clearEntities -+ @Override -+ public void clearEntities() { -+ getSnapshot().clearBees(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-EntityInsideBlockEvent.patch b/Spigot-Server-Patches/Add-EntityInsideBlockEvent.patch deleted file mode 100644 index f54fefcbd1..0000000000 --- a/Spigot-Server-Patches/Add-EntityInsideBlockEvent.patch +++ /dev/null @@ -1,222 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 18:02:36 -0700 -Subject: [PATCH] Add EntityInsideBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java b/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBubbleColumn.java -@@ -0,0 +0,0 @@ public class BlockBubbleColumn extends Block implements IFluidSource { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - IBlockData iblockdata1 = world.getType(blockposition.up()); - - if (iblockdata1.isAir()) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockButtonAbstract.java -@@ -0,0 +0,0 @@ public abstract class BlockButtonAbstract extends BlockAttachable { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide && this.v && !(Boolean) iblockdata.get(BlockButtonAbstract.POWERED)) { - this.e(iblockdata, world, blockposition); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCactus.java b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCactus.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -@@ -0,0 +0,0 @@ public class BlockCactus extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - CraftEventFactory.blockDamage = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); // CraftBukkit - entity.damageEntity(DamageSource.CACTUS, 1.0F); - CraftEventFactory.blockDamage = null; // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCampfire.java -@@ -0,0 +0,0 @@ public class BlockCampfire extends BlockTileEntity implements IBlockWaterlogged - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!entity.isFireProof() && (Boolean) iblockdata.get(BlockCampfire.LIT) && entity instanceof EntityLiving && !EnchantmentManager.i((EntityLiving) entity)) { - entity.damageEntity(DamageSource.FIRE, (float) this.h); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCauldron.java b/src/main/java/net/minecraft/world/level/block/BlockCauldron.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCauldron.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCauldron.java -@@ -0,0 +0,0 @@ public class BlockCauldron extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - int i = (Integer) iblockdata.get(BlockCauldron.LEVEL); - float f = (float) blockposition.getY() + (6.0F + (float) (3 * i)) / 16.0F; - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCrops.java b/src/main/java/net/minecraft/world/level/block/BlockCrops.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCrops.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCrops.java -@@ -0,0 +0,0 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (entity instanceof EntityRavager && !CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData(), !world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)).isCancelled()) { // CraftBukkit - world.a(blockposition, true, entity); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -@@ -0,0 +0,0 @@ public class BlockEnderPortal extends BlockTileEntity { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (world instanceof WorldServer && !entity.isPassenger() && !entity.isVehicle() && entity.canPortal() && VoxelShapes.c(VoxelShapes.a(entity.getBoundingBox().d((double) (-blockposition.getX()), (double) (-blockposition.getY()), (double) (-blockposition.getZ()))), iblockdata.getShape(world, blockposition), OperatorBoolean.AND)) { - ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends - WorldServer worldserver = ((WorldServer) world).getMinecraftServer().getWorldServer(resourcekey); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -@@ -0,0 +0,0 @@ public abstract class BlockFireAbstract extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!entity.isFireProof()) { - entity.setFireTicks(entity.getFireTicks() + 1); - if (entity.getFireTicks() == 0) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockHoney.java b/src/main/java/net/minecraft/world/level/block/BlockHoney.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockHoney.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockHoney.java -@@ -0,0 +0,0 @@ public class BlockHoney extends BlockHalfTransparent { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (this.a(blockposition, entity)) { - this.a(entity, blockposition); - this.d(entity); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockHopper.java b/src/main/java/net/minecraft/world/level/block/BlockHopper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockHopper.java -@@ -0,0 +0,0 @@ public class BlockHopper extends BlockTileEntity { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - TileEntity tileentity = world.getTileEntity(blockposition); - - if (tileentity instanceof TileEntityHopper) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -@@ -0,0 +0,0 @@ public class BlockMinecartDetector extends BlockMinecartTrackAbstract { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - if (!(Boolean) iblockdata.get(BlockMinecartDetector.POWERED)) { - this.a(world, blockposition, iblockdata); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -@@ -0,0 +0,0 @@ public class BlockPortal extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!entity.isPassenger() && !entity.isVehicle() && entity.canPortal()) { - // CraftBukkit start - Entity in portal - EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateAbstract.java -@@ -0,0 +0,0 @@ public abstract class BlockPressurePlateAbstract extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - int i = this.getPower(iblockdata); - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java b/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockSweetBerryBush.java -@@ -0,0 +0,0 @@ public class BlockSweetBerryBush extends BlockPlant implements IBlockFragilePlan - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (entity instanceof EntityLiving && entity.getEntityType() != EntityTypes.FOX && entity.getEntityType() != EntityTypes.BEE) { - entity.a(iblockdata, new Vec3D(0.800000011920929D, 0.75D, 0.800000011920929D)); - if (!world.isClientSide && (Integer) iblockdata.get(BlockSweetBerryBush.a) > 0 && (entity.D != entity.locX() || entity.F != entity.locZ())) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTripwire.java b/src/main/java/net/minecraft/world/level/block/BlockTripwire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTripwire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTripwire.java -@@ -0,0 +0,0 @@ public class BlockTripwire extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide) { - if (!(Boolean) iblockdata.get(BlockTripwire.POWERED)) { - this.a(world, blockposition); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java b/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockWaterLily.java -@@ -0,0 +0,0 @@ public class BlockWaterLily extends BlockPlant { - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { - super.a(iblockdata, world, blockposition, entity); -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (world instanceof WorldServer && entity instanceof EntityBoat && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { // CraftBukkit - world.a(new BlockPosition(blockposition), true, entity); - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockWeb.java b/src/main/java/net/minecraft/world/level/block/BlockWeb.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockWeb.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockWeb.java -@@ -0,0 +0,0 @@ public class BlockWeb extends Block { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - entity.a(iblockdata, new Vec3D(0.25D, 0.05000000074505806D, 0.25D)); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java b/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockWitherRose.java -@@ -0,0 +0,0 @@ public class BlockWitherRose extends BlockFlowers { - - @Override - public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Entity entity) { -+ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition)).callEvent()) { return; } // Paper - if (!world.isClientSide && world.getDifficulty() != EnumDifficulty.PEACEFUL) { - if (entity instanceof EntityLiving) { - EntityLiving entityliving = (EntityLiving) entity; diff --git a/Spigot-Server-Patches/Add-EntityLoadCrossbowEvent.patch b/Spigot-Server-Patches/Add-EntityLoadCrossbowEvent.patch deleted file mode 100644 index 2b8925dae2..0000000000 --- a/Spigot-Server-Patches/Add-EntityLoadCrossbowEvent.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: Wed, 7 Oct 2020 12:04:01 -0400 -Subject: [PATCH] Add EntityLoadCrossbowEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java -+++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -@@ -0,0 +0,0 @@ package net.minecraft.world.item; - import com.google.common.collect.Lists; - import com.mojang.math.Quaternion; - import com.mojang.math.Vector3fa; -+import org.bukkit.inventory.EquipmentSlot; // Paper -+import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; // Paper - EntityLoadCrossbowEvent namespace conflicts - import java.util.List; - import java.util.Random; - import java.util.function.Predicate; -@@ -0,0 +0,0 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - int j = this.e_(itemstack) - i; - float f = a(j, itemstack); - -- if (f >= 1.0F && !d(itemstack) && a(entityliving, itemstack)) { -+ // Paper start - EntityLoadCrossbowEvent -+ if (f >= 1.0F && !d(itemstack) /*&& a(entityliving, itemstack)*/) { -+ final EntityLoadCrossbowEvent event = new EntityLoadCrossbowEvent(entityliving.getBukkitLivingEntity(), itemstack.asBukkitMirror(), entityliving.getRaisedHand() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND); -+ if (!event.callEvent() || !attemptProjectileLoad(entityliving, itemstack, event.shouldConsumeItem())) return; -+ // Paper end - a(itemstack, true); - SoundCategory soundcategory = entityliving instanceof EntityHuman ? SoundCategory.PLAYERS : SoundCategory.HOSTILE; - -@@ -0,0 +0,0 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - - } - -- private static boolean a(EntityLiving entityliving, ItemStack itemstack) { -+ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow) { return a(ent, bow); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean attemptProjectileLoad(EntityLiving ent, ItemStack bow, boolean consume) { return a(ent, bow, consume); } // Paper - EntityLoadCrossbowEvent - OBFHELPER -+ private static boolean a(EntityLiving entityliving, ItemStack itemstack) { return a(entityliving, itemstack, true); };// Paper - add consume -+ private static boolean a(EntityLiving entityliving, ItemStack itemstack, boolean consume) { // Paper - add consume - int i = EnchantmentManager.getEnchantmentLevel(Enchantments.MULTISHOT, itemstack); - int j = i == 0 ? 1 : 3; -- boolean flag = entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; -+ boolean flag = !consume || entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.canInstantlyBuild; // Paper - add consme - ItemStack itemstack1 = entityliving.f(itemstack); - ItemStack itemstack2 = itemstack1.cloneItemStack(); - diff --git a/Spigot-Server-Patches/Add-EntityZapEvent.patch b/Spigot-Server-Patches/Add-EntityZapEvent.patch deleted file mode 100644 index d1f62144c0..0000000000 --- a/Spigot-Server-Patches/Add-EntityZapEvent.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Sun, 16 Oct 2016 23:19:30 -0700 -Subject: [PATCH] Add EntityZapEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -0,0 +0,0 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - } - - entitypigzombie.setPersistent(); -+ // Paper start -+ if (CraftEventFactory.callEntityZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - EntityVillager.LOGGER.info("Villager {} was struck by lightning {}.", this, entitylightning); - EntityWitch entitywitch = (EntityWitch) EntityTypes.WITCH.a((World) worldserver); - -+ // Paper start -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) { -+ return; -+ } -+ // Paper end -+ - entitywitch.setPositionRotation(this.locX(), this.locY(), this.locZ(), this.yaw, this.pitch); - entitywitch.prepare(worldserver, worldserver.getDamageScaler(entitywitch.getChunkCoordinates()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (NBTTagCompound) null); - entitywitch.setNoAI(this.isNoAI()); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.EntityZapEvent callEntityZapEvent (Entity entity, Entity lightning, Entity changedEntity) { -+ com.destroystokyo.paper.event.entity.EntityZapEvent event = new com.destroystokyo.paper.event.entity.EntityZapEvent(entity.getBukkitEntity(), (LightningStrike) lightning.getBukkitEntity(), changedEntity.getBukkitEntity()); -+ entity.getBukkitEntity().getServer().getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static HorseJumpEvent callHorseJumpEvent(Entity horse, float power) { - HorseJumpEvent event = new HorseJumpEvent((AbstractHorse) horse.getBukkitEntity(), power); - horse.getBukkitEntity().getServer().getPluginManager().callEvent(event); diff --git a/Spigot-Server-Patches/Add-Heightmap-API.patch b/Spigot-Server-Patches/Add-Heightmap-API.patch deleted file mode 100644 index 49c2f327c7..0000000000 --- a/Spigot-Server-Patches/Add-Heightmap-API.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 1 Jan 2019 02:22:01 -0800 -Subject: [PATCH] Add Heightmap API - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - } - -- @Override -- public int a(HeightMap.Type heightmap_type, int i, int j) { -+ public final int getHighestBlockY(final HeightMap.Type heightmap, final int x, final int z) { return this.a(heightmap, x, z); } // Paper - OBFHELPER -+ @Override public int a(HeightMap.Type heightmap_type, int i, int j) { // Paper - OBFHELPER - int k; - - if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - return getHighestBlockYAt(x, z, org.bukkit.HeightMap.MOTION_BLOCKING); - } - -+ // Paper start - Implement heightmap api -+ @Override -+ public int getHighestBlockYAt(final int x, final int z, final com.destroystokyo.paper.HeightmapType heightmap) throws UnsupportedOperationException { -+ this.getChunkAt(x >> 4, z >> 4); // heightmap will ret 0 on unloaded areas -+ -+ switch (heightmap) { -+ case LIGHT_BLOCKING: -+ throw new UnsupportedOperationException(); // TODO -+ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); -+ case ANY: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.WORLD_SURFACE, x, z); -+ case SOLID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.OCEAN_FLOOR, x, z); -+ case SOLID_OR_LIQUID: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING, x, z); -+ case SOLID_OR_LIQUID_NO_LEAVES: -+ return this.world.getHighestBlockY(net.minecraft.world.level.levelgen.HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, x, z); -+ default: -+ throw new UnsupportedOperationException(); -+ } -+ } -+ // Paper end -+ - @Override - public Location getSpawnLocation() { - BlockPosition spawn = world.getSpawn(); diff --git a/Spigot-Server-Patches/Add-LivingEntity-clearActiveItem.patch b/Spigot-Server-Patches/Add-LivingEntity-clearActiveItem.patch deleted file mode 100644 index 8d7c280205..0000000000 --- a/Spigot-Server-Patches/Add-LivingEntity-clearActiveItem.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anrza -Date: Wed, 15 Jul 2020 12:08:49 +0200 -Subject: [PATCH] Add LivingEntity#clearActiveItem - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().activeItem.asBukkitMirror(); - } - -+ // Paper start -+ @Override -+ public void clearActiveItem() { -+ getHandle().clearActiveItem(); -+ } -+ // Paper end -+ - @Override - public int getItemUseRemainingTime() { - return getHandle().getItemUseRemainingTime(); diff --git a/Spigot-Server-Patches/Add-LivingEntity-getTargetEntity.patch b/Spigot-Server-Patches/Add-LivingEntity-getTargetEntity.patch deleted file mode 100644 index d28faf0a3b..0000000000 --- a/Spigot-Server-Patches/Add-LivingEntity-getTargetEntity.patch +++ /dev/null @@ -1,187 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 22 Sep 2018 00:33:08 -0500 -Subject: [PATCH] Add LivingEntity#getTargetEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.c(f - 90.0F, f1); - } - -+ public final Vec3D getEyePosition(float partialTicks) { return j(partialTicks); } // Paper - OBFHELPER - public final Vec3D j(float f) { - if (f == 1.0F) { - return new Vec3D(this.locX(), this.getHeadY(), this.locZ()); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.getPassengers().size() < 1; - } - -+ public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER - public float bg() { - return 0.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameterSet - import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.ScoreboardTeam; - import org.apache.logging.log4j.Logger; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return world.rayTrace(raytrace); - } - -+ public MovingObjectPositionEntity getTargetEntity(int maxDistance) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3D start = this.getEyePosition(1.0F); -+ Vec3D direction = this.getLookDirection(); -+ Vec3D end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); -+ -+ List entityList = world.getEntities(this, getBoundingBox().expand(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).grow(1.0D, 1.0D, 1.0D), IEntitySelector.canAITarget().and(Entity::isInteractable)); -+ -+ double distance = 0.0D; -+ MovingObjectPositionEntity result = null; -+ -+ for (Entity entity : entityList) { -+ AxisAlignedBB aabb = entity.getBoundingBox().grow((double) entity.getCollisionBorderSize()); -+ Optional rayTraceResult = aabb.calculateIntercept(start, end); -+ -+ if (rayTraceResult.isPresent()) { -+ Vec3D rayTrace = rayTraceResult.get(); -+ double distanceTo = start.distanceSquared(rayTrace); -+ if (distanceTo < distance || distance == 0.0D) { -+ result = new MovingObjectPositionEntity(entity, rayTrace); -+ distance = distanceTo; -+ } -+ } -+ } -+ -+ return result; -+ } -+ - public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -0,0 +0,0 @@ public final class IEntitySelector { - public static final Predicate e = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative(); - }; -+ public static Predicate canAITarget() { return f; } // Paper - OBFHELPER - public static final Predicate f = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; - }; -diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -@@ -0,0 +0,0 @@ public class AxisAlignedBB { - return this.b(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final AxisAlignedBB expand(double x, double y, double z) { return b(x, y, z); } // Paper - OBFHELPER - public AxisAlignedBB b(double d0, double d1, double d2) { - double d3 = this.minX; - double d4 = this.minY; -@@ -0,0 +0,0 @@ public class AxisAlignedBB { - return new AxisAlignedBB(d3, d4, d5, d6, d7, d8); - } - -+ // Paper start -+ public AxisAlignedBB grow(double d0) { -+ return grow(d0, d0, d0); -+ } -+ // Paper end -+ - public AxisAlignedBB grow(double d0, double d1, double d2) { - double d3 = this.minX - d0; - double d4 = this.minY - d1; -@@ -0,0 +0,0 @@ public class AxisAlignedBB { - return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; - } - -+ public final boolean contains(Vec3D vec3d) { return d(vec3d); } // Paper - OBFHELPER - public boolean d(Vec3D vec3d) { - return this.e(vec3d.x, vec3d.y, vec3d.z); - } -@@ -0,0 +0,0 @@ public class AxisAlignedBB { - return this.g(-d0); - } - -+ public final Optional calculateIntercept(Vec3D vec3d, Vec3D vec3d1) { return b(vec3d, vec3d1); } // Paper - OBFHELPER - public Optional b(Vec3D vec3d, Vec3D vec3d1) { - double[] adouble = new double[]{1.0D}; - double d0 = vec3d1.x - vec3d.x; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.entity.TargetEntityInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.entity.projectile.EntityThrownTrident; - import net.minecraft.world.entity.projectile.EntityTippedArrow; - import net.minecraft.world.entity.projectile.EntityWitherSkull; -+import net.minecraft.world.level.RayTrace; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.world.phys.Vec3D; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), - MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); - } -+ -+ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); -+ } -+ -+ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); -+ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getPos().x, rayTrace.getPos().y, rayTrace.getPos().z)); -+ } -+ -+ public MovingObjectPositionEntity rayTraceEntity(int maxDistance, boolean ignoreBlocks) { -+ MovingObjectPositionEntity rayTrace = getHandle().getTargetEntity(maxDistance); -+ if (rayTrace == null) { -+ return null; -+ } -+ if (!ignoreBlocks) { -+ MovingObjectPosition rayTraceBlocks = getHandle().getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); -+ if (rayTraceBlocks != null) { -+ Vec3D eye = getHandle().getEyePosition(1.0F); -+ if (eye.distanceSquared(rayTraceBlocks.getPos()) <= eye.distanceSquared(rayTrace.getPos())) { -+ return null; -+ } -+ } -+ } -+ return rayTrace; -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/Add-MinecraftKey-Information-to-Objects.patch b/Spigot-Server-Patches/Add-MinecraftKey-Information-to-Objects.patch deleted file mode 100644 index 19038b684a..0000000000 --- a/Spigot-Server-Patches/Add-MinecraftKey-Information-to-Objects.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 01:40:13 -0400 -Subject: [PATCH] Add MinecraftKey Information to Objects - -Stores the reference to the objects respective MinecraftKey - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { -- MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch -+ MinecraftKey key = e.getMinecraftKey(); - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -diff --git a/src/main/java/net/minecraft/server/KeyedObject.java b/src/main/java/net/minecraft/server/KeyedObject.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/KeyedObject.java -@@ -0,0 +0,0 @@ -+package net.minecraft.server; -+ -+import net.minecraft.resources.MinecraftKey; -+ -+public interface KeyedObject { -+ MinecraftKey getMinecraftKey(); -+ default String getMinecraftKeyString() { -+ MinecraftKey key = getMinecraftKey(); -+ return key != null ? key.toString() : null; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import org.bukkit.event.player.PlayerTeleportEvent; - import org.bukkit.plugin.PluginManager; - // CraftBukkit end - --public abstract class Entity implements INamableTileEntity, ICommandListener { -+public abstract class Entity implements INamableTileEntity, ICommandListener, net.minecraft.server.KeyedObject { // Paper - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener { - return true; - } - -+ // Paper start -+ private MinecraftKey entityKey; -+ private String entityKeyString; -+ -+ @Override -+ public MinecraftKey getMinecraftKey() { -+ if (entityKey == null) { -+ this.entityKey = EntityTypes.getName(this.getEntityType()); -+ this.entityKeyString = this.entityKey != null ? this.entityKey.toString() : null; -+ } -+ return entityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. see: https://github.com/PaperMC/Paper/issues/1280 -+ return entityKeyString; -+ } - @Nullable - public final String getSaveID() { - EntityTypes entitytypes = this.getEntityType(); - MinecraftKey minecraftkey = EntityTypes.getName(entitytypes); - -- return entitytypes.a() && minecraftkey != null ? minecraftkey.toString() : null; -+ return entitytypes != null && entitytypes.isPersistable() ? getMinecraftKeyString() : null; -+ // Paper end - } - - protected abstract void loadData(NBTTagCompound nbttagcompound); -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ public class EntityTypes { - } - } - -+ public boolean isPersistable() { return a(); } // Paper - OBFHELPER - public boolean a() { - return this.bi; - } -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ import org.bukkit.inventory.InventoryHolder; - - import org.spigotmc.CustomTimingsHandler; // Spigot - --public abstract class TileEntity { -+public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper - - public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot - // CraftBukkit start - data containers -@@ -0,0 +0,0 @@ public abstract class TileEntity { - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -- private final TileEntityTypes tileType; -+ private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER - @Nullable - protected World world; - protected BlockPosition position; -@@ -0,0 +0,0 @@ public abstract class TileEntity { - this.tileType = tileentitytypes; - } - -+ // Paper start -+ private String tileEntityKeyString = null; -+ private MinecraftKey tileEntityKey = null; -+ -+ @Override -+ public MinecraftKey getMinecraftKey() { -+ if (tileEntityKey == null) { -+ tileEntityKey = TileEntityTypes.a(this.getTileEntityType()); -+ tileEntityKeyString = tileEntityKey != null ? tileEntityKey.toString() : null; -+ } -+ return tileEntityKey; -+ } -+ -+ @Override -+ public String getMinecraftKeyString() { -+ getMinecraftKey(); // Try to load if it doesn't exists. -+ return tileEntityKeyString; -+ } -+ // Paper end -+ - @Nullable - public World getWorld() { - return this.world; diff --git a/Spigot-Server-Patches/Add-Mob-lookAt-API.patch b/Spigot-Server-Patches/Add-Mob-lookAt-API.patch deleted file mode 100644 index f0e9b3ae21..0000000000 --- a/Spigot-Server-Patches/Add-Mob-lookAt-API.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 14 May 2021 13:42:17 -0500 -Subject: [PATCH] Add Mob#lookAt API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - - protected void mobTick() {} - -+ public int getMaxHeadXRot() { return O(); } // Paper - OBFHELPER - public int O() { - return 40; - } - -+ public int getMaxHeadYRot() { return Q(); } // Paper - OBFHELPER - public int Q() { - return 75; - } - -+ public int getHeadRotSpeed() { return ep(); } // Paper - OBFHELPER - public int ep() { - return 10; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerLook.java -@@ -0,0 +0,0 @@ public class ControllerLook { - this.a = entityinsentient; - } - -+ public void lookAt(Vec3D vec3d) { a(vec3d); } // Paper - OBFHELPER - public void a(Vec3D vec3d) { - this.a(vec3d.x, vec3d.y, vec3d.z); - } - -+ // Paper start -+ public void lookAt(Entity entity) { -+ this.lookAt(entity.locX(), getWantedY(entity), entity.locZ()); -+ } -+ // Paper end -+ -+ public void lookAt(Entity entity, float f, float f1) { a(entity, f, f1); } // Paper - OBFHELPER - public void a(Entity entity, float f, float f1) { - this.a(entity.locX(), b(entity), entity.locZ(), f, f1); - } - -+ public void lookAt(double d0, double d1, double d2) { a(d0, d1, d2); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2) { - this.a(d0, d1, d2, (float) this.a.ep(), (float) this.a.O()); - } - -+ public void lookAt(double d0, double d1, double d2, float f, float f1) { a(d0, d1, d2, f, f1); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2, float f, float f1) { - this.e = d0; - this.f = d1; -@@ -0,0 +0,0 @@ public class ControllerLook { - return f + f4; - } - -+ public static double getWantedY(Entity entity) { return b(entity); } // Paper - OBFHELPER - private static double b(Entity entity) { - return entity instanceof EntityLiving ? entity.getHeadY() : (entity.getBoundingBox().minY + entity.getBoundingBox().maxY) / 2.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -0,0 +0,0 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public boolean isInDaylight() { - return getHandle().isInDaylight(); - } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getControllerLook().lookAt(location.getX(), location.getY(), location.getZ()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.Location location, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(location, "location cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(location.getWorld().equals(getWorld()), "location in a different world"); -+ getHandle().getControllerLook().lookAt(location.getX(), location.getY(), location.getZ(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getControllerLook().lookAt(((CraftEntity) entity).getHandle()); -+ } -+ -+ @Override -+ public void lookAt(@org.jetbrains.annotations.NotNull org.bukkit.entity.Entity entity, float headRotationSpeed, float maxHeadPitch) { -+ com.google.common.base.Preconditions.checkNotNull(entity, "entity cannot be null"); -+ com.google.common.base.Preconditions.checkArgument(entity.getWorld().equals(getWorld()), "entity in a different world"); -+ getHandle().getControllerLook().lookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z) { -+ getHandle().getControllerLook().lookAt(x, y, z); -+ } -+ -+ @Override -+ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { -+ getHandle().getControllerLook().lookAt(x, y, z, headRotationSpeed, maxHeadPitch); -+ } -+ -+ @Override -+ public int getHeadRotationSpeed() { -+ return getHandle().getHeadRotSpeed(); -+ } -+ -+ @Override -+ public int getMaxHeadPitch() { -+ return getHandle().getMaxHeadXRot(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Add-More-Creeper-API.patch b/Spigot-Server-Patches/Add-More-Creeper-API.patch deleted file mode 100644 index cd6be16983..0000000000 --- a/Spigot-Server-Patches/Add-More-Creeper-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 11:50:26 -0500 -Subject: [PATCH] Add More Creeper API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -0,0 +0,0 @@ public class EntityCreeper extends EntityMonster { - } - - public void ignite() { -- this.datawatcher.set(EntityCreeper.d, true); -+ // Paper start -+ setIgnited(true); -+ } -+ -+ public void setIgnited(boolean ignited) { -+ if (isIgnited() != ignited) { -+ com.destroystokyo.paper.event.entity.CreeperIgniteEvent event = new com.destroystokyo.paper.event.entity.CreeperIgniteEvent((org.bukkit.entity.Creeper) getBukkitEntity(), ignited); -+ if (event.callEvent()) { -+ this.datawatcher.set(EntityCreeper.d, event.isIgnited()); -+ } -+ } -+ // Paper end - } - - public boolean canCauseHeadDrop() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -@@ -0,0 +0,0 @@ public class CraftCreeper extends CraftMonster implements Creeper { - public EntityType getType() { - return EntityType.CREEPER; - } -+ -+ // Paper start -+ public void setIgnited(boolean ignited) { -+ getHandle().setIgnited(ignited); -+ } -+ -+ public boolean isIgnited() { -+ return getHandle().isIgnited(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Spigot-Server-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch deleted file mode 100644 index 38f95c17fa..0000000000 --- a/Spigot-Server-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:43:39 -0800 -Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult - - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return BedEnterResult.TOO_FAR_AWAY; - case NOT_SAFE: - return BedEnterResult.NOT_SAFE; -+ // Paper start -+ case OBSTRUCTED: -+ return BedEnterResult.OBSTRUCTED; -+ // Paper end - default: - return BedEnterResult.OTHER_PROBLEM; - } diff --git a/Spigot-Server-Patches/Add-PhantomPreSpawnEvent.patch b/Spigot-Server-Patches/Add-PhantomPreSpawnEvent.patch deleted file mode 100644 index 83c8df0848..0000000000 --- a/Spigot-Server-Patches/Add-PhantomPreSpawnEvent.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 25 Aug 2018 19:56:51 -0500 -Subject: [PATCH] Add PhantomPreSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - } - - this.setSize(nbttagcompound.getInt("Size")); -+ // Paper start -+ if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { -+ this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); -+ } -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - nbttagcompound.setInt("AY", this.d.getY()); - nbttagcompound.setInt("AZ", this.d.getZ()); - nbttagcompound.setInt("Size", this.getSize()); -+ // Paper start -+ if (this.spawningEntity != null) { -+ nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - return entitysize.a(f); - } - -+ // Paper start -+ java.util.UUID spawningEntity; -+ -+ public java.util.UUID getSpawningEntity() { -+ return spawningEntity; -+ } -+ public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ // Paper end -+ - class b extends PathfinderGoal { - - private final PathfinderTargetCondition b; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -@@ -0,0 +0,0 @@ import java.util.Iterator; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.stats.ServerStatisticManager; -@@ -0,0 +0,0 @@ public class MobSpawnerPhantom implements MobSpawner { - int k = 1 + random.nextInt(difficultydamagescaler.a().a() + 1); - - for (int l = 0; l < k; ++l) { -+ // Paper start -+ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(worldserver, blockposition1), ((EntityPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ // Paper end - EntityPhantom entityphantom = (EntityPhantom) EntityTypes.PHANTOM.a((World) worldserver); -- -+ entityphantom.setSpawningEntity(entityhuman.getUniqueID()); // Paper - entityphantom.setPositionRotation(blockposition1, 0.0F, 0.0F); - groupdataentity = entityphantom.prepare(worldserver, difficultydamagescaler, EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null); - worldserver.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -0,0 +0,0 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public EntityType getType() { - return EntityType.PHANTOM; - } -+ -+ // Paper start -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().getSpawningEntity(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-PlayerArmorChangeEvent.patch b/Spigot-Server-Patches/Add-PlayerArmorChangeEvent.patch deleted file mode 100644 index f39ec8aaf3..0000000000 --- a/Spigot-Server-Patches/Add-PlayerArmorChangeEvent.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: pkt77 -Date: Fri, 10 Nov 2017 23:46:34 -0500 -Subject: [PATCH] Add PlayerArmorChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.entity; - -+import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Paper - import com.google.common.base.Objects; - import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - ItemStack itemstack1 = this.getEquipment(enumitemslot); - - if (!ItemStack.matches(itemstack1, itemstack)) { -+ // Paper start - PlayerArmorChangeEvent -+ if (this instanceof EntityPlayer && enumitemslot.getType() == EnumItemSlot.Function.ARMOR) { -+ final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack); -+ final org.bukkit.inventory.ItemStack newItem = CraftItemStack.asBukkitCopy(itemstack1); -+ new PlayerArmorChangeEvent((Player) this.getBukkitEntity(), PlayerArmorChangeEvent.SlotType.valueOf(enumitemslot.name()), oldItem, newItem).callEvent(); -+ } -+ // Paper end - if (map == null) { - map = Maps.newEnumMap(EnumItemSlot.class); - } -diff --git a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -+++ b/src/main/java/net/minecraft/world/entity/EnumItemSlot.java -@@ -0,0 +0,0 @@ public enum EnumItemSlot { - this.j = s; - } - -+ public EnumItemSlot.Function getType() { return this.a(); } // Paper - OBFHELPER - public EnumItemSlot.Function a() { - return this.g; - } diff --git a/Spigot-Server-Patches/Add-PlayerAttackEntityCooldownResetEvent.patch b/Spigot-Server-Patches/Add-PlayerAttackEntityCooldownResetEvent.patch deleted file mode 100644 index cf7c5bf392..0000000000 --- a/Spigot-Server-Patches/Add-PlayerAttackEntityCooldownResetEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: nossr50 -Date: Thu, 26 Mar 2020 19:44:50 -0700 -Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); - if (damagesource.getEntity() instanceof EntityHuman) { -- ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired -+ // Paper start - PlayerAttackEntityCooldownResetEvent -+ if (damagesource.getEntity() instanceof EntityPlayer) { -+ EntityPlayer player = (EntityPlayer) damagesource.getEntity(); -+ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackCooldown(0F)).callEvent()) { -+ player.resetAttackCooldown(); -+ } -+ } else { -+ ((EntityHuman) damagesource.getEntity()).resetAttackCooldown(); -+ } -+ // Paper end - } - if (event.isCancelled()) { - return false; diff --git a/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch b/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch deleted file mode 100644 index 6acea9bc30..0000000000 --- a/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 7 Oct 2018 12:05:28 -0700 -Subject: [PATCH] Add PlayerConnectionCloseEvent - -This event is invoked when a player has disconnected. It is guaranteed that, -if the server is in online-mode, that the provided uuid and username have been -validated. - -The event is invoked for players who have not yet logged into the world, whereas -PlayerQuitEvent is only invoked on players who have logged into the world. - -The event is invoked for players who have already logged into the world, -although whether or not the player exists in the world at the time of -firing is undefined. (That is, whether the plugin can retrieve a Player object -using the event parameters is undefined). However, it is guaranteed that this -event is invoked AFTER PlayerQuitEvent, if the player has already logged into -the world. - -This event is guaranteed to never fire unless AsyncPlayerPreLoginEvent has -been called beforehand, and this event may not be called in parallel with -AsyncPlayerPreLoginEvent for the same connection. - -Cancelling the AsyncPlayerPreLoginEvent guarantees the corresponding -PlayerConnectionCloseEvent is never called. - -The event may be invoked asynchronously or synchronously. As it stands, -it is never invoked asynchronously. However, plugins should check -Event#isAsynchronous to be future-proof. - -On purpose, the deprecated PlayerPreLoginEvent event is left out of the -API spec for this event. Plugins should not be using that event, and -how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent -is undefined. - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - this.j().a(new ChatMessage("multiplayer.disconnect.generic")); - } - this.packetQueue.clear(); // Free up packet queue. -+ // Paper start - Add PlayerConnectionCloseEvent -+ final PacketListener packetListener = this.j(); -+ if (packetListener instanceof PlayerConnection) { -+ /* Player was logged in */ -+ final PlayerConnection playerConnection = (PlayerConnection) packetListener; -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUniqueID(), -+ playerConnection.player.getName(), ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); -+ } else if (packetListener instanceof LoginListener) { -+ /* Player is login stage */ -+ final LoginListener loginListener = (LoginListener) packetListener; -+ switch (loginListener.getLoginState()) { -+ case READY_TO_ACCEPT: -+ case DELAY_ACCEPT: -+ case ACCEPTED: -+ final com.mojang.authlib.GameProfile profile = loginListener.getGameProfile(); /* Should be non-null at this stage */ -+ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(profile.getId(), profile.getName(), -+ ((java.net.InetSocketAddress)socketAddress).getAddress(), false).callEvent(); -+ } -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - private final byte[] e = new byte[4]; - private final MinecraftServer server; - public final NetworkManager networkManager; -- private LoginListener.EnumProtocolState g; -+ private LoginListener.EnumProtocolState g; public final LoginListener.EnumProtocolState getLoginState() { return this.g; }; // Paper - OBFHELPER - private int h; -- private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER -+ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } public GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER - private final String j; - private SecretKey loginKey; - private EntityPlayer l; diff --git a/Spigot-Server-Patches/Add-PlayerInitialSpawnEvent.patch b/Spigot-Server-Patches/Add-PlayerInitialSpawnEvent.patch deleted file mode 100644 index e52ae43861..0000000000 --- a/Spigot-Server-Patches/Add-PlayerInitialSpawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Steve Anton -Date: Thu, 3 Mar 2016 00:09:38 -0600 -Subject: [PATCH] Add PlayerInitialSpawnEvent - -For modifying a player's initial spawn location as they join the server - -This is a duplicate API from spigot, so use our duplicate subclass and -improve setPosition to use raw - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - // Spigot start - spawn location event - Player bukkitPlayer = entityplayer.getBukkitEntity(); -- org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(bukkitPlayer, bukkitPlayer.getLocation()); -+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(bukkitPlayer, bukkitPlayer.getLocation()); // Paper use our duplicate event - cserver.getPluginManager().callEvent(ev); - - Location loc = ev.getSpawnLocation(); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - entityplayer.spawnIn(worldserver1); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); -- entityplayer.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); -+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world) -+ entityplayer.setPositionRaw(loc.getX(), loc.getY(), loc.getZ()); -+ entityplayer.setYawPitch(loc.getYaw(), loc.getPitch()); -+ // Paper end - // Spigot end - - // CraftBukkit - Moved message to after join -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return d1 * d1 + d2 * d2 + d3 * d3 < d0 * d0; - } - -- protected void setYawPitch(float f, float f1) { -+ public void setYawPitch(float f, float f1) { // Paper - protected -> public - // CraftBukkit start - yaw was sometimes set to NaN, so we need to set it back to 0 - if (Float.isNaN(f)) { - f = 0; diff --git a/Spigot-Server-Patches/Add-PlayerItemCooldownEvent.patch b/Spigot-Server-Patches/Add-PlayerItemCooldownEvent.patch deleted file mode 100644 index 967b3ae655..0000000000 --- a/Spigot-Server-Patches/Add-PlayerItemCooldownEvent.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -Date: Tue, 25 Aug 2020 13:48:33 +0200 -Subject: [PATCH] Add PlayerItemCooldownEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -+++ b/src/main/java/net/minecraft/world/item/ItemCooldownPlayer.java -@@ -0,0 +0,0 @@ package net.minecraft.world.item; - import net.minecraft.network.protocol.game.PacketPlayOutSetCooldown; - import net.minecraft.server.level.EntityPlayer; - -+import io.papermc.paper.event.player.PlayerItemCooldownEvent; // Paper -+ - public class ItemCooldownPlayer extends ItemCooldown { - -- private final EntityPlayer a; -+ private final EntityPlayer a; public EntityPlayer getEntityPlayer() { return a; } // Paper - OBFHELPER - - public ItemCooldownPlayer(EntityPlayer entityplayer) { - this.a = entityplayer; - } - -+ // Paper start -+ @Override -+ public void setCooldown(Item item, int ticks) { -+ PlayerItemCooldownEvent event = new PlayerItemCooldownEvent(getEntityPlayer().getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), ticks); -+ if (event.callEvent()) { -+ super.setCooldown(item, event.getCooldown()); -+ } -+ } -+ // Paper end -+ - @Override - protected void b(Item item, int i) { - super.b(item, i); diff --git a/Spigot-Server-Patches/Add-PlayerJumpEvent.patch b/Spigot-Server-Patches/Add-PlayerJumpEvent.patch deleted file mode 100644 index ecd171d834..0000000000 --- a/Spigot-Server-Patches/Add-PlayerJumpEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Thu, 28 Sep 2017 17:21:44 -0400 -Subject: [PATCH] Add PlayerJumpEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - boolean flag = d8 > 0.0D; - - if (this.player.isOnGround() && !packetplayinflying.b() && flag) { -- this.player.jump(); -+ // Paper start - Add player jump event -+ Player player = this.getPlayer(); -+ Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. -+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location. -+ -+ // If the packet contains movement information then we update the To location with the correct XYZ. -+ if (packetplayinflying.hasPos) { -+ to.setX(packetplayinflying.x); -+ to.setY(packetplayinflying.y); -+ to.setZ(packetplayinflying.z); -+ } -+ -+ // If the packet contains look information then we update the To location with the correct Yaw & Pitch. -+ if (packetplayinflying.hasLook) { -+ to.setYaw(packetplayinflying.yaw); -+ to.setPitch(packetplayinflying.pitch); -+ } -+ -+ com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); -+ -+ if (event.callEvent()) { -+ this.player.jump(); -+ } else { -+ from = event.getFrom(); -+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); -+ return; -+ } -+ // Paper end - } - - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); diff --git a/Spigot-Server-Patches/Add-PlayerKickEvent-causes.patch b/Spigot-Server-Patches/Add-PlayerKickEvent-causes.patch deleted file mode 100644 index 4fe4eaf2c7..0000000000 --- a/Spigot-Server-Patches/Add-PlayerKickEvent-causes.patch +++ /dev/null @@ -1,393 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 20:30:45 -0700 -Subject: [PATCH] Add PlayerKickEvent causes - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); -- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_PLAYER); // Paper - use configurable kick message & kick event cause - return; - } - } else { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { - if (++this.E > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); -- this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage, org.bukkit.event.player.PlayerKickEvent.Cause.FLYING_VEHICLE); // Paper - use configurable kick message & kick event cause - return; - } - } else { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.isPendingPing()) { - if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected - PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info -- this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); -+ this.disconnect(new ChatMessage("disconnect.timeout", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - } - } else { - if (elapsedTime >= 15000L) { // 15 seconds -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (this.player.F() > 0L && this.minecraftServer.getIdleTimeout() > 0 && SystemUtils.getMonotonicMillis() - this.player.F() > (long) (this.minecraftServer.getIdleTimeout() * 1000 * 60)) { - this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 -- this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause - } - - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - public void disconnect(String s) { - // Paper start -- this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); -+ } -+ -+ public void disconnect(String s, PlayerKickEvent.Cause cause) { -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s), cause); - } - - public void disconnect(final IChatBaseComponent reason) { -- this.disconnect(PaperAdventure.asAdventure(reason)); -+ this.disconnect(PaperAdventure.asAdventure(reason), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); -+ } -+ -+ public void disconnect(final IChatBaseComponent reason, PlayerKickEvent.Cause cause) { -+ this.disconnect(PaperAdventure.asAdventure(reason), cause); - } - -- public void disconnect(net.kyori.adventure.text.Component reason) { -+ public void disconnect(net.kyori.adventure.text.Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause) { - // Paper end - // CraftBukkit start - fire PlayerKickEvent - if (this.processedDisconnect) { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - -- PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure -+ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage, cause); // Paper - Adventure & kick event reason - - if (this.server.getServer().isRunning()) { - this.server.getPluginManager().callEvent(event); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInVehicleMove packetplayinvehiclemove) { - PlayerConnectionUtils.ensureMainThread(packetplayinvehiclemove, this, this.player.getWorldServer()); - if (b(packetplayinvehiclemove)) { -- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_vehicle_movement")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause - } else { - Entity entity = this.player.getRootVehicle(); - -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start - if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable -- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - // Paper start - String str = packetplayintabcomplete.c(); int index = -1; - if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - // Paper end -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Paper start - validate pick item position - if (!(packetplayinpickitem.b() >= 0 && packetplayinpickitem.b() < this.player.inventory.items.size())) { - PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); -- this.disconnect("Invalid hotbar selection (Hacking?)"); -+ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - this.player.inventory.c(packetplayinpickitem.b()); // Paper - Diff above if changed -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - NBTTagList pageList = testStack.getTag().getList("pages", 8); - if (pageList.size() > 100) { - PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); -- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - long byteTotal = 0; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; - if (byteLength > 256 * 4) { - PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); -- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - byteTotal += byteLength; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (byteTotal > byteAllowed) { - PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -- minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause - return; - } - } - // Paper end - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { -- this.disconnect("Book edited too quickly!"); -+ this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - this.lastBookTick = MinecraftServer.currentTick; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInFlying packetplayinflying) { - PlayerConnectionUtils.ensureMainThread(packetplayinflying, this, this.player.getWorldServer()); - if (b(packetplayinflying)) { -- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_player_movement")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause - } else { - WorldServer worldserver = this.player.getWorldServer(); - -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.dropCount++; - if (this.dropCount >= 20) { - LOGGER.warn(this.player.getName() + " dropped their items too quickly!"); -- this.disconnect("You dropped your items too quickly (Hacking?)"); -+ this.disconnect("You dropped your items too quickly (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause - return; - } - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.resetIdleTimer(); - } else { - PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); -- this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit -+ this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause - } - } - -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters")); -+ PlayerConnection.this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - return null; - } - }; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - throw new RuntimeException(e); - } - } else { -- this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - kick event cause - } - // CraftBukkit end - return; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- PlayerConnection.this.disconnect(new ChatMessage("disconnect.spam")); -+ PlayerConnection.this.disconnect(new ChatMessage("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause - return null; - } - }; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - throw new RuntimeException(e); - } - } else { -- this.disconnect(new ChatMessage("disconnect.spam")); -+ this.disconnect(new ChatMessage("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause - } - // CraftBukkit end - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Spigot Start - if ( entity == player && !player.isSpectator() ) - { -- disconnect( "Cannot interact with self!" ); -+ disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - kick event cause - return; - } - // Spigot End -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - } else if (packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK) { - if (entity instanceof EntityItem || entity instanceof EntityExperienceOrb || entity instanceof EntityArrow || (entity == this.player && !player.isSpectator())) { // CraftBukkit -- this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked")); -+ this.disconnect(new ChatMessage("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - kick event cause - PlayerConnection.LOGGER.warn("Player {} tried to attack an invalid entity", this.player.getDisplayName().getString()); - return; - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Paper start - if (!Bukkit.isPrimaryThread()) { - if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { -- minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause - return; - } - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } else if (!this.isExemptPlayer()) { - // Paper start - This needs to be handled on the main thread for plugins - minecraftServer.scheduleOnMain(() -> { -- this.disconnect(new ChatMessage("disconnect.timeout")); -+ this.disconnect(new ChatMessage("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - }); - // Paper end - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t register custom payload", ex); -- this.disconnect("Invalid payload REGISTER!"); -+ this.disconnect("Invalid payload REGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } else if (packetplayincustompayload.tag.equals(CUSTOM_UNREGISTER)) { - try { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t unregister custom payload", ex); -- this.disconnect("Invalid payload UNREGISTER!"); -+ this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } else { - try { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packetplayincustompayload.tag.toString(), data); - } catch (Exception ex) { - PlayerConnection.LOGGER.error("Couldn\'t dispatch custom payload", ex); -- this.disconnect("Invalid custom payload!"); -+ this.disconnect("Invalid custom payload!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause - } - } - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - while (iterator.hasNext()) { - entityplayer = (EntityPlayer) iterator.next(); - savePlayerFile(entityplayer); // CraftBukkit - Force the player's inventory to be saved -- entityplayer.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0])); -+ entityplayer.playerConnection.disconnect(new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.DUPLICATE_LOGIN); // Paper - kick event cause - } - - // Instead of kicking then returning, we need to store the kick reason -@@ -0,0 +0,0 @@ public abstract class PlayerList { - public void shutdown(boolean isRestarting) { - // CraftBukkit start - disconnect safely - for (EntityPlayer player : this.players) { -- if (isRestarting) player.playerConnection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper -- player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure -+ if (isRestarting) player.playerConnection.disconnect(org.spigotmc.SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here) -+ player.playerConnection.disconnect(this.server.server.shutdownMessage(), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // CraftBukkit - add custom shutdown message // Paper - Adventure & KickEventCause (cause is never used here) - } - // CraftBukkit end - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot - if (getHandle().playerConnection == null) return; - -- getHandle().playerConnection.disconnect(message == null ? "" : message); -+ getHandle().playerConnection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause - } - - // Paper start - @Override - public void kick(final net.kyori.adventure.text.Component message) { -+ kick(message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); -+ } -+ -+ @Override -+ public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { - org.spigotmc.AsyncCatcher.catchOp("player kick"); - final PlayerConnection connection = this.getHandle().playerConnection; - if (connection != null) { -- connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); -+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); - } - } - // Paper end -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -0,0 +0,0 @@ public class RestartCommand extends Command - // Kick all players - for ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) - { -- p.playerConnection.disconnect(SpigotConfig.restartMessage); -+ p.playerConnection.disconnect(SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.RESTART_COMMAND); // Paper - kick event reason (cause is never used)) - } - // Give the socket a chance to send the packets - try diff --git a/Spigot-Server-Patches/Add-PlayerShearBlockEvent.patch b/Spigot-Server-Patches/Add-PlayerShearBlockEvent.patch deleted file mode 100644 index 06bc02fb7d..0000000000 --- a/Spigot-Server-Patches/Add-PlayerShearBlockEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Thu, 27 Aug 2020 15:02:48 -0400 -Subject: [PATCH] Add PlayerShearBlockEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -0,0 +0,0 @@ public class Block extends BlockBase implements IMaterial { - - } - -- public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { -+ public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { dropItem(world, blockposition, itemstack); } public static void dropItem(World world, BlockPosition blockposition, ItemStack itemstack) { // Paper - OBFHELPER - if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { - float f = 0.5F; - double d0 = (double) (world.random.nextFloat() * 0.5F) + 0.25D; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBeehive.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - import java.util.Iterator; - import java.util.List; - import java.util.Random; -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; -@@ -0,0 +0,0 @@ public class BlockBeehive extends BlockTileEntity { - - if (i >= 5) { - if (itemstack.getItem() == Items.SHEARS) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.HONEYCOMB, 3))); -+ if (!event.callEvent()) { -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end - world.playSound(entityhuman, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.BLOCK_BEEHIVE_SHEAR, SoundCategory.NEUTRAL, 1.0F, 1.0F); -- a(world, blockposition); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ dropItem(world, blockposition, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ } -+ // Paper end - itemstack.damage(1, entityhuman, (entityhuman1) -> { - entityhuman1.broadcastItemBreak(enumhand); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPumpkin.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.BlockBase; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.MovingObjectPositionBlock; - -+import io.papermc.paper.event.block.PlayerShearBlockEvent; // Paper - PlayerShearBlockEvent namespace conflicts -+ - public class BlockPumpkin extends BlockStemmed { - - protected BlockPumpkin(BlockBase.Info blockbase_info) { -@@ -0,0 +0,0 @@ public class BlockPumpkin extends BlockStemmed { - - if (itemstack.getItem() == Items.SHEARS) { - if (!world.isClientSide) { -+ // Paper start - Add PlayerShearBlockEvent -+ PlayerShearBlockEvent event = new PlayerShearBlockEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), MCUtil.toBukkitBlock(world, blockposition), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (enumhand == EnumHand.OFF_HAND ? org.bukkit.inventory.EquipmentSlot.OFF_HAND : org.bukkit.inventory.EquipmentSlot.HAND), new java.util.ArrayList<>()); -+ event.getDrops().add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(new ItemStack(Items.PUMPKIN_SEEDS, 4))); -+ if (!event.callEvent()) { -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end - EnumDirection enumdirection = movingobjectpositionblock.getDirection(); - EnumDirection enumdirection1 = enumdirection.n() == EnumDirection.EnumAxis.Y ? entityhuman.getDirection().opposite() : enumdirection; - - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PUMPKIN_CARVE, SoundCategory.BLOCKS, 1.0F, 1.0F); - world.setTypeAndData(blockposition, (IBlockData) Blocks.CARVED_PUMPKIN.getBlockData().set(BlockPumpkinCarved.a, enumdirection1), 11); -- EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); -+ // Paper start - Add PlayerShearBlockEvent -+ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { -+ EntityItem entityitem = new EntityItem(world, (double) blockposition.getX() + 0.5D + (double) enumdirection1.getAdjacentX() * 0.65D, (double) blockposition.getY() + 0.1D, (double) blockposition.getZ() + 0.5D + (double) enumdirection1.getAdjacentZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); -+ // Paper end - - entityitem.setMot(0.05D * (double) enumdirection1.getAdjacentX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double) enumdirection1.getAdjacentZ() + world.random.nextDouble() * 0.02D); - world.addEntity(entityitem); -+ } // Paper - Add PlayerShearBlockEvent - itemstack.damage(1, entityhuman, (entityhuman1) -> { - entityhuman1.broadcastItemBreak(enumhand); - }); diff --git a/Spigot-Server-Patches/Add-PlayerUseUnknownEntityEvent.patch b/Spigot-Server-Patches/Add-PlayerUseUnknownEntityEvent.patch deleted file mode 100644 index 6fe855aa24..0000000000 --- a/Spigot-Server-Patches/Add-PlayerUseUnknownEntityEvent.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 05:09:16 -0400 -Subject: [PATCH] Add PlayerUseUnknownEntityEvent - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInUseEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.Vec3D; - - public class PacketPlayInUseEntity implements Packet { - -- private int a; -+ private int a; public int getEntityId() { return this.a; } // Paper - add accessor - private PacketPlayInUseEntity.EnumEntityUseAction action; - private Vec3D c; - private EnumHand d; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - } - } -+ // Paper start - fire event -+ else { -+ this.server.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( -+ this.getPlayer(), -+ packetplayinuseentity.getEntityId(), -+ packetplayinuseentity.b() == PacketPlayInUseEntity.EnumEntityUseAction.ATTACK, -+ packetplayinuseentity.c() == EnumHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND -+ )); -+ } -+ // Paper end - - } - diff --git a/Spigot-Server-Patches/Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/Spigot-Server-Patches/Add-Plugin-Tickets-to-API-Chunk-Methods.patch deleted file mode 100644 index 70f3977097..0000000000 --- a/Spigot-Server-Patches/Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 9 Jun 2020 03:33:03 -0400 -Subject: [PATCH] Add Plugin Tickets to API Chunk Methods - -Like previous versions, plugins loading chunks kept them loaded until -they garbage collected to avoid constant spamming of chunk loads - -This adds tickets to a few more places so that they can be unloaded. - -Additionally, this drops their ticket level to BORDER so they wont be ticking -so they will just sit inactive instead. - -Using .loadChunk to keep a chunk ticking was a horrible idea for upstream -when we have TWO methods that are able to do that already in the API. - -Also reduce their collection count down to a maximum of 1 second. Barely -anyone knows what chunk-gc is in bukkit.yml as its less relevant now, and -since this wasn't spigot behavior, this is safe to mostly ignore (unless someone -wants it to collect even faster, they can restore that setting back to 1 instead of 20+) - -Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); - } -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - waterAmbientSpawn = configuration.getInt("spawn-limits.water-ambient"); - ambientSpawn = configuration.getInt("spawn-limits.ambient"); - warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); -- TicketType.PLUGIN.loadPeriod = configuration.getInt("chunk-gc.period-in-ticks"); -+ TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - printSaveWarning = false; - console.autosavePeriod = configuration.getInt("ticks-per.autosave"); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutCustomSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutUpdateTime; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.ChunkMapDistance; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.PlayerChunkMap; -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public Chunk getChunkAt(int x, int z) { -- return this.world.getChunkProvider().getChunkAt(x, z, true).bukkitChunk; -+ // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it -+ net.minecraft.world.level.chunk.Chunk chunk = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ if (chunk == null) { -+ addTicket(x, z); -+ chunk = this.world.getChunkProvider().getChunkAt(x, z, true); -+ } -+ return chunk.bukkitChunk; -+ // Paper end -+ } -+ -+ // Paper start -+ private void addTicket(int x, int z) { -+ MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE)); // Paper - } -+ // Paper end - - @Override - public Chunk getChunkAt(Block block) { -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - public boolean unloadChunkRequest(int x, int z) { - org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot - if (isChunkLoaded(x, z)) { -- world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); -+ world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 0, Unit.INSTANCE); // Paper - } - - return true; -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot - // Paper start - Optimize this method - ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ IChunkAccess immediate = world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); // Paper -+ if (immediate != null) return true; // Paper - - if (!generate) { -- IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); -+ -+ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper - if (immediate == null) { - immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); - } -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { - return false; // not full status - } -- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower - return true; - } -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - // we do this so we do not re-read the chunk data on disk - } - -- world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper - world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); - return true; - // Paper end -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - } - return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); -+ if (chunk != null) addTicket(x, z); // Paper - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } diff --git a/Spigot-Server-Patches/Add-PrepareResultEvent.patch b/Spigot-Server-Patches/Add-PrepareResultEvent.patch deleted file mode 100644 index 209aa2e059..0000000000 --- a/Spigot-Server-Patches/Add-PrepareResultEvent.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 3 Jul 2020 11:58:56 -0500 -Subject: [PATCH] Add PrepareResultEvent - -Adds a new event for all crafting stations that generate a result slot item - -Anvil, Grindstone and Smithing now extend this event - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -0,0 +0,0 @@ public abstract class Container { - return nonnulllist; - } - -+ public final void notifyListeners() { this.c(); } // Paper - OBFHELPER - public void c() { - int i; - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -@@ -0,0 +0,0 @@ public class ContainerAnvil extends ContainerAnvilAbstract { - } - - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvilAbstract.java -@@ -0,0 +0,0 @@ public abstract class ContainerAnvilAbstract extends Container { - super.a(iinventory); - if (iinventory == this.repairInventory) { - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerCartography.java -@@ -0,0 +0,0 @@ public class ContainerCartography extends Container { - this.a(itemstack, itemstack1, itemstack2); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - private void a(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2) { -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -0,0 +0,0 @@ public class ContainerGrindstone extends Container { - super.a(iinventory); - if (iinventory == this.craftInventory) { - this.e(); -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -@@ -0,0 +0,0 @@ public class ContainerLoom extends Container { - } - - this.j(); -- this.c(); -+ //this.c(); // Paper - done below -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 3); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerSmithing.java -@@ -0,0 +0,0 @@ public class ContainerSmithing extends ContainerAnvilAbstract { - // CraftBukkit end - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -@@ -0,0 +0,0 @@ public class ContainerStonecutter extends Container { - this.a(iinventory, itemstack); - } - -+ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper - } - - private void a(IInventory iinventory, ItemStack itemstack) { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return event; - } - -- public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { -- PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled below -+ public static void callPrepareAnvilEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end - -- public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { -- PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item).clone()); -- event.getView().getPlayer().getServer().getPluginManager().callEvent(event); -+ // Paper start - disable this method, handled in callPrepareResultEvent -+ public static void callPrepareSmithingEvent(InventoryView view, ItemStack item) { // Paper - verify nothing uses return - handled below in PrepareResult -+ PrepareSmithingEvent event = new PrepareSmithingEvent(view, CraftItemStack.asCraftMirror(item)); // Paper - remove clone -+ //event.getView().getPlayer().getServer().getPluginManager().callEvent(event); // Paper - disable event - event.getInventory().setItem(2, event.getResult()); -- return event; -+ //return event; // Paper - } -+ // Paper end -+ -+ // Paper start - support specific overrides for prepare result -+ public static void callPrepareResultEvent(Container container, int resultSlot) { -+ com.destroystokyo.paper.event.inventory.PrepareResultEvent event; -+ InventoryView view = container.getBukkitView(); -+ org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); -+ CraftItemStack result = origItem != null ? CraftItemStack.asCraftCopy(origItem) : null; -+ if (view.getTopInventory() instanceof org.bukkit.inventory.AnvilInventory) { -+ event = new PrepareAnvilEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.GrindstoneInventory) { -+ event = new com.destroystokyo.paper.event.inventory.PrepareGrindstoneEvent(view, result); -+ } else if (view.getTopInventory() instanceof org.bukkit.inventory.SmithingInventory) { -+ event = new PrepareSmithingEvent(view, result); -+ } else { -+ event = new com.destroystokyo.paper.event.inventory.PrepareResultEvent(view, result); -+ } -+ event.callEvent(); -+ event.getInventory().setItem(resultSlot, event.getResult()); -+ container.notifyListeners(); -+ } -+ // Paper end - - /** - * Mob spawner event. diff --git a/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch b/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch deleted file mode 100644 index 246f6579d4..0000000000 --- a/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Fri, 16 Dec 2016 21:25:39 -0600 -Subject: [PATCH] Add ProjectileCollideEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile { - } - } - -+ // Paper start - Call ProjectileCollideEvent -+ // TODO: flag - noclip - call cancelled? -+ if (object instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)object); -+ if (event.isCancelled()) { -+ object = null; -+ movingobjectpositionentity = null; -+ } -+ } -+ // Paper end -+ - if (object != null && !flag) { - this.preOnHit((MovingObjectPosition) object); // CraftBukkit - projectile hit event - this.impulse = true; -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.World; - import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit -@@ -0,0 +0,0 @@ public abstract class EntityFireball extends IProjectile { - - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); - -- if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ // Paper end -+ -+ if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event - - // CraftBukkit start - Fire ProjectileHitEvent -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityProjectile.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.entity.TileEntityEndGateway; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; - - public abstract class EntityProjectile extends IProjectile { -@@ -0,0 +0,0 @@ public abstract class EntityProjectile extends IProjectile { - } - - if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && !flag) { -+ // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); -+ if (event.isCancelled()) { -+ movingobjectposition = null; -+ } -+ } -+ if (movingobjectposition != null) { -+ // Paper end - this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event -+ } // Paper - } - - this.checkBlockCollisions(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return CraftItemStack.asNMSCopy(bitem); - } - -+ // Paper start -+ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, MovingObjectPositionEntity position) { -+ Projectile projectile = (Projectile) entity.getBukkitEntity(); -+ org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity(); -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { - Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); - ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); diff --git a/Spigot-Server-Patches/Add-PufferFishStateChangeEvent.patch b/Spigot-Server-Patches/Add-PufferFishStateChangeEvent.patch deleted file mode 100644 index 069c82b962..0000000000 --- a/Spigot-Server-Patches/Add-PufferFishStateChangeEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Mon, 10 May 2021 16:59:05 +0100 -Subject: [PATCH] Add PufferFishStateChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPufferFish.java -@@ -0,0 +0,0 @@ public class EntityPufferFish extends EntityFish { - public void tick() { - if (!this.world.isClientSide && this.isAlive() && this.doAITick()) { - if (this.c > 0) { -+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent - if (this.getPuffState() == 0) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.dH()); - this.setPuffState(1); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.c > 40 && this.getPuffState() == 1) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 2).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.dH()); - this.setPuffState(2); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } - -+ if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.c; -+ } // Paper - Add PufferFishStateChangeEvent - } else if (this.getPuffState() != 0) { -+ boolean increase = true; // Paper - Add PufferFishStateChangeEvent - if (this.d > 60 && this.getPuffState() == 2) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 1).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.dH()); - this.setPuffState(1); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.d > 100 && this.getPuffState() == 1) { -+ if (new io.papermc.paper.event.entity.PufferFishStateChangeEvent((org.bukkit.entity.PufferFish) getBukkitEntity(), 0).callEvent()) { // Paper - Add PufferFishStateChangeEvent - this.playSound(SoundEffects.ENTITY_PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.dH()); - this.setPuffState(0); -+ } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } - -+ if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.d; -+ } // Paper - Add PufferFishStateChangeEvent - } - } - diff --git a/Spigot-Server-Patches/Add-Raw-Byte-ItemStack-Serialization.patch b/Spigot-Server-Patches/Add-Raw-Byte-ItemStack-Serialization.patch deleted file mode 100644 index e5a5980cee..0000000000 --- a/Spigot-Server-Patches/Add-Raw-Byte-ItemStack-Serialization.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Thu, 30 Apr 2020 16:56:54 +0200 -Subject: [PATCH] Add Raw Byte ItemStack Serialization - -Serializes using NBT which is safer for server data migrations than bukkits format. - -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -0,0 +0,0 @@ public class NBTCompressedStreamTools { - return nbttagcompound; - } - -+ public static NBTTagCompound readNBT(InputStream inputstream) throws IOException { return a(inputstream); } // Paper - OBFHELPER - public static NBTTagCompound a(InputStream inputstream) throws IOException { - DataInputStream datainputstream = new DataInputStream(new BufferedInputStream(new GZIPInputStream(inputstream))); - Throwable throwable = null; -@@ -0,0 +0,0 @@ public class NBTCompressedStreamTools { - - } - -+ public static void writeNBT(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { a(nbttagcompound, outputstream); } // Paper - OBFHELPER - public static void a(NBTTagCompound nbttagcompound, OutputStream outputstream) throws IOException { - DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(outputstream))); - Throwable throwable = null; -diff --git a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -+++ b/src/main/java/net/minecraft/util/datafix/DataConverterRegistry.java -@@ -0,0 +0,0 @@ public class DataConverterRegistry { - return datafixerbuilder.build(SystemUtils.e()); - } - -+ public static DataFixer getDataFixer() { return a(); } // Paper - OBFHELPER - public static DataFixer a() { - return DataConverterRegistry.c; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - this.checkEmpty(); - } - -+ public static ItemStack fromCompound(NBTTagCompound nbttagcompound) { return a(nbttagcompound); } // Paper - OBFHELPER - public static ItemStack a(NBTTagCompound nbttagcompound) { - try { - return new ItemStack(nbttagcompound); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public boolean isSupportedApiVersion(String apiVersion) { - return apiVersion != null && SUPPORTED_API.contains(apiVersion); - } -+ -+ @Override -+ public byte[] serializeItem(ItemStack item) { -+ Preconditions.checkNotNull(item, "null cannot be serialized"); -+ Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized"); -+ -+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); -+ NBTTagCompound compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new NBTTagCompound()); -+ compound.setInt("DataVersion", getDataVersion()); -+ try { -+ net.minecraft.nbt.NBTCompressedStreamTools.writeNBT( -+ compound, -+ outputStream -+ ); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return outputStream.toByteArray(); -+ } -+ -+ @Override -+ public ItemStack deserializeItem(byte[] data) { -+ Preconditions.checkNotNull(data, "null cannot be deserialized"); -+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing"); -+ -+ try { -+ NBTTagCompound compound = net.minecraft.nbt.NBTCompressedStreamTools.readNBT( -+ new java.io.ByteArrayInputStream(data) -+ ); -+ int dataVersion = compound.getInt("DataVersion"); -+ -+ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); -+ Dynamic converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic(DynamicOpsNBT.a, compound), dataVersion, getDataVersion()); -+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.fromCompound((NBTTagCompound) converted.getValue())); -+ } catch (IOException ex) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ex); -+ throw new RuntimeException(); -+ } -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/Add-StructureLocateEvent.patch b/Spigot-Server-Patches/Add-StructureLocateEvent.patch deleted file mode 100644 index afe6b4dc70..0000000000 --- a/Spigot-Server-Patches/Add-StructureLocateEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: dfsek -Date: Wed, 16 Sep 2020 01:12:29 -0700 -Subject: [PATCH] Add StructureLocateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.chunk; - - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; -+import io.papermc.paper.event.world.StructureLocateEvent; // Paper - Add import due to naming conflict. - import java.util.BitSet; - import java.util.Iterator; - import java.util.List; -@@ -0,0 +0,0 @@ public abstract class ChunkGenerator { - - @Nullable - public BlockPosition findNearestMapFeature(WorldServer worldserver, StructureGenerator structuregenerator, BlockPosition blockposition, int i, boolean flag) { -+ // Paper start -+ org.bukkit.World world = worldserver.getWorld(); -+ org.bukkit.Location originLocation = new org.bukkit.Location(world, blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ StructureLocateEvent event = new StructureLocateEvent(world, originLocation, org.bukkit.StructureType.getStructureTypes().get(structuregenerator.i()), i, flag); -+ if(!event.callEvent()) return null; -+ // If event call set a final location, skip structure finding and just return set result. -+ if(event.getResult() != null) return new BlockPosition(event.getResult().getBlockX(), event.getResult().getBlockY(), event.getResult().getBlockZ()); -+ // Get origin location (re)defined by event call. -+ blockposition = new BlockPosition(event.getOrigin().getBlockX(), event.getOrigin().getBlockY(), event.getOrigin().getBlockZ()); -+ // Get world (re)defined by event call. -+ worldserver = ((org.bukkit.craftbukkit.CraftWorld) event.getOrigin().getWorld()).getHandle(); -+ // Get radius and whether to find unexplored structures (re)defined by event call. -+ i = event.getRadius(); -+ flag = event.shouldFindUnexplored(); -+ structuregenerator = StructureGenerator.a.get(event.getType().getName()); -+ // Paper end - if (!this.b.a(structuregenerator)) { - return null; - } else if (structuregenerator == StructureGenerator.STRONGHOLD) { diff --git a/Spigot-Server-Patches/Add-TNTPrimeEvent.patch b/Spigot-Server-Patches/Add-TNTPrimeEvent.patch deleted file mode 100644 index e3519a82b6..0000000000 --- a/Spigot-Server-Patches/Add-TNTPrimeEvent.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 16 Jul 2018 00:05:05 +0300 -Subject: [PATCH] Add TNTPrimeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.event.entity.EntityExplodeEvent; - import org.bukkit.event.entity.EntityRegainHealthEvent; - // CraftBukkit end -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class EntityEnderDragon extends EntityInsentient implements IMonster { - -@@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - }); - craftBlock.getNMS().dropNaturally((WorldServer) world, blockposition, ItemStack.b); - } -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSource().getBukkitEntity()).callEvent()) -+ continue; -+ // Paper end - nmsBlock.wasExploded(world, blockposition, explosionSource); - - this.world.a(blockposition, false); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.block; - import com.google.common.collect.ImmutableMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - import java.util.Map; - import java.util.Random; - import java.util.function.Function; -@@ -0,0 +0,0 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.item.context.BlockActionContext; - import net.minecraft.world.level.GameRules; -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - - world.setTypeAndData(blockposition, this.a(world, blockposition, l), 3); - } else { -- world.a(blockposition, false); -+ if(iblockdata.getBlock() != Blocks.TNT) world.a(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down - } - - Block block = iblockdata.getBlock(); -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - if (block instanceof BlockTNT) { - BlockTNT blocktnt = (BlockTNT) block; - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { -+ return; -+ } -+ world.setAir(blockposition, false); -+ // Paper end - BlockTNT.a(world, blockposition); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTNT.java b/src/main/java/net/minecraft/world/level/block/BlockTNT.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTNT.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTNT.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.block.state.properties.BlockProperties; - import net.minecraft.world.level.block.state.properties.BlockStateBoolean; - import net.minecraft.world.phys.MovingObjectPositionBlock; -+import com.destroystokyo.paper.event.block.TNTPrimeEvent; // Paper - TNTPrimeEvent - - public class BlockTNT extends Block { - -@@ -0,0 +0,0 @@ public class BlockTNT extends Block { - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata1.a(iblockdata.getBlock())) { - if (world.isBlockIndirectlyPowered(blockposition)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - a(world, blockposition); - world.a(blockposition, false); - } -@@ -0,0 +0,0 @@ public class BlockTNT extends Block { - @Override - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (world.isBlockIndirectlyPowered(blockposition)) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition);; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) -+ return; -+ // Paper end - a(world, blockposition); - world.a(blockposition, false); - } -@@ -0,0 +0,0 @@ public class BlockTNT extends Block { - @Override - public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) { - if (!world.isClientSide) { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) -+ return; -+ // Paper end - EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, explosion.getSource()); - - entitytntprimed.setFuseTicks((short) (world.random.nextInt(entitytntprimed.getFuseTicks() / 4) + entitytntprimed.getFuseTicks() / 8)); -@@ -0,0 +0,0 @@ public class BlockTNT extends Block { - if (item != Items.FLINT_AND_STEEL && item != Items.FIRE_CHARGE) { - return super.interact(iblockdata, world, blockposition, entityhuman, enumhand, movingobjectpositionblock); - } else { -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if(!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.ITEM, entityhuman.getBukkitEntity()).callEvent()) -+ return EnumInteractionResult.FAIL; -+ // Paper end - a(world, blockposition, (EntityLiving) entityhuman); - world.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 11); - if (!entityhuman.isCreative()) { -@@ -0,0 +0,0 @@ public class BlockTNT extends Block { - } - // CraftBukkit end - -+ // Paper start - TNTPrimeEvent -+ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); -+ if (!new TNTPrimeEvent(tntBlock, TNTPrimeEvent.PrimeReason.PROJECTILE, iprojectile.getBukkitEntity()).callEvent()) { -+ return; -+ } -+ // Paper end -+ - a(world, blockposition, entity instanceof EntityLiving ? (EntityLiving) entity : null); - world.a(blockposition, false); - } diff --git a/Spigot-Server-Patches/Add-ThrownEggHatchEvent.patch b/Spigot-Server-Patches/Add-ThrownEggHatchEvent.patch deleted file mode 100644 index 183e2ac240..0000000000 --- a/Spigot-Server-Patches/Add-ThrownEggHatchEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 9 Feb 2020 00:19:05 -0600 -Subject: [PATCH] Add ThrownEggHatchEvent - -Adds a new event similar to PlayerEggThrowEvent, but without the Player requirement -(dispensers can throw eggs to hatch them, too). - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityEgg.java -@@ -0,0 +0,0 @@ public class EntityEgg extends EntityProjectileThrowable { - hatchingType = event.getHatchingType(); - } - -+ // Paper start -+ com.destroystokyo.paper.event.entity.ThrownEggHatchEvent event = new com.destroystokyo.paper.event.entity.ThrownEggHatchEvent((org.bukkit.entity.Egg) getBukkitEntity(), hatching, b0, hatchingType); -+ event.callEvent(); -+ -+ b0 = event.getNumHatches(); -+ hatching = event.isHatching(); -+ hatchingType = event.getHatchingType(); -+ // Paper end -+ -+ - if (hatching) { - for (int i = 0; i < b0; ++i) { - Entity entity = world.getWorld().createEntity(new org.bukkit.Location(world.getWorld(), this.locX(), this.locY(), this.locZ(), this.yaw, 0.0F), hatchingType.getEntityClass()); diff --git a/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch b/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch deleted file mode 100644 index 1a2c0f6c96..0000000000 --- a/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Tue, 11 May 2021 17:39:22 -0400 -Subject: [PATCH] Add Unix domain socket support - -For Windows and ARM support, JEP-380 is required: -https://inside.java/2021/02/03/jep380-unix-domain-sockets-channels/ -This will be possible as of the Minecraft 1.17 Java version bump. - -Tested-by: Mariell Hoversholm -Reviewed-by: Mariell Hoversholm - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - // Spigot Start - public SocketAddress getRawAddress() - { -+ // Paper start - this can be nullable in the case of a Unix domain socket, so if it is, fake something -+ if (this.channel.remoteAddress() == null) { -+ return new java.net.InetSocketAddress(java.net.InetAddress.getLoopbackAddress(), 0); -+ } -+ // Paper end - return this.channel.remoteAddress(); - } - // Spigot End -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 IMinecraftServer - this.i(dedicatedserverproperties.enforceWhitelist); - // this.saveData.setGameType(dedicatedserverproperties.gamemode); // CraftBukkit - moved to world loading - DedicatedServer.LOGGER.info("Default game type: {}", dedicatedserverproperties.gamemode); -+ // Paper start - Unix domain socket support -+ java.net.SocketAddress bindAddress; -+ if (this.getServerIp().startsWith("unix:")) { -+ if (!io.netty.channel.epoll.Epoll.isAvailable()) { -+ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); -+ DedicatedServer.LOGGER.fatal("You are trying to use a Unix domain socket but you're not on a supported OS."); -+ return false; -+ } else if (!com.destroystokyo.paper.PaperConfig.velocitySupport && !org.spigotmc.SpigotConfig.bungee) { -+ DedicatedServer.LOGGER.fatal("**** INVALID CONFIGURATION!"); -+ DedicatedServer.LOGGER.fatal("Unix domain sockets require IPs to be forwarded from a proxy."); -+ return false; -+ } -+ bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getServerIp().substring("unix:".length())); -+ } else { - InetAddress inetaddress = null; - - if (!this.getServerIp().isEmpty()) { -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - if (this.getPort() < 0) { - this.setPort(dedicatedserverproperties.serverPort); - } -+ bindAddress = new java.net.InetSocketAddress(inetaddress, this.getPort()); -+ } -+ // Paper end - - this.P(); - DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getServerIp().isEmpty() ? "*" : this.getServerIp(), this.getPort()); - - try { -- this.getServerConnection().a(inetaddress, this.getPort()); -+ this.getServerConnection().bind(bindAddress); // Paper - Unix domain socket support - } catch (IOException ioexception) { - DedicatedServer.LOGGER.warn("**** FAILED TO BIND TO PORT!"); - DedicatedServer.LOGGER.warn("The exception was: {}", ioexception.toString()); -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - this.c.setProtocol(EnumProtocol.LOGIN); - // CraftBukkit start - Connection throttle - try { -+ if (!(this.c.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - the connection throttle is useless when you have a Unix domain socket - long currentTime = System.currentTimeMillis(); - long connectionThrottle = this.b.server.getConnectionThrottle(); - InetAddress address = ((java.net.InetSocketAddress) this.c.getSocketAddress()).getAddress(); -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - } - } - } -+ } // Paper - add closing bracket for if check above - } catch (Throwable t) { - org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); - } -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper -+ // Paper start - Unix domain socket support -+ java.net.SocketAddress socketAddress = c.getSocketAddress(); - packethandshakinginsetprotocol.hostname = split[0]; -- c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort()); -+ c.socketAddress = new java.net.InetSocketAddress(split[1], socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); -+ // Paper end - c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); - } else - { -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -0,0 +0,0 @@ public class ServerConnection { - this.c = true; - } - -+ // Paper start - public void a(@Nullable InetAddress inetaddress, int i) throws IOException { -+ bind(new java.net.InetSocketAddress(inetaddress, i)); -+ } -+ public void bind(java.net.SocketAddress address) throws IOException { -+ // Paper end - List list = this.listeningChannels; - - synchronized (this.listeningChannels) { -@@ -0,0 +0,0 @@ public class ServerConnection { - LazyInitVar lazyinitvar; - - if (Epoll.isAvailable() && this.e.l()) { -+ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { -+ oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; -+ } else { - oclass = EpollServerSocketChannel.class; -+ } - lazyinitvar = ServerConnection.b; - ServerConnection.LOGGER.info("Using epoll channel type"); - } else { -@@ -0,0 +0,0 @@ public class ServerConnection { - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); - io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper - } -- }).group((EventLoopGroup) lazyinitvar.a()).localAddress(inetaddress, i)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit -+ }).group((EventLoopGroup) lazyinitvar.a()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper - } - } - diff --git a/Spigot-Server-Patches/Add-UnknownCommandEvent.patch b/Spigot-Server-Patches/Add-UnknownCommandEvent.patch deleted file mode 100644 index c9f550790a..0000000000 --- a/Spigot-Server-Patches/Add-UnknownCommandEvent.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sweepyoface -Date: Sat, 17 Jun 2017 18:48:21 -0400 -Subject: [PATCH] Add UnknownCommandEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - - // Spigot start - if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { -- sender.sendMessage(org.spigotmc.SpigotConfig.unknownCommandMessage); -+ // Paper start -+ org.bukkit.event.command.UnknownCommandEvent event = new org.bukkit.event.command.UnknownCommandEvent(sender, commandLine, org.spigotmc.SpigotConfig.unknownCommandMessage); -+ Bukkit.getServer().getPluginManager().callEvent(event); -+ if (event.message() != null) { -+ sender.sendMessage(event.message()); -+ } -+ // Paper end - } - // Spigot end - diff --git a/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch b/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch deleted file mode 100644 index d75f2ceb46..0000000000 --- a/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 8 Oct 2018 14:36:14 -0400 -Subject: [PATCH] Add Velocity IP Forwarding Support - -While Velocity supports BungeeCord-style IP forwarding, it is not secure. Users -have a lot of problems setting up firewalls or setting up plugins like IPWhitelist. -Further, the BungeeCord IP forwarding protocol still retains essentially its original -form, when there is brand new support for custom login plugin messages in 1.13. - -Velocity's modern IP forwarding uses an HMAC-SHA256 code to ensure authenticity -of messages, is packed into a binary format that is smaller than BungeeCord's -forwarding, and is integrated into the Minecraft login process by using the 1.13 -login plugin message packet. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ import java.io.IOException; - import java.lang.reflect.InvocationTargetException; - import java.lang.reflect.Method; - import java.lang.reflect.Modifier; -+import java.nio.charset.StandardCharsets; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -@@ -0,0 +0,0 @@ public class PaperConfig { - } - - public static boolean isProxyOnlineMode() { -- return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode) || (velocitySupport && velocityOnlineMode); - } - - public static int packetInSpamThreshold = 300; -@@ -0,0 +0,0 @@ public class PaperConfig { - } - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } -+ -+ public static boolean velocitySupport; -+ public static boolean velocityOnlineMode; -+ public static byte[] velocitySecretKey; -+ private static void velocitySupport() { -+ velocitySupport = getBoolean("settings.velocity-support.enabled", false); -+ velocityOnlineMode = getBoolean("settings.velocity-support.online-mode", false); -+ String secret = getString("settings.velocity-support.secret", ""); -+ if (velocitySupport && secret.isEmpty()) { -+ fatal("Velocity support is enabled, but no secret key was specified. A secret key is required!"); -+ } else { -+ velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/proxy/VelocityProxy.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.proxy; -+ -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.net.InetAddresses; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import net.minecraft.network.PacketDataSerializer; -+import net.minecraft.resources.MinecraftKey; -+ -+import java.net.InetAddress; -+import java.security.InvalidKeyException; -+import java.security.MessageDigest; -+import java.security.NoSuchAlgorithmException; -+ -+import javax.crypto.Mac; -+import javax.crypto.spec.SecretKeySpec; -+ -+public class VelocityProxy { -+ private static final int SUPPORTED_FORWARDING_VERSION = 1; -+ public static final MinecraftKey PLAYER_INFO_CHANNEL = new MinecraftKey("velocity", "player_info"); -+ -+ public static boolean checkIntegrity(final PacketDataSerializer buf) { -+ final byte[] signature = new byte[32]; -+ buf.readBytes(signature); -+ -+ final byte[] data = new byte[buf.readableBytes()]; -+ buf.getBytes(buf.readerIndex(), data); -+ -+ try { -+ final Mac mac = Mac.getInstance("HmacSHA256"); -+ mac.init(new SecretKeySpec(PaperConfig.velocitySecretKey, "HmacSHA256")); -+ final byte[] mySignature = mac.doFinal(data); -+ if (!MessageDigest.isEqual(signature, mySignature)) { -+ return false; -+ } -+ } catch (final InvalidKeyException | NoSuchAlgorithmException e) { -+ throw new AssertionError(e); -+ } -+ -+ int version = buf.readVarInt(); -+ if (version != SUPPORTED_FORWARDING_VERSION) { -+ throw new IllegalStateException("Unsupported forwarding version " + version + ", wanted " + SUPPORTED_FORWARDING_VERSION); -+ } -+ -+ return true; -+ } -+ -+ public static InetAddress readAddress(final PacketDataSerializer buf) { -+ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); -+ } -+ -+ public static GameProfile createProfile(final PacketDataSerializer buf) { -+ final GameProfile profile = new GameProfile(buf.readUUID(), buf.readUTF(16)); -+ readProperties(buf, profile); -+ return profile; -+ } -+ -+ private static void readProperties(final PacketDataSerializer buf, final GameProfile profile) { -+ final int properties = buf.readVarInt(); -+ for (int i1 = 0; i1 < properties; i1++) { -+ final String name = buf.readUTF(Short.MAX_VALUE); -+ final String value = buf.readUTF(Short.MAX_VALUE); -+ final String signature = buf.readBoolean() ? buf.readUTF(Short.MAX_VALUE) : null; -+ profile.getProperties().put(name, new Property(name, value, signature)); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - return this.d(oenum.ordinal()); - } - -+ public int readVarInt() { return i(); } // Paper - OBFHELPER - public int i() { - int i = 0; - int j = 0; -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - return this; - } - -+ public UUID readUUID() { return k(); } // Paper - OBFHELPER - public UUID k() { - return new UUID(this.readLong(), this.readLong()); - } -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - } - } - -+ public String readUTF(int maxLength) { return this.e(maxLength); } // Paper - OBFHELPER - public String e(int i) { - int j = this.i(); - -diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -+++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginInCustomPayload.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet; - - public class PacketLoginInCustomPayload implements Packet { - -- private int a; -- private PacketDataSerializer b; -+ private int a; public int getId() { return a; } // Paper - OBFHELPER -+ private PacketDataSerializer b; public PacketDataSerializer getBuf() { return b; } // Paper - OBFHELPER - - public PacketLoginInCustomPayload() {} - -diff --git a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -+++ b/src/main/java/net/minecraft/network/protocol/login/PacketLoginOutCustomPayload.java -@@ -0,0 +0,0 @@ public class PacketLoginOutCustomPayload implements Packet { -+ try { -+ new LoginHandler().fireEvents(); -+ } catch (Exception ex) { -+ disconnect("Failed to verify username!"); -+ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); -+ } -+ }); -+ return; -+ } -+ // Paper end - this.disconnect(new ChatMessage("multiplayer.disconnect.unexpected_query_response")); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - @Override - public long getConnectionThrottle() { - // Spigot Start - Automatically set connection throttle for bungee configurations -- if (org.spigotmc.SpigotConfig.bungee) { -+ if (org.spigotmc.SpigotConfig.bungee || com.destroystokyo.paper.PaperConfig.velocitySupport) { // Paper - Velocity support - return -1; - } else { - return this.configuration.getInt("settings.connection-throttle"); diff --git a/Spigot-Server-Patches/Add-Wandering-Trader-spawn-rate-config-options.patch b/Spigot-Server-Patches/Add-Wandering-Trader-spawn-rate-config-options.patch deleted file mode 100644 index 6b3e3b3a18..0000000000 --- a/Spigot-Server-Patches/Add-Wandering-Trader-spawn-rate-config-options.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Thu, 20 Aug 2020 11:20:12 -0700 -Subject: [PATCH] Add Wandering Trader spawn rate config options - -Adds config options for modifying the spawn rates of Wandering Traders. -These values are all easy to understand and configure after a quick read of this -page on the Minecraft wiki: https://minecraft.gamepedia.com/Wandering_Trader#Spawning -Usages of the vanilla WanderingTraderSpawnDelay and WanderingTraderSpawnChance values -in IWorldServerData are removed as they were only used in certain places, with hardcoded -values used in other places. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - log("The Ender Dragon will be removed if she already exists without a portal."); - } - } -+ -+ public int wanderingTraderSpawnMinuteTicks = 1200; -+ public int wanderingTraderSpawnDayTicks = 24000; -+ public int wanderingTraderSpawnChanceFailureIncrement = 25; -+ public int wanderingTraderSpawnChanceMin = 25; -+ public int wanderingTraderSpawnChanceMax = 75; -+ private void wanderingTraderSettings() { -+ wanderingTraderSpawnMinuteTicks = getInt("wandering-trader.spawn-minute-length", wanderingTraderSpawnMinuteTicks); -+ wanderingTraderSpawnDayTicks = getInt("wandering-trader.spawn-day-length", wanderingTraderSpawnDayTicks); -+ wanderingTraderSpawnChanceFailureIncrement = getInt("wandering-trader.spawn-chance-failure-increment", wanderingTraderSpawnChanceFailureIncrement); -+ wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); -+ wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -@@ -0,0 +0,0 @@ public class MobSpawnerTrader implements MobSpawner { - - private final Random a = new Random(); - private final IWorldDataServer b; -- private int c; -- private int d; -- private int e; -+ private int c; public final int getMinuteTimer() { return this.c; } public final void setMinuteTimer(int x) { this.c = x; } // Paper - OBFHELPER -+ private int d; public final int getDayTimer() { return this.d; } public final void setDayTimer(int x) { this.d = x; } // Paper - OBFHELPER -+ private int e; public final int getSpawnChance() { return this.e; } public final void setSpawnChance(int x) { this.e = x; } // Paper - OBFHELPER - - public MobSpawnerTrader(IWorldDataServer iworlddataserver) { - this.b = iworlddataserver; -- this.c = 1200; -- this.d = iworlddataserver.v(); -- this.e = iworlddataserver.w(); -- if (this.d == 0 && this.e == 0) { -- this.d = 24000; -- iworlddataserver.g(this.d); -- this.e = 25; -- iworlddataserver.h(this.e); -- } -+ // Paper start -+ this.setMinuteTimer(Integer.MIN_VALUE); -+ //this.d = iworlddataserver.v(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //this.e = iworlddataserver.w(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value -+ //if (this.d == 0 && this.e == 0) { -+ // this.d = 24000; -+ // iworlddataserver.g(this.d); -+ // this.e = 25; -+ // iworlddataserver.h(this.e); -+ //} -+ // Paper end - - } - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -+ // Paper start -+ if (this.getMinuteTimer() == Integer.MIN_VALUE) { -+ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); -+ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); -+ } - if (!worldserver.getGameRules().getBoolean(GameRules.DO_TRADER_SPAWNING)) { - return 0; -- } else if (--this.c > 0) { -+ } else if (this.getMinuteTimer() - 1 > 0) { -+ this.setMinuteTimer(this.getMinuteTimer() - 1); - return 0; - } else { -- this.c = 1200; -- this.d -= 1200; -- this.b.g(this.d); -- if (this.d > 0) { -+ this.setMinuteTimer(worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ this.setDayTimer(getDayTimer() - worldserver.paperConfig.wanderingTraderSpawnMinuteTicks); -+ //this.b.g(this.d); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways -+ if (this.getDayTimer() > 0) { - return 0; - } else { -- this.d = 24000; -+ this.setDayTimer(worldserver.paperConfig.wanderingTraderSpawnDayTicks); - if (!worldserver.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING)) { - return 0; - } else { -- int i = this.e; -+ int i = this.getSpawnChance(); - -- this.e = MathHelper.clamp(this.e + 25, 25, 75); -- this.b.h(this.e); -+ this.setSpawnChance(MathHelper.clamp(i + worldserver.paperConfig.wanderingTraderSpawnChanceFailureIncrement, worldserver.paperConfig.wanderingTraderSpawnChanceMin, worldserver.paperConfig.wanderingTraderSpawnChanceMax)); -+ //this.b.h(this.e); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways - if (this.a.nextInt(100) > i) { - return 0; - } else if (this.a(worldserver)) { -- this.e = 25; -+ this.setSpawnChance(worldserver.paperConfig.wanderingTraderSpawnChanceMin); -+ // Paper end - return 1; - } else { - return 0; diff --git a/Spigot-Server-Patches/Add-World-Util-Methods.patch b/Spigot-Server-Patches/Add-World-Util-Methods.patch deleted file mode 100644 index 3588eef5e8..0000000000 --- a/Spigot-Server-Patches/Add-World-Util-Methods.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 20:16:03 -0400 -Subject: [PATCH] Add World Util Methods - -Methods that can be used for other patches to help improve logic. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - -- public Chunk getChunkIfLoaded(int x, int z) { -+ @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); - } - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - @Override -- public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ public final Fluid getFluidIfLoaded(BlockPosition blockposition) { - IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); - - return chunk == null ? null : chunk.getFluid(blockposition); - } -+ -+ public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline -+ return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; -+ } -+ -+ public Chunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final -+ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ } -+ public final Chunk getChunkIfLoaded(BlockPosition blockposition) { -+ return ((WorldServer) this).getChunkProvider().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ } -+ -+ // reduces need to do isLoaded before getType -+ public final IBlockData getTypeIfLoadedAndInBounds(BlockPosition blockposition) { -+ return getWorldBorder().isInBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; -+ } - // Paper end - - @Override -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -0,0 +0,0 @@ public class WorldBorder { - - public WorldBorder() {} - -+ public final boolean isInBounds(BlockPosition blockposition) { return this.a(blockposition); } // Paper - OBFHELPER - public boolean a(BlockPosition blockposition) { - return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); - } diff --git a/Spigot-Server-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Spigot-Server-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch deleted file mode 100644 index 56e162de3b..0000000000 --- a/Spigot-Server-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 May 2021 00:48:33 +0200 -Subject: [PATCH] Add a "should burn in sunlight" API for Phantoms and - Skeletons - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - - @Override - public void movementTick() { -- if (this.isAlive() && this.eG()) { -+ if (this.isAlive() && shouldBurnInDay && this.eG()) { // Paper - Configurable Burning - this.setOnFire(8); - } - -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { - this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); - } -+ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); - // Paper end - } - -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - if (this.spawningEntity != null) { - nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); - } -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - // Paper end - } - -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - return spawningEntity; - } - public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } -+ -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } - // Paper end - - class b extends PathfinderGoal { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - return EnumMonsterType.UNDEAD; - } - -+ // Paper start -+ private boolean shouldBurnInDay = true; -+ public boolean shouldBurnInDay() { return shouldBurnInDay; } -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } -+ // Paper end -+ - @Override - public void movementTick() { -- boolean flag = this.eG(); -+ boolean flag = shouldBurnInDay && this.eG(); // Paper - Configurable Burning - - if (flag) { - ItemStack itemstack = this.getEquipment(EnumItemSlot.HEAD); -@@ -0,0 +0,0 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - public void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); - this.eL(); -+ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); // Paper -+ } -+ -+ // Paper start -+ @Override -+ public void saveData(NBTTagCompound nbttagcompound) { -+ super.saveData(nbttagcompound); -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); - } -+ // Paper end - - @Override - public void setSlot(EnumItemSlot enumitemslot, ItemStack itemstack) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -@@ -0,0 +0,0 @@ public class CraftPhantom extends CraftFlying implements Phantom { - public java.util.UUID getSpawningEntity() { - return getHandle().getSpawningEntity(); - } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -0,0 +0,0 @@ public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroy - public void setSkeletonType(SkeletonType type) { - throw new UnsupportedOperationException("Not supported."); - } -+ -+ // Paper start -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Spigot-Server-Patches/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch deleted file mode 100644 index b798100830..0000000000 --- a/Spigot-Server-Patches/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 11 Aug 2020 19:16:09 +0200 -Subject: [PATCH] Add a way to get translation keys for blocks, entities and - materials - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ public class EntityTypes { - return IRegistry.ENTITY_TYPE.getKey(entitytypes); - } - -+ public static Optional> getByName(String name) { return a(name); } // Paper - OBFHELPER - public static Optional> a(String s) { - return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); - } -@@ -0,0 +0,0 @@ public class EntityTypes { - return this.bg; - } - -+ public String getDescriptionId() { return f(); } // Paper - OBFHELPER - public String f() { - if (this.bo == null) { - this.bo = SystemUtils.a("entity", IRegistry.ENTITY_TYPE.getKey(this)); -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -0,0 +0,0 @@ public class Item implements IMaterial { - private final FoodInfo foodInfo; - - public static int getId(Item item) { -- return item == null ? 0 : IRegistry.ITEM.a((Object) item); -+ return item == null ? 0 : IRegistry.ITEM.a(item); // Paper - Fix Decompiler Issue - } - - public static Item getById(int i) { -@@ -0,0 +0,0 @@ public class Item implements IMaterial { - return IRegistry.ITEM.getKey(this).getKey(); - } - -+ public String getOrCreateDescriptionId() { return m(); } // Paper - OBFHELPER - protected String m() { - if (this.name == null) { - this.name = SystemUtils.a("item", IRegistry.ITEM.getKey(this)); -@@ -0,0 +0,0 @@ public class Item implements IMaterial { - return this.m(); - } - -+ public String getDescriptionId(ItemStack itemStack) { return f(itemStack); } // Paper - OBFHELPER - public String f(ItemStack itemstack) { - return this.getName(); - } -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -0,0 +0,0 @@ public class Block extends BlockBase implements IMaterial { - return !this.material.isBuildable() && !this.material.isLiquid(); - } - -+ public String getOrCreateDescriptionId() { return i(); } // Paper - OBFHELPER - public String i() { - if (this.name == null) { - this.name = SystemUtils.a("block", IRegistry.BLOCK.getKey(this)); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { - return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); - } -+ -+ @Override -+ public String getTranslationKey() { -+ return org.bukkit.Bukkit.getUnsafe().getTranslationKey(this); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ import org.bukkit.Registry; - import org.bukkit.UnsafeValues; - import org.bukkit.advancement.Advancement; - import org.bukkit.block.data.BlockData; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.craftbukkit.legacy.CraftLegacy; -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - throw new RuntimeException(); - } - } -+ -+ @Override -+ public String getTranslationKey(Material mat) { -+ if (mat.isBlock()) { -+ return getBlock(mat).getOrCreateDescriptionId(); -+ } -+ return getItem(mat).getName(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.block.Block block) { -+ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getOrCreateDescriptionId(); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.entity.EntityType type) { -+ return net.minecraft.world.entity.EntityTypes.getByName(type.getName()).map(net.minecraft.world.entity.EntityTypes::getDescriptionId).orElse(null); -+ } -+ -+ @Override -+ public String getTranslationKey(org.bukkit.inventory.ItemStack itemStack) { -+ net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); -+ return nmsItemStack.getItem().getDescriptionId(nmsItemStack); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/Add-ability-to-configure-frosted_ice-properties.patch b/Spigot-Server-Patches/Add-ability-to-configure-frosted_ice-properties.patch deleted file mode 100644 index 086598e7f4..0000000000 --- a/Spigot-Server-Patches/Add-ability-to-configure-frosted_ice-properties.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Thu, 21 Apr 2016 23:51:55 -0700 -Subject: [PATCH] Add ability to configure frosted_ice properties - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void useVanillaScoreboardColoring() { - useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); - } -+ -+ public boolean frostedIceEnabled = true; -+ public int frostedIceDelayMin = 20; -+ public int frostedIceDelayMax = 40; -+ private void frostedIce() { -+ this.frostedIceEnabled = this.getBoolean("frosted-ice.enabled", this.frostedIceEnabled); -+ this.frostedIceDelayMin = this.getInt("frosted-ice.delay.min", this.frostedIceDelayMin); -+ this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); -+ log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -@@ -0,0 +0,0 @@ public class BlockIceFrost extends BlockIce { - - @Override - public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (!worldserver.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice - if ((random.nextInt(3) == 0 || this.a(worldserver, blockposition, 4)) && worldserver.getLightLevel(blockposition) > 11 - (Integer) iblockdata.get(BlockIceFrost.a) - iblockdata.b((IBlockAccess) worldserver, blockposition) && this.e(iblockdata, (World) worldserver, blockposition)) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - EnumDirection[] aenumdirection = EnumDirection.values(); -@@ -0,0 +0,0 @@ public class BlockIceFrost extends BlockIce { - IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); - - if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { -- worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, 20, 40)); -+ worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - - } else { -- worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, 20, 40)); -+ worldserver.getBlockTickList().a(blockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay - } - } - diff --git a/Spigot-Server-Patches/Add-additional-open-container-api-to-HumanEntity.patch b/Spigot-Server-Patches/Add-additional-open-container-api-to-HumanEntity.patch deleted file mode 100644 index d9f286da23..0000000000 --- a/Spigot-Server-Patches/Add-additional-open-container-api-to-HumanEntity.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Wed, 26 Aug 2020 02:12:31 -0400 -Subject: [PATCH] Add additional open container api to HumanEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return this.getHandle().activeContainer.getBukkitView(); - } - -+ // Paper start - Add additional containers -+ @Override -+ public InventoryView openAnvil(Location location, boolean force) { -+ return openInventory(location, force, Material.ANVIL); -+ } -+ -+ @Override -+ public InventoryView openCartographyTable(Location location, boolean force) { -+ return openInventory(location, force, Material.CARTOGRAPHY_TABLE); -+ } -+ -+ @Override -+ public InventoryView openGrindstone(Location location, boolean force) { -+ return openInventory(location, force, Material.GRINDSTONE); -+ } -+ -+ @Override -+ public InventoryView openLoom(Location location, boolean force) { -+ return openInventory(location, force, Material.LOOM); -+ } -+ -+ @Override -+ public InventoryView openSmithingTable(Location location, boolean force) { -+ return openInventory(location, force, Material.SMITHING_TABLE); -+ } -+ -+ @Override -+ public InventoryView openStonecutter(Location location, boolean force) { -+ return openInventory(location, force, Material.STONECUTTER); -+ } -+ -+ private InventoryView openInventory(Location location, boolean force, Material material) { -+ org.spigotmc.AsyncCatcher.catchOp("open" + material); -+ if (location == null) { -+ location = getLocation(); -+ } -+ if (!force) { -+ Block block = location.getBlock(); -+ if (block.getType() != material) { -+ return null; -+ } -+ } -+ net.minecraft.world.level.block.Block block; -+ if (material == Material.ANVIL) { -+ block = Blocks.ANVIL; -+ } else if (material == Material.CARTOGRAPHY_TABLE) { -+ block = Blocks.CARTOGRAPHY_TABLE; -+ } else if (material == Material.GRINDSTONE) { -+ block = Blocks.GRINDSTONE; -+ } else if (material == Material.LOOM) { -+ block = Blocks.LOOM; -+ } else if (material == Material.SMITHING_TABLE) { -+ block = Blocks.SMITHING_TABLE; -+ } else if (material == Material.STONECUTTER) { -+ block = Blocks.STONECUTTER; -+ } else { -+ throw new IllegalArgumentException("Unsupported inventory type: " + material); -+ } -+ getHandle().openContainer(block.getInventory(null, getHandle().world, new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); -+ getHandle().activeContainer.checkReachable = !force; -+ return getHandle().activeContainer.getBukkitView(); -+ } -+ // Paper end -+ - @Override - public void closeInventory() { - // Paper start diff --git a/Spigot-Server-Patches/Add-and-implement-PlayerRecipeBookClickEvent.patch b/Spigot-Server-Patches/Add-and-implement-PlayerRecipeBookClickEvent.patch deleted file mode 100644 index cf0f23155a..0000000000 --- a/Spigot-Server-Patches/Add-and-implement-PlayerRecipeBookClickEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Fri, 5 Jun 2020 18:24:06 -0400 -Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); - this.player.resetIdleTimer(); - if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { -- this.minecraftServer.getCraftingManager().getRecipe(packetplayinautorecipe.c()).ifPresent((irecipe) -> { -- ((ContainerRecipeBook) this.player.activeContainer).a(packetplayinautorecipe.d(), irecipe, this.player); -- }); -+ // Paper start - fire event for clicking recipes in the recipe book -+ com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent event = new com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent( -+ player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(packetplayinautorecipe.c()), packetplayinautorecipe.d()); -+ if (event.callEvent()) { -+ this.minecraftServer.getCraftingManager().getRecipe(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { -+ ((ContainerRecipeBook) this.player.activeContainer).a(event.isMakeAll(), irecipe, this.player); -+ }); -+ } -+ // Paper end - } - } - diff --git a/Spigot-Server-Patches/Add-basic-Datapack-API.patch b/Spigot-Server-Patches/Add-basic-Datapack-API.patch deleted file mode 100644 index e691ee2cfb..0000000000 --- a/Spigot-Server-Patches/Add-basic-Datapack-API.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Sun, 16 May 2021 15:07:34 +0100 -Subject: [PATCH] Add basic Datapack API - - -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapack.java b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapack.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.datapack; -+ -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.packs.repository.ResourcePackLoader; -+ -+import java.util.List; -+import java.util.stream.Collectors; -+ -+public class PaperDatapack implements Datapack { -+ private final String name; -+ private final Compatibility compatibility; -+ private final boolean enabled; -+ -+ PaperDatapack(ResourcePackLoader loader, boolean enabled) { -+ this.name = loader.getName(); -+ this.compatibility = Compatibility.valueOf(loader.getVersion().name()); -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public String getName() { -+ return name; -+ } -+ -+ @Override -+ public Compatibility getCompatibility() { -+ return compatibility; -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void setEnabled(boolean enabled) { -+ if (enabled == this.enabled) { -+ return; -+ } -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ List enabledKeys = server.getResourcePackRepository().getEnabledPacks().stream().map(ResourcePackLoader::getName).collect(Collectors.toList()); -+ if (enabled) { -+ enabledKeys.add(this.name); -+ } else { -+ enabledKeys.remove(this.name); -+ } -+ server.reloadServerResources(enabledKeys, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/datapack/PaperDatapackManager.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.datapack; -+ -+import net.minecraft.server.packs.repository.ResourcePackLoader; -+import net.minecraft.server.packs.repository.ResourcePackRepository; -+ -+import java.util.Collection; -+import java.util.stream.Collectors; -+ -+public class PaperDatapackManager implements DatapackManager { -+ private final ResourcePackRepository repository; -+ -+ public PaperDatapackManager(ResourcePackRepository repository) { -+ this.repository = repository; -+ } -+ -+ @Override -+ public Collection getPacks() { -+ Collection enabledPacks = repository.getEnabledPacks(); -+ return repository.getPacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); -+ } -+ -+ @Override -+ public Collection getEnabledPacks() { -+ return repository.getEnabledPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -+++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackLoader.java -@@ -0,0 +0,0 @@ public class ResourcePackLoader implements AutoCloseable { - }); - } - -+ public final EnumResourcePackVersion getVersion() { return this.c(); } // Paper - OBFHELPER - public EnumResourcePackVersion c() { - return this.g; - } -@@ -0,0 +0,0 @@ public class ResourcePackLoader implements AutoCloseable { - return (IResourcePack) this.d.get(); - } - -+ public final String getName() { return this.e(); } // Paper - OBFHELPER - public String e() { - return this.c; - } -diff --git a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -+++ b/src/main/java/net/minecraft/server/packs/repository/ResourcePackRepository.java -@@ -0,0 +0,0 @@ public class ResourcePackRepository implements AutoCloseable { - return this.b.keySet(); - } - -+ public final Collection getPacks() { return this.c(); } // Paper - OBFHELPER - public Collection c() { - return this.b.values(); - } -@@ -0,0 +0,0 @@ public class ResourcePackRepository implements AutoCloseable { - return (Collection) this.c.stream().map(ResourcePackLoader::e).collect(ImmutableSet.toImmutableSet()); - } - -+ public final Collection getEnabledPacks() { return this.e(); } // Paper - OBFHELPER - public Collection e() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ import com.mojang.serialization.Lifecycle; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.datapack.PaperDatapackManager; // Paper - import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - import java.awt.image.BufferedImage; -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ private final PaperDatapackManager datapackManager; // Paper - public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - TicketType.PLUGIN.loadPeriod = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second - minimumAPI = configuration.getString("settings.minimum-api"); - loadIcon(); -+ datapackManager = new PaperDatapackManager(console.getResourcePackRepository()); // Paper - } - - public boolean getCommandBlockOverride(String command) { -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { - return mobGoals; - } -+ -+ @Override -+ public PaperDatapackManager getDatapackManager() { -+ return datapackManager; -+ } -+ - // Paper end - } diff --git a/Spigot-Server-Patches/Add-bypass-host-check.patch b/Spigot-Server-Patches/Add-bypass-host-check.patch deleted file mode 100644 index 0c1e46628b..0000000000 --- a/Spigot-Server-Patches/Add-bypass-host-check.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Apr 2021 21:27:01 +0100 -Subject: [PATCH] Add bypass host check - -Paper.bypassHostCheck - -Seriously, fix your firewalls. -.- - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); - private final MinecraftServer b; - private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER -+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper - - public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { - this.b = minecraftserver; -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - // Spigot Start - //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); -- if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { -+ if ( ( split.length == 3 || split.length == 4 ) && ( BYPASS_HOSTCHECK || HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper - packethandshakinginsetprotocol.hostname = split[0]; - c.socketAddress = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) c.getSocketAddress()).getPort()); - c.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/Spigot-Server-Patches/Add-cause-to-Weather-ThunderChangeEvents.patch b/Spigot-Server-Patches/Add-cause-to-Weather-ThunderChangeEvents.patch deleted file mode 100644 index 4c91dae9fd..0000000000 --- a/Spigot-Server-Patches/Add-cause-to-Weather-ThunderChangeEvents.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 18:23:26 -0800 -Subject: [PATCH] Add cause to Weather/ThunderChangeEvents - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.worldDataServer.setClearWeatherTime(i); - this.worldDataServer.setWeatherDuration(j); - this.worldDataServer.setThunderDuration(j); -- this.worldDataServer.setStorm(flag); -- this.worldDataServer.setThundering(flag1); -+ this.worldDataServer.setStorm(flag, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper -+ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper - } - - public BiomeBase getBiomeBySeed(int i, int j, int k) { return a(i, j, k); } // Paper - OBFHELPER -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.worldDataServer.setThunderDuration(j); - this.worldDataServer.setWeatherDuration(k); - this.worldDataServer.setClearWeatherTime(i); -- this.worldDataServer.setThundering(flag1); -- this.worldDataServer.setStorm(flag2); -+ this.worldDataServer.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper -+ this.worldDataServer.setStorm(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper - } - - this.lastThunderLevel = this.thunderLevel; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void clearWeather() { - // CraftBukkit start -- this.worldDataServer.setStorm(false); -+ this.worldDataServer.setStorm(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - when passing the night - // If we stop due to everyone sleeping we should reset the weather duration to some other random value. - // Not that everyone ever manages to get the whole server to sleep at the same time.... - if (!this.worldDataServer.hasStorm()) { - this.worldDataServer.setWeatherDuration(0); - } - // CraftBukkit end -- this.worldDataServer.setThundering(false); -+ this.worldDataServer.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - when passing the night - // CraftBukkit start - // If we stop due to everyone sleeping we should reset the weather duration to some other random value. - // Not that everyone ever manages to get the whole server to sleep at the same time.... -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java b/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldDataServer.java -@@ -0,0 +0,0 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - @Override - public void setThundering(boolean flag) { -+ // Paper start -+ this.setThundering(flag, org.bukkit.event.weather.ThunderChangeEvent.Cause.UNKNOWN); -+ } -+ public void setThundering(boolean flag, org.bukkit.event.weather.ThunderChangeEvent.Cause cause) { -+ // Paper end - // CraftBukkit start - if (this.thundering == flag) { - return; -@@ -0,0 +0,0 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - org.bukkit.World world = Bukkit.getWorld(getName()); - if (world != null) { -- ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag); -+ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper - Bukkit.getServer().getPluginManager().callEvent(thunder); - if (thunder.isCancelled()) { - return; -@@ -0,0 +0,0 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - @Override - public void setStorm(boolean flag) { -+ // Paper start -+ this.setStorm(flag, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); -+ } -+ -+ public void setStorm(boolean flag, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { -+ // Paper end - // CraftBukkit start - if (this.raining == flag) { - return; -@@ -0,0 +0,0 @@ public class WorldDataServer implements IWorldDataServer, SaveData { - - org.bukkit.World world = Bukkit.getWorld(getName()); - if (world != null) { -- WeatherChangeEvent weather = new WeatherChangeEvent(world, flag); -+ WeatherChangeEvent weather = new WeatherChangeEvent(world, flag, cause); // Paper - Bukkit.getServer().getPluginManager().callEvent(weather); - if (weather.isCancelled()) { - return; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public void setStorm(boolean hasStorm) { -- world.worldData.setStorm(hasStorm); -+ world.worldDataServer.setStorm(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper - setWeatherDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) - } -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public void setThundering(boolean thundering) { -- world.worldDataServer.setThundering(thundering); -+ world.worldDataServer.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper - setThunderDuration(0); // Reset weather duration (legacy behaviour) - setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) - } diff --git a/Spigot-Server-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Spigot-Server-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch deleted file mode 100644 index de900ec33c..0000000000 --- a/Spigot-Server-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Tue, 18 May 2021 14:39:44 -0700 -Subject: [PATCH] Add command line option to load extra plugin jars not in the - plugins folder - -ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - - File pluginFolder = (File) console.options.valueOf("plugins"); - -- if (pluginFolder.exists()) { -- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); -+ // Paper start -+ if (true || pluginFolder.exists()) { -+ if (!pluginFolder.exists()) { -+ pluginFolder.mkdirs(); -+ } -+ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); -+ // Paper end - for (Plugin plugin : plugins) { - try { - String message = String.format("Loading %s", plugin.getDescription().getFullName()); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - } - -+ // Paper start -+ private List extraPluginJars() { -+ @SuppressWarnings("unchecked") -+ final List jars = (List) this.console.options.valuesOf("add-plugin"); -+ return jars.stream() -+ .filter(File::exists) -+ .filter(File::isFile) -+ .filter(file -> file.getName().endsWith(".jar")) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ // Paper end -+ - public void enablePlugins(PluginLoadOrder type) { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - .ofType(String.class) - .defaultsTo("Unknown Server") - .describedAs("Name"); -+ -+ acceptsAll(asList("add-plugin", "add-extra-plugin-jar")) -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File[] {}) -+ .describedAs("Specify paths to extra plugin jars to be loaded in addition to those in the plugins folder. This argument can be specified multiple times, once for each extra plugin jar path."); - // Paper end - } - }; diff --git a/Spigot-Server-Patches/Add-config-to-disable-ender-dragon-legacy-check.patch b/Spigot-Server-Patches/Add-config-to-disable-ender-dragon-legacy-check.patch deleted file mode 100644 index e13071e6ee..0000000000 --- a/Spigot-Server-Patches/Add-config-to-disable-ender-dragon-legacy-check.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 22 Jun 2018 10:38:31 -0500 -Subject: [PATCH] Add config to disable ender dragon legacy check - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void shieldBlockingDelay() { - shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); - } -+ -+ public boolean scanForLegacyEnderDragon = true; -+ private void scanForLegacyEnderDragon() { -+ scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -0,0 +0,0 @@ public class EnderDragonBattle { - private boolean dragonKilled; - private boolean previouslyKilled; - public UUID dragonUUID; -- private boolean n; -+ private boolean n; private void setScanForLegacyFight(boolean scanForLegacyFight) { this.n = scanForLegacyFight; } private boolean scanForLegacyFight() { return this.n; } // Paper - OBFHELPER - public BlockPosition exitPortalLocation; - public EnumDragonRespawn respawnPhase; - private int q; -@@ -0,0 +0,0 @@ public class EnderDragonBattle { - this.bossBattle = (BossBattleServer) (new BossBattleServer(new ChatMessage("entity.minecraft.ender_dragon"), BossBattle.BarColor.PINK, BossBattle.BarStyle.PROGRESS)).setPlayMusic(true).c(true); - this.gateways = Lists.newArrayList(); - this.n = true; -+ // Paper start -+ setScanForLegacyFight(worldserver.paperConfig.scanForLegacyEnderDragon); -+ if (!scanForLegacyFight()) dragonKilled = true; -+ // Paper end - this.world = worldserver; - if (nbttagcompound.hasKeyOfType("DragonKilled", 99)) { - if (nbttagcompound.b("Dragon")) { diff --git a/Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch b/Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch deleted file mode 100644 index 974c7c1e57..0000000000 --- a/Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Suddenly -Date: Tue, 1 Mar 2016 13:51:54 -0600 -Subject: [PATCH] Add configurable despawn distances for living entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void nerfedMobsShouldJump() { - nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); - } -+ -+ public int softDespawnDistance; -+ public int hardDespawnDistance; -+ private void despawnDistances() { -+ softDespawnDistance = getInt("despawn-ranges.soft", 32); // 32^2 = 1024, Minecraft Default -+ hardDespawnDistance = getInt("despawn-ranges.hard", 128); // 128^2 = 16384, Minecraft Default -+ -+ if (softDespawnDistance > hardDespawnDistance) { -+ softDespawnDistance = hardDespawnDistance; -+ } -+ -+ log("Living Entity Despawn Ranges: Soft: " + softDespawnDistance + " Hard: " + hardDespawnDistance); -+ -+ softDespawnDistance = softDespawnDistance*softDespawnDistance; -+ hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - int i = this.getEntityType().e().f(); - int j = i * i; - -- if (d0 > (double) j) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (d0 > (double) world.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.die(); - } - - int k = this.getEntityType().e().g(); - int l = k * k; - -- if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check -+ if (this.ticksFarFromPlayer > 600 && this.random.nextInt(800) == 0 && d0 > world.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances - this.die(); -- } else if (d0 < (double) l) { -+ } else if (d0 < world.paperConfig.softDespawnDistance) { // Paper - custom despawn distances - this.ticksFarFromPlayer = 0; - } - } diff --git a/Spigot-Server-Patches/Add-configurable-portal-search-radius.patch b/Spigot-Server-Patches/Add-configurable-portal-search-radius.patch deleted file mode 100644 index 584b4ae3a9..0000000000 --- a/Spigot-Server-Patches/Add-configurable-portal-search-radius.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:46:17 -0600 -Subject: [PATCH] Add configurable portal search radius - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); - } -+ -+ public int portalSearchRadius; -+ public int portalCreateRadius; -+ public boolean portalSearchVanillaDimensionScaling; -+ private void portalSearchRadius() { -+ portalSearchRadius = getInt("portal-search-radius", 128); -+ portalCreateRadius = getInt("portal-create-radius", 16); -+ portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - double d4 = DimensionManager.a(this.world.getDimensionManager(), worldserver.getDimensionManager()); - BlockPosition blockposition = new BlockPosition(MathHelper.a(this.locX() * d4, d0, d2), this.locY(), MathHelper.a(this.locZ() * d4, d1, d3)); - // CraftBukkit start -- CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); -+ // Paper start -+ int portalSearchRadius = worldserver.paperConfig.portalSearchRadius; -+ if (world.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER -+ portalSearchRadius = (int) (portalSearchRadius / worldserver.getDimensionManager().getCoordinateScale()); -+ } -+ // Paper end -+ CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, worldserver.paperConfig.portalCreateRadius); // Paper start - configurable portal radius - if (event == null) { - return null; - } -diff --git a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -+++ b/src/main/java/net/minecraft/world/level/portal/PortalTravelAgent.java -@@ -0,0 +0,0 @@ public class PortalTravelAgent { - - public Optional findPortal(BlockPosition blockposition, boolean flag) { - // CraftBukkit start -- return findPortal(blockposition, flag ? 16 : 128); // Search Radius -+ return findPortal(blockposition, flag ? world.paperConfig.portalCreateRadius : world.paperConfig.portalSearchRadius); // Paper - search Radius - } - - public Optional findPortal(BlockPosition blockposition, int i) { diff --git a/Spigot-Server-Patches/Add-configuration-option-to-prevent-player-names-fro.patch b/Spigot-Server-Patches/Add-configuration-option-to-prevent-player-names-fro.patch deleted file mode 100644 index 6f9c18a75d..0000000000 --- a/Spigot-Server-Patches/Add-configuration-option-to-prevent-player-names-fro.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Fri, 9 Jun 2017 07:24:34 -0700 -Subject: [PATCH] Add configuration option to prevent player names from being - suggested - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); - flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); - } -+ -+ public static boolean suggestPlayersWhenNullTabCompletions = true; -+ private static void suggestPlayersWhenNull() { -+ suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - return true; - } -+ -+ @Override -+ public boolean suggestPlayerNamesWhenNullTabCompletions() { -+ return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Spigot-Server-Patches/Add-dropLeash-variable-to-EntityUnleashEvent.patch deleted file mode 100644 index b334771bcf..0000000000 --- a/Spigot-Server-Patches/Add-dropLeash-variable-to-EntityUnleashEvent.patch +++ /dev/null @@ -1,156 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -Date: Fri, 29 Jan 2021 15:13:11 +0100 -Subject: [PATCH] Add dropLeash variable to EntityUnleashEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -0,0 +0,0 @@ public abstract class EntityCreature extends EntityInsentient { - - if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { - if (f > entity.world.paperConfig.maxLeashDistance) { // Paper -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - return; -@@ -0,0 +0,0 @@ public abstract class EntityCreature extends EntityInsentient { - - this.x(f); - if (f > entity.world.paperConfig.maxLeashDistance) { // Paper -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - this.goalSelector.a(PathfinderGoal.Type.MOVE); - } else if (f > 6.0F) { - double d0 = (entity.locX() - this.locX()) / (double) f; -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTargetEvent; - import org.bukkit.event.entity.EntityTransformEvent; - import org.bukkit.event.entity.EntityUnleashEvent; - import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper - // CraftBukkit end - - public abstract class EntityInsentient extends EntityLiving { -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - return EnumInteractionResult.PASS; - } else if (this.getLeashHolder() == entityhuman) { - // CraftBukkit start - fire PlayerUnleashEntityEvent -- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, entityhuman, !entityhuman.abilities.canInstantlyBuild); -+ if (event.isCancelled()) { -+ // Paper end - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutAttachEntity(this, this.getLeashHolder())); - return EnumInteractionResult.PASS; - } - // CraftBukkit end -- this.unleash(true, !entityhuman.abilities.canInstantlyBuild); -+ this.unleash(true, event.isDropLeash()); // Paper - drop leash variable - return EnumInteractionResult.a(this.world.isClientSide); - } else { - EnumInteractionResult enuminteractionresult = this.c(entityhuman, enumhand); -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - - if (this.leashHolder != null) { - if (!this.isAlive() || !this.leashHolder.isAlive()) { -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - } -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - boolean flag1 = super.a(entity, flag); - - if (flag1 && this.isLeashed()) { -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.unleash(true, true); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - - return flag1; -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - protected void bN() { - super.bN(); -- this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit -- this.unleash(true, false); -+ // Paper start - drop leash variable -+ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); -+ this.world.getServer().getPluginManager().callEvent(event); // CraftBukkit -+ this.unleash(true, event.isDropLeash()); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityLeash.java -@@ -0,0 +0,0 @@ import net.minecraft.server.level.WorldServer; - import org.bukkit.craftbukkit.event.CraftEventFactory; - // CraftBukkit end - -+import org.bukkit.event.player.PlayerUnleashEntityEvent; // Paper -+ - public class EntityLeash extends EntityHanging { - - public EntityLeash(EntityTypes entitytypes, World world) { -@@ -0,0 +0,0 @@ public class EntityLeash extends EntityHanging { - entityinsentient = (EntityInsentient) iterator.next(); - if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { - // CraftBukkit start -- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman).isCancelled()) { -+ // Paper start - drop leash variable -+ PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman, !entityhuman.abilities.canInstantlyBuild); -+ if (event.isCancelled()) { -+ // Paper end - die = false; - continue; - } -- entityinsentient.unleash(true, !entityhuman.abilities.canInstantlyBuild); // false -> survival mode boolean -+ entityinsentient.unleash(true, event.isDropLeash()); // false -> survival mode boolean // Paper - drop leash variable - // CraftBukkit end - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return itemInHand; - } - -- public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player) { -- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); -+ // Paper start - drop leash variable -+ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(EntityInsentient entity, EntityHuman player, boolean dropLeash) { -+ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); -+ // Paper end - entity.world.getServer().getPluginManager().callEvent(event); - return event; - } diff --git a/Spigot-Server-Patches/Add-effect-to-block-break-naturally.patch b/Spigot-Server-Patches/Add-effect-to-block-break-naturally.patch deleted file mode 100644 index 4c183d1106..0000000000 --- a/Spigot-Server-Patches/Add-effect-to-block-break-naturally.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jan 2020 12:25:07 -0600 -Subject: [PATCH] Add effect to block break naturally - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - - @Override - public boolean breakNaturally(ItemStack item) { -+ // Paper start -+ return breakNaturally(item, false); -+ } -+ -+ @Override -+ public boolean breakNaturally(ItemStack item, boolean triggerEffect) { -+ // Paper end - // Order matters here, need to drop before setting to air so skulls can get their data - net.minecraft.world.level.block.state.IBlockData iblockdata = this.getNMS(); - net.minecraft.world.level.block.Block block = iblockdata.getBlock(); -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - // Modelled off EntityHuman#hasBlock - if (block != Blocks.AIR && (item == null || !iblockdata.isRequiresSpecialTool() || nmsItem.canDestroySpecialBlock(iblockdata))) { - net.minecraft.world.level.block.Block.dropItems(iblockdata, world.getMinecraftWorld(), position, world.getTileEntity(position), null, nmsItem); -+ if (triggerEffect) world.triggerEffect(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getCombinedId(block.getBlockData())); // Paper - result = true; - } - diff --git a/Spigot-Server-Patches/Add-entity-liquid-API.patch b/Spigot-Server-Patches/Add-entity-liquid-API.patch deleted file mode 100644 index a531656cd1..0000000000 --- a/Spigot-Server-Patches/Add-entity-liquid-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 2 Jul 2020 18:11:43 -0500 -Subject: [PATCH] Add entity liquid API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.inWater; - } - -- private boolean isInRain() { -+ public boolean isInRain() { // Paper - private -> public - BlockPosition blockposition = this.getChunkCoordinates(); - - return this.world.isRainingAt(blockposition) || this.world.isRainingAt(new BlockPosition((double) blockposition.getX(), this.getBoundingBox().maxY, (double) blockposition.getZ())); - } - -+ public final boolean isInBubbleColumn() { return k(); } // Paper - OBFHELPER - private boolean k() { - return this.world.getType(this.getChunkCoordinates()).a(Blocks.BUBBLE_COLUMN); - } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.isInWater() || this.isInRain() || this.k(); - } - -+ public final boolean isInWaterOrBubbleColumn() { return aH(); } // Paper - OBFHELPER - public boolean aH() { - return this.isInWater() || this.k(); - } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.O == tag; - } - -+ public final boolean isInLava() { return aQ(); } // Paper - OBFHELPER - public boolean aQ() { - return !this.justCreated && this.M.getDouble(TagsFluid.LAVA) > 0.0D; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { - return getHandle().spawnReason; - } -+ -+ public boolean isInRain() { -+ return getHandle().isInRain(); -+ } -+ -+ public boolean isInBubbleColumn() { -+ return getHandle().isInBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRain() { -+ return getHandle().isInWaterOrRain(); -+ } -+ -+ public boolean isInWaterOrBubbleColumn() { -+ return getHandle().isInWaterOrBubbleColumn(); -+ } -+ -+ public boolean isInWaterOrRainOrBubbleColumn() { -+ return getHandle().isInWaterOrRainOrBubble(); -+ } -+ -+ public boolean isInLava() { -+ return getHandle().isInLava(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Add-environment-variable-to-disable-server-gui.patch b/Spigot-Server-Patches/Add-environment-variable-to-disable-server-gui.patch deleted file mode 100644 index 7b868cfcda..0000000000 --- a/Spigot-Server-Patches/Add-environment-variable-to-disable-server-gui.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Mon, 17 May 2021 00:34:55 -0700 -Subject: [PATCH] Add environment variable to disable server gui - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ public class Main { - */ - boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); - -+ if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper - if (flag1 && !GraphicsEnvironment.isHeadless()) { - dedicatedserver1.bd(); - } diff --git a/Spigot-Server-Patches/Add-exception-reporting-event.patch b/Spigot-Server-Patches/Add-exception-reporting-event.patch deleted file mode 100644 index cc82314f53..0000000000 --- a/Spigot-Server-Patches/Add-exception-reporting-event.patch +++ /dev/null @@ -1,264 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 03:15:41 -0600 -Subject: [PATCH] Add exception reporting event - - -diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Preconditions; -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; -+ -+/** -+ * Reporting wrapper to catch exceptions not natively -+ */ -+public class ServerSchedulerReportingWrapper implements Runnable { -+ -+ private final CraftTask internalTask; -+ -+ public ServerSchedulerReportingWrapper(CraftTask internalTask) { -+ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ internalTask.run(); -+ } catch (RuntimeException e) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask)) -+ ); -+ throw e; -+ } catch (Throwable t) { -+ internalTask.getOwner().getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask)) -+ ); //Do not rethrow, since it is not permitted with Runnable#run -+ } -+ } -+ -+ public CraftTask getInternalTask() { -+ return internalTask; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return true; - } catch (Exception exception) { - PlayerChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return false; - } - } -diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.players; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.io.Files; -@@ -0,0 +0,0 @@ public class NameReferencingFileConverter { - root = NBTCompressedStreamTools.a(new java.io.FileInputStream(file5)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - - if (root != null) { -@@ -0,0 +0,0 @@ public class NameReferencingFileConverter { - NBTCompressedStreamTools.a(root, new java.io.FileOutputStream(file2)); - } catch (Exception exception) { - exception.printStackTrace(); -+ ServerInternalException.reportInternalException(exception); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.entity.ai.village; - -+import com.destroystokyo.paper.exception.ServerInternalException; -+ - import java.util.Iterator; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; -@@ -0,0 +0,0 @@ public class VillageSiege implements MobSpawner { - entityzombie.prepare(worldserver, worldserver.getDamageScaler(entityzombie.getChunkCoordinates()), EnumMobSpawn.EVENT, (GroupDataEntity) null, (NBTTagCompound) null); - } catch (Exception exception) { - VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); -+ ServerInternalException.reportInternalException(exception); // Paper - return; - } - -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - } - } catch (Exception exception) { - SpawnerCreature.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - return null; - } - } -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - entity = biomesettingsmobs_c.c.a((World) worldaccess.getMinecraftWorld()); - } catch (Exception exception) { - SpawnerCreature.LOGGER.warn("Failed to create mob", exception); -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - continue; - } - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level; - -+import co.aikar.timings.Timing; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerInternalException; -+import com.google.common.base.MoreObjects; - import com.google.common.collect.Lists; - import com.mojang.serialization.Codec; - import java.io.IOException; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - gameprofilerfiller.exit(); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); -+ String msg = "TileEntity threw exception at " + tileentity.getWorld().getWorld().getName() + ":" + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); -+ // Paper end - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - continue; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - consumer.accept(entity); - } catch (Throwable throwable) { - // Paper start - Prevent tile entity and entity crashes -- System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); -+ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); -+ System.err.println(msg); - throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); - entity.dead = true; - return; - // Paper end -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.chunk; - -+import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - this.tileEntities.remove(blockposition); - // Paper end - } else { -- System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() -- + " (" + getType(blockposition) + ") where there was no entity tile!"); -- System.out.println("Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); -- new Exception().printStackTrace(); -+ // Paper start -+ ServerInternalException e = new ServerInternalException( -+ "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," -+ + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() -+ + " (" + getType(blockposition) + ") where there was no entity tile!\n" + -+ "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); -+ e.printStackTrace(); -+ ServerInternalException.reportInternalException(e); -+ // Paper end - // CraftBukkit end - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper - return false; - } - } -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - filechannel.write(bytebuffer); - } catch (Throwable throwable1) { - throwable = throwable1; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable1; - } finally { - if (filechannel != null) { -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -@@ -0,0 +0,0 @@ public class WorldPersistentData { - } - } catch (Throwable throwable6) { - throwable = throwable6; -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - throw throwable6; - } finally { - if (fileinputstream != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ import java.util.concurrent.atomic.AtomicInteger; - import java.util.concurrent.atomic.AtomicReference; - import java.util.function.Consumer; - import java.util.logging.Level; -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.destroystokyo.paper.event.server.ServerExceptionEvent; -+import com.destroystokyo.paper.exception.ServerSchedulerException; - import org.apache.commons.lang.Validate; - import org.bukkit.plugin.IllegalPluginAccessException; - import org.bukkit.plugin.Plugin; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - msg, - throwable); - } -+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent( -+ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); - // Paper end - } finally { - currentTask = null; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -- executor.execute(task); -+ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } diff --git a/Spigot-Server-Patches/Add-fast-alternative-constructor-for-Vector3f.patch b/Spigot-Server-Patches/Add-fast-alternative-constructor-for-Vector3f.patch deleted file mode 100644 index 53affe4aba..0000000000 --- a/Spigot-Server-Patches/Add-fast-alternative-constructor-for-Vector3f.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Irmo van den Berge -Date: Wed, 10 Mar 2021 21:26:31 +0100 -Subject: [PATCH] Add fast alternative constructor for Vector3f - -Signed-off-by: Irmo van den Berge - -diff --git a/src/main/java/net/minecraft/core/Vector3f.java b/src/main/java/net/minecraft/core/Vector3f.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/Vector3f.java -+++ b/src/main/java/net/minecraft/core/Vector3f.java -@@ -0,0 +0,0 @@ public class Vector3f { - this(nbttaglist.i(0), nbttaglist.i(1), nbttaglist.i(2)); - } - -+ // Paper start - faster alternative constructor -+ private Vector3f(float x, float y, float z, Void dummy_var) { -+ this.x = x; -+ this.y = y; -+ this.z = z; -+ } -+ -+ public static Vector3f createWithoutValidityChecks(float x, float y, float z) { -+ return new Vector3f(x, y, z, null); -+ } -+ // Paper end -+ - public NBTTagList a() { - NBTTagList nbttaglist = new NBTTagList(); - diff --git a/Spigot-Server-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Spigot-Server-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch deleted file mode 100644 index 0515cea2e3..0000000000 --- a/Spigot-Server-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aleksander Jagiello -Date: Sun, 24 Jan 2021 22:17:54 +0100 -Subject: [PATCH] Add getMainThreadExecutor to BukkitScheduler - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - public BukkitTask runTaskTimerAsynchronously(Plugin plugin, BukkitRunnable task, long delay, long period) throws IllegalArgumentException { - throw new UnsupportedOperationException("Use BukkitRunnable#runTaskTimerAsynchronously(Plugin, long, long)"); - } -+ -+ // Paper start - add getMainThreadExecutor -+ @Override -+ public Executor getMainThreadExecutor(Plugin plugin) { -+ Validate.notNull(plugin, "Plugin cannot be null"); -+ return command -> { -+ Validate.notNull(command, "Command cannot be null"); -+ this.runTask(plugin, command); -+ }; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-getOfflinePlayerIfCached-String.patch b/Spigot-Server-Patches/Add-getOfflinePlayerIfCached-String.patch deleted file mode 100644 index 96ab5c9c1f..0000000000 --- a/Spigot-Server-Patches/Add-getOfflinePlayerIfCached-String.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: oxygencraft <21054297+oxygencraft@users.noreply.github.com> -Date: Sun, 25 Oct 2020 18:34:50 +1100 -Subject: [PATCH] Add getOfflinePlayerIfCached(String) - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return result; - } - -+ // Paper start -+ @Override -+ @Nullable -+ public OfflinePlayer getOfflinePlayerIfCached(String name) { -+ Validate.notNull(name, "Name cannot be null"); -+ Validate.notEmpty(name, "Name cannot be empty"); -+ -+ OfflinePlayer result = getPlayerExact(name); -+ if (result == null) { -+ GameProfile profile = console.getUserCache().getProfileIfCached(name); -+ -+ if (profile != null) { -+ result = getOfflinePlayer(profile); -+ } -+ } else { -+ offlinePlayers.remove(result.getUniqueId()); -+ } -+ -+ return result; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOfflinePlayer(UUID id) { - Validate.notNull(id, "UUID cannot be null"); diff --git a/Spigot-Server-Patches/Add-hand-to-bucket-events.patch b/Spigot-Server-Patches/Add-hand-to-bucket-events.patch deleted file mode 100644 index 50ceef31fb..0000000000 --- a/Spigot-Server-Patches/Add-hand-to-bucket-events.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Thu, 2 Aug 2018 08:44:35 -0500 -Subject: [PATCH] Add hand to bucket events - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); - } - -- public BlockPosition getSpawn() { -- BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -- -- if (!this.getWorldBorder().a(blockposition)) { -- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -- } -- -- return blockposition; -- } -+ // Paper - moved up to World -+ //public BlockPosition getSpawn() { -+ // BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -+ // -+ // if (!this.getWorldBorder().a(blockposition)) { -+ // blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ // } -+ // -+ // return blockposition; -+ //} -+ // Paper end - - public float v() { - return this.worldData.d(); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityCow.java -@@ -0,0 +0,0 @@ public class EntityCow extends EntityAnimal { - - if (itemstack.getItem() == Items.BUCKET && !this.isBaby()) { - // CraftBukkit start - Got milk? -- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET); -+ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) entityhuman.world, entityhuman, this.getChunkCoordinates(), this.getChunkCoordinates(), null, itemstack, Items.MILK_BUCKET, enumhand); // Paper - add enumHand - - if (event.isCancelled()) { - return EnumInteractionResult.PASS; -diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBucket.java -+++ b/src/main/java/net/minecraft/world/item/ItemBucket.java -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - if (iblockdata.getBlock() instanceof IFluidSource) { - // CraftBukkit start - FluidType dummyFluid = ((IFluidSource) iblockdata.getBlock()).removeFluid(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); -- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a()); -+ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((WorldServer) world, entityhuman, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.a(), enumhand); // Paper - add enumhand - - if (event.isCancelled()) { - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - iblockdata = world.getType(blockposition); - BlockPosition blockposition2 = iblockdata.getBlock() instanceof IFluidContainer && this.fluidType == FluidTypes.WATER ? blockposition : blockposition1; - -- if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack)) { // CraftBukkit -+ if (this.a(entityhuman, world, blockposition2, movingobjectpositionblock1, movingobjectpositionblock1.getDirection(), blockposition, itemstack, enumhand)) { // CraftBukkit // Paper - add enumhand - this.a(world, itemstack, blockposition2); - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.y.a((EntityPlayer) entityhuman, blockposition2, itemstack); -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - public void a(World world, ItemStack itemstack, BlockPosition blockposition) {} - - public boolean a(@Nullable EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock) { -- return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null); -+ // Paper start - add enumHand -+ return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, null); - } - -- public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack) { -+ public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { -+ // Paper end - // CraftBukkit end - if (!(this.fluidType instanceof FluidTypeFlowing)) { - return false; -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - - // CraftBukkit start - if (flag1 && entityhuman != null) { -- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack); -+ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((WorldServer) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand - if (event.isCancelled()) { - ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition)); // SPIGOT-4238: needed when looking through entity - ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - } - // CraftBukkit end - if (!flag1) { -- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack); // CraftBukkit -+ return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPosition().shift(movingobjectpositionblock.getDirection()), (MovingObjectPositionBlock) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand - } else if (world.getDimensionManager().isNether() && this.fluidType.a((Tag) TagsFluid.WATER)) { - int i = blockposition.getX(); - int j = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - // Paper end - -+ // Paper start - moved up from WorldServer -+ public BlockPosition getSpawn() { -+ BlockPosition blockposition = new BlockPosition(this.worldData.a(), this.worldData.b(), this.worldData.c()); -+ -+ if (!this.getWorldBorder().a(blockposition)) { -+ blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); -+ } -+ -+ return blockposition; -+ } -+ // Paper end - @Override - public boolean s_() { - return this.isClientSide; -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - public static Entity entityDamage; // For use in EntityDamageByEntityEvent - - // helper methods -- private static boolean canBuild(WorldServer world, Player player, int x, int z) { -+ private static boolean canBuild(World world, Player player, int x, int z) { - int spawnSize = Bukkit.getServer().getSpawnRadius(); - - if (world.getDimensionKey() != World.OVERWORLD) return true; -@@ -0,0 +0,0 @@ public class CraftEventFactory { - } - - private static PlayerEvent getPlayerBucketEvent(boolean isFilling, WorldServer world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item) { -+ // Paper start - add enumHand -+ return getPlayerBucketEvent(isFilling, world, who, changed, clicked, clickedFace, itemstack, item, null); -+ } -+ -+ public static PlayerBucketEmptyEvent callPlayerBucketEmptyEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, EnumHand enumHand) { -+ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); -+ } -+ -+ public static PlayerBucketFillEvent callPlayerBucketFillEvent(World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, EnumHand enumHand) { -+ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); -+ } -+ -+ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, World world, EntityHuman who, BlockPosition changed, BlockPosition clicked, EnumDirection clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, EnumHand enumHand) { -+ // Paper end - Player player = (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item); - Material bucket = CraftMagicNumbers.getMaterial(itemstack.getItem()); -@@ -0,0 +0,0 @@ public class CraftEventFactory { - - PlayerEvent event; - if (isFilling) { -- event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketFillEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketFillEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } else { -- event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand); -+ event = new PlayerBucketEmptyEvent(player, block, blockClicked, blockFace, bucket, itemInHand, enumHand == null ? null : enumHand == EnumHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand - ((PlayerBucketEmptyEvent) event).setCancelled(!canBuild(world, player, changed.getX(), changed.getZ())); - } - diff --git a/Spigot-Server-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Spigot-Server-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch deleted file mode 100644 index c4e6764d91..0000000000 --- a/Spigot-Server-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Wed, 13 Apr 2016 20:21:38 -0700 -Subject: [PATCH] Add handshake event to allow plugins to handle client - handshaking logic themselves - - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - // CraftBukkit end - private static final IChatBaseComponent a = new ChatComponentText("Ignoring status request"); - private final MinecraftServer b; -- private final NetworkManager c; -+ private final NetworkManager c; final NetworkManager getNetworkManager() { return this.c; } // Paper - OBFHELPER - - public HandshakeListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { - this.b = minecraftserver; -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - this.c.close(chatmessage); - } else { - this.c.setPacketListener(new LoginListener(this.b, this.c)); -+ // Paper start - handshake event -+ boolean proxyLogicEnabled = org.spigotmc.SpigotConfig.bungee; -+ boolean handledByEvent = false; -+ // Try and handle the handshake through the event -+ if (com.destroystokyo.paper.event.player.PlayerHandshakeEvent.getHandlerList().getRegisteredListeners().length != 0) { // Hello? Can you hear me? -+ java.net.SocketAddress socketAddress = this.getNetworkManager().socketAddress; -+ String hostnameOfRemote = socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getHostString() : InetAddress.getLoopbackAddress().getHostAddress(); -+ com.destroystokyo.paper.event.player.PlayerHandshakeEvent event = new com.destroystokyo.paper.event.player.PlayerHandshakeEvent(packethandshakinginsetprotocol.hostname, hostnameOfRemote, !proxyLogicEnabled); -+ if (event.callEvent()) { -+ // If we've failed somehow, let the client know so and go no further. -+ if (event.isFailed()) { -+ chatmessage = new ChatMessage(event.getFailMessage()); -+ this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); -+ this.getNetworkManager().close(chatmessage); -+ return; -+ } -+ -+ if (event.getServerHostname() != null) packethandshakinginsetprotocol.hostname = event.getServerHostname(); -+ if (event.getSocketAddressHostname() != null) this.getNetworkManager().socketAddress = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); -+ this.getNetworkManager().spoofedUUID = event.getUniqueId(); -+ this.getNetworkManager().spoofedProfile = gson.fromJson(event.getPropertiesJson(), com.mojang.authlib.properties.Property[].class); -+ handledByEvent = true; // Hooray, we did it! -+ } -+ } -+ // Don't try and handle default logic if it's been handled by the event. -+ if (!handledByEvent && proxyLogicEnabled) { -+ // Paper end - // Spigot Start -- if (org.spigotmc.SpigotConfig.bungee) { -+ //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! - String[] split = packethandshakinginsetprotocol.hostname.split("\00"); - if ( ( split.length == 3 || split.length == 4 ) && ( HOST_PATTERN.matcher( split[1] ).matches() ) ) { - packethandshakinginsetprotocol.hostname = split[0]; diff --git a/Spigot-Server-Patches/Add-ignore-discounts-API.patch b/Spigot-Server-Patches/Add-ignore-discounts-API.patch deleted file mode 100644 index 728df9b6ac..0000000000 --- a/Spigot-Server-Patches/Add-ignore-discounts-API.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Mon, 9 Nov 2020 20:44:51 +0100 -Subject: [PATCH] Add ignore discounts API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - - while (iterator.hasNext()) { - MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); -+ if (merchantrecipe.ignoreDiscounts) continue; // Paper - - // CraftBukkit start - int bonus = -MathHelper.d((float) i * merchantrecipe.getPriceMultiplier()); -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - - while (iterator1.hasNext()) { - MerchantRecipe merchantrecipe1 = (MerchantRecipe) iterator1.next(); -+ if (merchantrecipe1.ignoreDiscounts) continue; // Paper - double d0 = 0.3D + 0.0625D * (double) j; - int k = (int) Math.floor(d0 * (double) merchantrecipe1.a().getCount()); - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -@@ -0,0 +0,0 @@ public class MerchantRecipe { - private int demand; - public float priceMultiplier; - public int xp; -+ public boolean ignoreDiscounts; // Paper - // CraftBukkit start - private CraftMerchantRecipe bukkitHandle; - -@@ -0,0 +0,0 @@ public class MerchantRecipe { - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { -- this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, false, bukkit); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, boolean ignoreDiscounts, CraftMerchantRecipe bukkit) { -+ this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.bukkitHandle = bukkit; - } - // CraftBukkit end -@@ -0,0 +0,0 @@ public class MerchantRecipe { - - this.specialPrice = nbttagcompound.getInt("specialPrice"); - this.demand = nbttagcompound.getInt("demand"); -+ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, int i, int j, float f) { -@@ -0,0 +0,0 @@ public class MerchantRecipe { - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f) { -- this(itemstack, itemstack1, itemstack2, i, j, k, f, 0); -+ // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, false); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, boolean ignoreDiscounts) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, 0, ignoreDiscounts); - } - - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l) { -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, l, false); -+ } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { -+ this.ignoreDiscounts = ignoreDiscounts; -+ // Paper end - this.rewardExp = true; - this.xp = 1; - this.buyingItem1 = itemstack; -@@ -0,0 +0,0 @@ public class MerchantRecipe { - nbttagcompound.setFloat("priceMultiplier", this.priceMultiplier); - nbttagcompound.setInt("specialPrice", this.specialPrice); - nbttagcompound.setInt("demand", this.demand); -+ nbttagcompound.setBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper - return nbttagcompound; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantRecipe.java -@@ -0,0 +0,0 @@ public class CraftMerchantRecipe extends MerchantRecipe { - } - - public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier) { -- super(result, uses, maxUses, experienceReward, experience, priceMultiplier); -+ // Paper start - add ignoreDiscounts param -+ this(result, uses, maxUses, experienceReward, experience, priceMultiplier, false); -+ } -+ public CraftMerchantRecipe(ItemStack result, int uses, int maxUses, boolean experienceReward, int experience, float priceMultiplier, boolean ignoreDiscounts) { -+ super(result, uses, maxUses, experienceReward, experience, priceMultiplier, ignoreDiscounts); -+ // Paper end - this.handle = new net.minecraft.world.item.trading.MerchantRecipe( - net.minecraft.world.item.ItemStack.b, - net.minecraft.world.item.ItemStack.b, -@@ -0,0 +0,0 @@ public class CraftMerchantRecipe extends MerchantRecipe { - maxUses, - experience, - priceMultiplier, -+ ignoreDiscounts, // Paper - add ignoreDiscounts param - this - ); - this.setExperienceReward(experienceReward); -@@ -0,0 +0,0 @@ public class CraftMerchantRecipe extends MerchantRecipe { - handle.priceMultiplier = priceMultiplier; - } - -+ // Paper start -+ @Override -+ public boolean shouldIgnoreDiscounts() { -+ return this.handle.ignoreDiscounts; -+ } -+ -+ @Override -+ public void setIgnoreDiscounts(boolean ignoreDiscounts) { -+ this.handle.ignoreDiscounts = ignoreDiscounts; -+ } -+ // Paper end -+ - public net.minecraft.world.item.trading.MerchantRecipe toMinecraft() { - List ingredients = getIngredients(); - Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); -@@ -0,0 +0,0 @@ public class CraftMerchantRecipe extends MerchantRecipe { - if (recipe instanceof CraftMerchantRecipe) { - return (CraftMerchantRecipe) recipe; - } else { -- CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier()); -+ CraftMerchantRecipe craft = new CraftMerchantRecipe(recipe.getResult(), recipe.getUses(), recipe.getMaxUses(), recipe.hasExperienceReward(), recipe.getVillagerExperience(), recipe.getPriceMultiplier(), recipe.shouldIgnoreDiscounts()); // Paper - shouldIgnoreDiscounts - craft.setIngredients(recipe.getIngredients()); - - return craft; diff --git a/Spigot-Server-Patches/Add-method-to-open-already-placed-sign.patch b/Spigot-Server-Patches/Add-method-to-open-already-placed-sign.patch deleted file mode 100644 index 98dfbce4ef..0000000000 --- a/Spigot-Server-Patches/Add-method-to-open-already-placed-sign.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 1 Apr 2018 02:29:37 +0300 -Subject: [PATCH] Add method to open already placed sign - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.BlockEnchantmentTable; - import net.minecraft.world.level.block.BlockWorkbench; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.block.state.IBlockData; - import org.bukkit.GameMode; - import org.bukkit.Location; -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start - Add method to open already placed sign -+ @Override -+ public void openSign(org.bukkit.block.Sign sign) { -+ org.apache.commons.lang.Validate.isTrue(sign.getWorld().equals(this.getWorld()), "Sign must be in the same world as player is in"); -+ org.bukkit.craftbukkit.block.CraftSign craftSign = (org.bukkit.craftbukkit.block.CraftSign) sign; -+ TileEntitySign teSign = craftSign.getTileEntity(); -+ // Make sign editable temporarily, will be set back to false in PlayerConnection later -+ teSign.isEditable = true; -+ getHandle().openSign(teSign); -+ } -+ // Paper end - @Override - public boolean dropItem(boolean dropAll) { - return getHandle().dropItem(dropAll); diff --git a/Spigot-Server-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-Server-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch deleted file mode 100644 index c0fd3c8a40..0000000000 --- a/Spigot-Server-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mrapple -Date: Sun, 25 Nov 2012 13:43:39 -0600 -Subject: [PATCH] Add methods for working with arrows stuck in living entities - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - getHandle().persistentInvisibility = invisible; - getHandle().setFlag(5, invisible); - } -+ -+ // Paper start -+ @Override -+ public int getArrowsStuck() { -+ return getHandle().getArrowCount(); -+ } -+ -+ @Override -+ public void setArrowsStuck(int arrows) { -+ getHandle().setArrowCount(arrows); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/Spigot-Server-Patches/Add-missing-strikeLighting-call-to-World-spigot-stri.patch deleted file mode 100644 index 05f3a8899b..0000000000 --- a/Spigot-Server-Patches/Add-missing-strikeLighting-call-to-World-spigot-stri.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 26 Jul 2020 12:11:39 +0100 -Subject: [PATCH] Add missing strikeLighting call to - World#spigot()#strikeLightningEffect - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - lightning.teleportAndSync( loc.getX(), loc.getY(), loc.getZ() ); - lightning.isEffect = true; - lightning.isSilent = isSilent; -+ world.strikeLightning( lightning ); - return (LightningStrike) lightning.getBukkitEntity(); - } - }; diff --git a/Spigot-Server-Patches/Add-moon-phase-API.patch b/Spigot-Server-Patches/Add-moon-phase-API.patch deleted file mode 100644 index 3ff89190eb..0000000000 --- a/Spigot-Server-Patches/Add-moon-phase-API.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 16:32:11 +0200 -Subject: [PATCH] Add moon phase API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - public int getPlayerCount() { - return world.players.size(); - } -+ -+ @Override -+ public io.papermc.paper.world.MoonPhase getMoonPhase() { -+ return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); -+ } - // Paper end - - private static final Random rand = new Random(); diff --git a/Spigot-Server-Patches/Add-more-Evoker-API.patch b/Spigot-Server-Patches/Add-more-Evoker-API.patch deleted file mode 100644 index ee36abb7c8..0000000000 --- a/Spigot-Server-Patches/Add-more-Evoker-API.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:28:35 +0200 -Subject: [PATCH] Add more Evoker API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEvoker.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class EntityEvoker extends EntityIllagerWizard { - -- private EntitySheep bo; -+ private EntitySheep bo; public final EntitySheep getWololoTarget() { return this.bo; } public final void setWololoTarget(EntitySheep sheep) { this.bo = sheep; } // Paper - OBFHELPER - - public EntityEvoker(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityEvoker extends EntityIllagerWizard { - this.goalSelector.a(8, new PathfinderGoalRandomStroll(this, 0.6D)); - this.goalSelector.a(9, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 3.0F, 1.0F)); - this.goalSelector.a(10, new PathfinderGoalLookAtPlayer(this, EntityInsentient.class, 8.0F)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, (new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)).a(300)); - this.targetSelector.a(3, (new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)).a(300)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, false)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.animal.EntitySheep; - import net.minecraft.world.entity.monster.EntityEvoker; - import net.minecraft.world.entity.monster.EntityIllagerWizard; - import org.bukkit.craftbukkit.CraftServer; -@@ -0,0 +0,0 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { - public void setCurrentSpell(Evoker.Spell spell) { - getHandle().setSpell(spell == null ? EntityIllagerWizard.Spell.NONE : EntityIllagerWizard.Spell.a(spell.ordinal())); - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.entity.Sheep getWololoTarget() { -+ EntitySheep sheep = getHandle().getWololoTarget(); -+ return sheep == null ? null : (org.bukkit.entity.Sheep) sheep.getBukkitEntity(); -+ } -+ -+ @Override -+ public void setWololoTarget(org.bukkit.entity.Sheep sheep) { -+ getHandle().setWololoTarget(sheep == null ? null : ((org.bukkit.craftbukkit.entity.CraftSheep) sheep).getHandle()); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-more-WanderingTrader-API.patch b/Spigot-Server-Patches/Add-more-WanderingTrader-API.patch deleted file mode 100644 index df08a10a91..0000000000 --- a/Spigot-Server-Patches/Add-more-WanderingTrader-API.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 6 May 2021 14:56:43 +0100 -Subject: [PATCH] Add more WanderingTrader API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -0,0 +0,0 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - @Nullable - private BlockPosition bp; - private int despawnDelay; -+ // Paper start - Add more WanderingTrader API -+ public boolean canDrinkPotion = true; -+ public boolean canDrinkMilk = true; -+ // Paper end - - public EntityVillagerTrader(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - protected void initPathfinder() { - this.goalSelector.a(0, new PathfinderGoalFloat(this)); - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, PotionUtil.a(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEffects.ENTITY_WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { -- return this.world.isNight() && !entityvillagertrader.isInvisible(); -+ return canDrinkPotion && this.world.isNight() && !entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.a(0, new PathfinderGoalUseItem<>(this, new ItemStack(Items.MILK_BUCKET), SoundEffects.ENTITY_WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { -- return this.world.isDay() && entityvillagertrader.isInvisible(); -+ return canDrinkMilk && this.world.isDay() && entityvillagertrader.isInvisible(); // Paper - Add more WanderingTrader API - })); - this.goalSelector.a(1, new PathfinderGoalTradeWithPlayer(this)); - this.goalSelector.a(1, new PathfinderGoalAvoidTarget<>(this, EntityZombie.class, 8.0F, 0.5D, 0.5D)); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -@@ -0,0 +0,0 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande - public void setDespawnDelay(int despawnDelay) { - getHandle().setDespawnDelay(despawnDelay); - } -+ -+ // Paper start - Add more WanderingTrader API -+ @Override -+ public void setCanDrinkPotion(boolean bool) { -+ getHandle().canDrinkPotion = bool; -+ } -+ -+ @Override -+ public boolean canDrinkPotion() { -+ return getHandle().canDrinkPotion; -+ } -+ -+ @Override -+ public void setCanDrinkMilk(boolean bool) { -+ getHandle().canDrinkMilk = bool; -+ } -+ -+ @Override -+ public boolean canDrinkMilk() { -+ return getHandle().canDrinkMilk; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-more-Witch-API.patch b/Spigot-Server-Patches/Add-more-Witch-API.patch deleted file mode 100644 index 57c5028e01..0000000000 --- a/Spigot-Server-Patches/Add-more-Witch-API.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 14:10:46 -0500 -Subject: [PATCH] Add more Witch API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.entity.monster; - -+// Paper start -+import com.destroystokyo.paper.event.entity.WitchReadyPotionEvent; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.entity.Witch; -+// Paper end -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - private static final UUID b = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); - private static final AttributeModifier bo = new AttributeModifier(EntityWitch.b, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); - private static final DataWatcherObject bp = DataWatcher.a(EntityWitch.class, DataWatcherRegistry.i); -- private int bq; -+ private int bq; public int getPotionUseTimeLeft() { return bq; } public void setPotionUseTimeLeft(int timeLeft) { bq = timeLeft; } // Paper - OBFHELPER - private PathfinderGoalNearestHealableRaider br; - private PathfinderGoalNearestAttackableTargetWitch bs; - -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - return SoundEffects.ENTITY_WITCH_DEATH; - } - -+ public void setDrinkingPotion(boolean drinkingPotion) { v(drinkingPotion); } // Paper - OBFHELPER - public void v(boolean flag) { - this.getDataWatcher().set(EntityWitch.bp, flag); - } - -+ public boolean isDrinkingPotion() { return m(); } // Paper - OBFHELPER - public boolean m() { - return (Boolean) this.getDataWatcher().get(EntityWitch.bp); - } -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - } - - if (potionregistry != null) { -- // Paper start - ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); -- org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -- this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper start - logic moved into setDrinkingPotion, copy exact impl into the method and then comment out -+ this.setDrinkingPotion(potion); -+// org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+// this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+// // Paper end -+// this.bq = this.getItemInMainHand().k(); -+// this.v(true); -+// if (!this.isSilent()) { -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+// } -+// -+// AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -+// -+// attributemodifiable.removeModifier(EntityWitch.bo); -+// attributemodifiable.b(EntityWitch.bo); - // Paper end -- this.bq = this.getItemInMainHand().k(); -- this.v(true); -- if (!this.isSilent()) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -- } - -- AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -- -- attributemodifiable.removeModifier(EntityWitch.bo); -- attributemodifiable.b(EntityWitch.bo); - } - } - -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - super.movementTick(); - } - -+ // Paper start - moved to its own method -+ public void setDrinkingPotion(ItemStack potion) { -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end -+ this.bq = this.getItemInMainHand().k(); -+ this.v(true); -+ if (!this.isSilent()) { -+ this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_WITCH_DRINK, this.getSoundCategory(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); -+ } -+ -+ AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); -+ -+ attributemodifiable.removeModifier(EntityWitch.bo); -+ attributemodifiable.b(EntityWitch.bo); -+ } -+ // Paper end -+ - @Override - public SoundEffect eL() { - return SoundEffects.ENTITY_WITCH_CELEBRATE; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.monster.EntityWitch; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; -+// Paper start -+import com.destroystokyo.paper.entity.CraftRangedEntity; -+import com.google.common.base.Preconditions; -+import org.bukkit.Material; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, EntityWitch entity) { -@@ -0,0 +0,0 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. - public EntityType getType() { - return EntityType.WITCH; - } -+ -+ // Paper start -+ public boolean isDrinkingPotion() { -+ return getHandle().isDrinkingPotion(); -+ } -+ -+ public int getPotionUseTimeLeft() { -+ return getHandle().getPotionUseTimeLeft(); -+ } -+ -+ @Override -+ public void setPotionUseTimeLeft(int ticks) { -+ getHandle().setPotionUseTimeLeft(ticks); -+ } -+ -+ public ItemStack getDrinkingPotion() { -+ return CraftItemStack.asCraftMirror(getHandle().getItemInMainHand()); -+ } -+ -+ public void setDrinkingPotion(ItemStack potion) { -+ Preconditions.checkArgument(potion == null || potion.getType().isEmpty() || potion.getType() == Material.POTION, "must be potion, air, or null"); -+ getHandle().setDrinkingPotion(CraftItemStack.asNMSCopy(potion)); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-more-Zombie-API.patch b/Spigot-Server-Patches/Add-more-Zombie-API.patch deleted file mode 100644 index 189522f35d..0000000000 --- a/Spigot-Server-Patches/Add-more-Zombie-API.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 04:29:59 -0500 -Subject: [PATCH] Add more Zombie API - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - private int bt; - public int drownedConversionTime; - private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field -+ private boolean shouldBurnInDay = true; // Paper - - public EntityZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - super.movementTick(); - } - -+ // Paper start -+ public void stopDrowning() { -+ this.drownedConversionTime = -1; -+ this.getDataWatcher().set(EntityZombie.DROWN_CONVERTING, false); -+ } -+ // Paper end - public void startDrownedConversion(int i) { - this.lastTick = MinecraftServer.currentTick; // CraftBukkit - this.drownedConversionTime = i; -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - - } - -+ public boolean shouldBurnInDay() { return T_(); } // Paper - OBFHELPER - protected boolean T_() { -- return true; -+ return this.shouldBurnInDay; // Paper - use api value instead -+ } -+ -+ // Paper start -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ this.shouldBurnInDay = shouldBurnInDay; - } -+ // Paper end - - @Override - public boolean damageEntity(DamageSource damagesource, float f) { -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - nbttagcompound.setBoolean("CanBreakDoors", this.eU()); - nbttagcompound.setInt("InWaterTime", this.isInWater() ? this.bt : -1); - nbttagcompound.setInt("DrownedConversionTime", this.isDrownConverting() ? this.drownedConversionTime : -1); -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - if (nbttagcompound.hasKeyOfType("DrownedConversionTime", 99) && nbttagcompound.getInt("DrownedConversionTime") > -1) { - this.startDrownedConversion(nbttagcompound.getInt("DrownedConversionTime")); - } -- -+ // Paper start -+ if (nbttagcompound.hasKey("Paper.ShouldBurnInDay")) { -+ shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -0,0 +0,0 @@ public class CraftZombie extends CraftMonster implements Zombie { - @Override - public void setAgeLock(boolean b) { - } -+ // Paper start -+ @Override -+ public boolean isDrowning() { -+ return getHandle().isDrownConverting(); -+ } -+ -+ @Override -+ public void startDrowning(int drownedConversionTime) { -+ getHandle().startDrownedConversion(drownedConversionTime); -+ } -+ -+ @Override -+ public void stopDrowning() { -+ getHandle().stopDrowning(); -+ } -+ -+ @Override -+ public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); -+ } -+ -+ @Override -+ public boolean isArmsRaised() { -+ return getHandle().isAggressive(); -+ } -+ -+ @Override -+ public void setArmsRaised(final boolean raised) { -+ getHandle().setAggressive(raised); -+ } -+ -+ @Override -+ public void setShouldBurnInDay(boolean shouldBurnInDay) { -+ getHandle().setShouldBurnInDay(shouldBurnInDay); -+ } -+ // Paper end - - @Override - public boolean getAgeLock() { diff --git a/Spigot-Server-Patches/Add-more-line-of-sight-methods.patch b/Spigot-Server-Patches/Add-more-line-of-sight-methods.patch deleted file mode 100644 index a4a2c44f60..0000000000 --- a/Spigot-Server-Patches/Add-more-line-of-sight-methods.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> -Date: Sat, 29 May 2021 14:33:25 -0500 -Subject: [PATCH] Add more line of sight methods - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - Vec3D vec3d = new Vec3D(this.locX(), this.getHeadY(), this.locZ()); - Vec3D vec3d1 = new Vec3D(entity.locX(), entity.getHeadY(), entity.locZ()); - -+ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists - return this.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - public io.papermc.paper.world.MoonPhase getMoonPhase() { - return io.papermc.paper.world.MoonPhase.getPhase(getFullTime() / 24000L); - } -+ -+ @Override -+ public boolean lineOfSightExists(Location from, Location to) { -+ Validate.notNull(from, "from parameter in lineOfSightExists cannot be null"); -+ Validate.notNull(to, "to parameter in lineOfSightExists cannot be null"); -+ if (from.getWorld() != to.getWorld()) return false; -+ Vec3D vec3d = new Vec3D(from.getX(), from.getY(), from.getZ()); -+ Vec3D vec3d1 = new Vec3D(to.getX(), to.getY(), to.getZ()); -+ -+ return this.getHandle().rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, null)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; -+ } - // Paper end - - private static final Random rand = new Random(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().hasLineOfSight(((CraftEntity) other).getHandle()); - } - -+ // Paper start -+ @Override -+ public boolean hasLineOfSight(Location loc) { -+ if (this.getHandle().world != ((CraftWorld) loc.getWorld()).getHandle()) return false; -+ Vec3D vec3d = new Vec3D(this.getHandle().locX(), this.getHandle().getHeadY(), this.getHandle().locZ()); -+ Vec3D vec3d1 = new Vec3D(loc.getX(), loc.getY(), loc.getZ()); -+ -+ return this.getHandle().world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.COLLIDER, RayTrace.FluidCollisionOption.NONE, this.getHandle())).getType() == MovingObjectPosition.EnumMovingObjectType.MISS; -+ } -+ // Paper end -+ - @Override - public boolean getRemoveWhenFarAway() { - return getHandle() instanceof EntityInsentient && !((EntityInsentient) getHandle()).persistent; diff --git a/Spigot-Server-Patches/Add-option-for-console-having-all-permissions.patch b/Spigot-Server-Patches/Add-option-for-console-having-all-permissions.patch deleted file mode 100644 index 50b1dad655..0000000000 --- a/Spigot-Server-Patches/Add-option-for-console-having-all-permissions.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:12:15 +0200 -Subject: [PATCH] Add option for console having all permissions - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - - } - -+ public static boolean consoleHasAllPermissions = false; -+ private static void consoleHasAllPermissions() { -+ consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); -+ } -+ - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - } - } - -- protected void releaseShoulderEntities() { -+ public void releaseShoulderEntities() { // Paper - protected -> public - if (this.e + 20L < this.world.getTime()) { - // CraftBukkit start - if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -0,0 +0,0 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { - this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); - } -+ -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftRemoteConsoleCommandSender.java -@@ -0,0 +0,0 @@ public class CraftRemoteConsoleCommandSender extends ServerCommandSender impleme - public void setOp(boolean value) { - throw new UnsupportedOperationException("Cannot change operator status of remote controller."); - } -+ -+ // Paper start -+ @Override -+ public boolean hasPermission(String name) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(name); -+ } -+ -+ @Override -+ public boolean hasPermission(org.bukkit.permissions.Permission perm) { -+ return com.destroystokyo.paper.PaperConfig.consoleHasAllPermissions || super.hasPermission(perm); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/Spigot-Server-Patches/Add-option-to-allow-iron-golems-to-spawn-in-air.patch deleted file mode 100644 index 68e6e34cd7..0000000000 --- a/Spigot-Server-Patches/Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 13 Apr 2019 16:50:58 -0500 -Subject: [PATCH] Add option to allow iron golems to spawn in air - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } - -+ public boolean ironGolemsCanSpawnInAir = false; -+ private void ironGolemsCanSpawnInAir() { -+ ironGolemsCanSpawnInAir = getBoolean("iron-golems-can-spawn-in-air", ironGolemsCanSpawnInAir); -+ } -+ - public boolean armorStandEntityLookups = true; - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityIronGolem.java -@@ -0,0 +0,0 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable { - BlockPosition blockposition1 = blockposition.down(); - IBlockData iblockdata = iworldreader.getType(blockposition1); - -- if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this)) { -+ if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this) && !world.paperConfig.ironGolemsCanSpawnInAir) { // Paper - return false; - } else { - for (int i = 1; i < 3; ++i) { diff --git a/Spigot-Server-Patches/Add-option-to-disable-pillager-patrols.patch b/Spigot-Server-Patches/Add-option-to-disable-pillager-patrols.patch deleted file mode 100644 index 7eefb50579..0000000000 --- a/Spigot-Server-Patches/Add-option-to-disable-pillager-patrols.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:46:15 -0500 -Subject: [PATCH] Add option to disable pillager patrols - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void generatorSettings() { - generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); - } -+ -+ public boolean disablePillagerPatrols = false; -+ private void pillagerSettings() { -+ disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -@@ -0,0 +0,0 @@ public class MobSpawnerPatrol implements MobSpawner { - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -+ if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper - if (!flag) { - return 0; - } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { diff --git a/Spigot-Server-Patches/Add-option-to-fix-items-merging-through-walls.patch b/Spigot-Server-Patches/Add-option-to-fix-items-merging-through-walls.patch deleted file mode 100644 index 5886e3653f..0000000000 --- a/Spigot-Server-Patches/Add-option-to-fix-items-merging-through-walls.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: GioSDA -Date: Wed, 10 Mar 2021 10:06:45 -0800 -Subject: [PATCH] Add option to fix items merging through walls - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void mapItemFrameCursorLimit() { - mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); - } -+ -+ public boolean fixItemsMergingThroughWalls; -+ private void fixItemsMergingThroughWalls() { -+ fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - EntityItem entityitem = (EntityItem) iterator.next(); - - if (entityitem.z()) { -+ // Paper Start - Fix items merging through walls -+ if (this.world.paperConfig.fixItemsMergingThroughWalls) { -+ net.minecraft.world.level.RayTrace rayTrace = new net.minecraft.world.level.RayTrace(this.getPositionVector(), entityitem.getPositionVector(), -+ net.minecraft.world.level.RayTrace.BlockCollisionOption.COLLIDER, net.minecraft.world.level.RayTrace.FluidCollisionOption.NONE, this); -+ net.minecraft.world.phys.MovingObjectPositionBlock rayTraceResult = world.rayTrace(rayTrace); -+ if (rayTraceResult.getType() == net.minecraft.world.phys.MovingObjectPosition.EnumMovingObjectType.BLOCK) continue; -+ } -+ // Paper End - this.a(entityitem); - if (this.dead) { - break; diff --git a/Spigot-Server-Patches/Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/Spigot-Server-Patches/Add-option-to-make-parrots-stay-on-shoulders-despite.patch deleted file mode 100644 index bdf6f0c58e..0000000000 --- a/Spigot-Server-Patches/Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 16 May 2017 21:29:08 -0500 -Subject: [PATCH] Add option to make parrots stay on shoulders despite movement - -Makes parrots not fall off whenever the player changes height, or touches water, or gets hit by a passing leaf. -Instead, switches the behavior so that players have to sneak to make the birds leave. - -I suspect Mojang may switch to this behavior before full release. - -To be converted into a Paper-API event at some point in the future? - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); - log( "Max Entity Collisions: " + maxCollisionsPerEntity ); - } -+ -+ public boolean parrotsHangOnBetter; -+ private void parrotsHangOnBetter() { -+ parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); -+ log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - switch (packetplayinentityaction.c()) { - case PRESS_SHIFT_KEY: - this.player.setSneaking(true); -+ -+ // Paper start - Hang on! -+ if (this.player.world.paperConfig.parrotsHangOnBetter) { -+ this.player.releaseShoulderEntities(); -+ } -+ // Paper end -+ - break; - case RELEASE_SHIFT_KEY: - this.player.setSneaking(false); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - this.j(this.getShoulderEntityLeft()); - this.j(this.getShoulderEntityRight()); - if (!this.world.isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.isFlying || this.isSleeping()) { -- this.releaseShoulderEntities(); -+ if (!this.world.paperConfig.parrotsHangOnBetter) this.releaseShoulderEntities(); // Paper - Hang on! - } - - } diff --git a/Spigot-Server-Patches/Add-option-to-nerf-pigmen-from-nether-portals.patch b/Spigot-Server-Patches/Add-option-to-nerf-pigmen-from-nether-portals.patch deleted file mode 100644 index 26a44dc336..0000000000 --- a/Spigot-Server-Patches/Add-option-to-nerf-pigmen-from-nether-portals.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 7 Feb 2020 14:36:56 -0600 -Subject: [PATCH] Add option to nerf pigmen from nether portals - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); - log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); - } -+ -+ public boolean nerfNetherPortalPigmen = false; -+ private void nerfNetherPortalPigmen() { -+ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public long activatedTick = Integer.MIN_VALUE; - public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one -+ public boolean fromNetherPortal; // Paper - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (spawnedViaMobSpawner) { - nbttagcompound.setBoolean("Paper.FromMobSpawner", true); - } -+ if (fromNetherPortal) { -+ nbttagcompound.setBoolean("Paper.FromNetherPortal", true); -+ } - // Paper end - return nbttagcompound; - } catch (Throwable throwable) { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ fromNetherPortal = nbttagcompound.getBoolean("Paper.FromNetherPortal"); - if (nbttagcompound.hasKey("Paper.SpawnReason")) { - String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); - try { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPortal.java b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPortal.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.player.EntityHuman; -@@ -0,0 +0,0 @@ public class BlockPortal extends Block { - - if (entity != null) { - entity.resetPortalCooldown(); -+ entity.fromNetherPortal = true; // Paper -+ if (worldserver.paperConfig.nerfNetherPortalPigmen) ((EntityInsentient) entity).aware = false; // Paper - } - } - } diff --git a/Spigot-Server-Patches/Add-option-to-prevent-players-from-moving-into-unloa.patch b/Spigot-Server-Patches/Add-option-to-prevent-players-from-moving-into-unloa.patch deleted file mode 100644 index 6e0381d908..0000000000 --- a/Spigot-Server-Patches/Add-option-to-prevent-players-from-moving-into-unloa.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Mon, 22 Oct 2018 17:34:10 +0200 -Subject: [PATCH] Add option to prevent players from moving into unloaded - chunks #1551 - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); - log("Water over lava flow speed: " + waterOverLavaFlowSpeed); - } -+ -+ public boolean preventMovingIntoUnloadedChunks = false; -+ private void preventMovingIntoUnloadedChunks() { -+ preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - speed *= 2f; // TODO: Get the speed of the vehicle instead of the player - -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packetplayinvehiclemove.getX()) >> 4, (int) Math.floor(packetplayinvehiclemove.getZ()) >> 4) == null) { -+ this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); -+ return; -+ } -+ // Paper end -+ - if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isExemptPlayer()) { - // CraftBukkit end - PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), d6, d7, d8); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d1 = this.player.locY(); - double d2 = this.player.locZ(); - double d3 = this.player.locY(); -- double d4 = packetplayinflying.a(this.player.locX()); -+ double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER - double d5 = packetplayinflying.b(this.player.locY()); -- double d6 = packetplayinflying.c(this.player.locZ()); -+ double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER - float f = packetplayinflying.a(this.player.yaw); - float f1 = packetplayinflying.b(this.player.pitch); - double d7 = d4 - this.l; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } else { - speed = player.abilities.walkSpeed * 10f; - } -+ // Paper start - Prevent moving into unloaded chunks -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); -+ return; -+ } -+ // Paper end - - if (!this.player.H() && (!this.player.getWorldServer().getGameRules().getBoolean(GameRules.DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isGliding())) { - float f2 = this.player.isGliding() ? 300.0F : 100.0F; diff --git a/Spigot-Server-Patches/Add-permission-for-command-blocks.patch b/Spigot-Server-Patches/Add-permission-for-command-blocks.patch deleted file mode 100644 index 44f53b9d1c..0000000000 --- a/Spigot-Server-Patches/Add-permission-for-command-blocks.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 16 May 2020 10:05:30 +0200 -Subject: [PATCH] Add permission for command blocks - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - TileEntity tileentity = this.world.getTileEntity(blockposition); - Block block = iblockdata.getBlock(); - -- if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp()) { -+ if ((block instanceof BlockCommand || block instanceof BlockStructure || block instanceof BlockJigsaw) && !this.player.isCreativeAndOp() && !(block instanceof BlockCommand && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - this.world.notify(blockposition, iblockdata, iblockdata, 3); - return false; - } else if (this.player.a((World) this.world, blockposition, this.gamemode)) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandblock, this, this.player.getWorldServer()); - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); -- } else if (!this.player.isCreativeAndOp()) { -+ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); - } else { - CommandBlockListenerAbstract commandblocklistenerabstract = null; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinsetcommandminecart, this, this.player.getWorldServer()); - if (!this.minecraftServer.getEnableCommandBlock()) { - this.player.sendMessage(new ChatMessage("advMode.notEnabled"), SystemUtils.b); -- } else if (!this.player.isCreativeAndOp()) { -+ } else if (!this.player.isCreativeAndOp() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - this.player.sendMessage(new ChatMessage("advMode.notAllowed"), SystemUtils.b); - } else { - CommandBlockListenerAbstract commandblocklistenerabstract = packetplayinsetcommandminecart.a(this.player.world); -diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -@@ -0,0 +0,0 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { - } - - public EnumInteractionResult a(EntityHuman entityhuman) { -- if (!entityhuman.isCreativeAndOp()) { -+ if (!entityhuman.isCreativeAndOp() && !entityhuman.isCreative() && !entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission - return EnumInteractionResult.PASS; - } else { - if (entityhuman.getWorld().isClientSide) { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCommand.java b/src/main/java/net/minecraft/world/level/block/BlockCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCommand.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCommand.java -@@ -0,0 +0,0 @@ public class BlockCommand extends BlockTileEntity { - public EnumInteractionResult interact(IBlockData iblockdata, World world, BlockPosition blockposition, EntityHuman entityhuman, EnumHand enumhand, MovingObjectPositionBlock movingobjectpositionblock) { - TileEntity tileentity = world.getTileEntity(blockposition); - -- if (tileentity instanceof TileEntityCommand && entityhuman.isCreativeAndOp()) { -+ if (tileentity instanceof TileEntityCommand && (entityhuman.isCreativeAndOp() || (entityhuman.isCreative() && entityhuman.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission - entityhuman.a((TileEntityCommand) tileentity); - return EnumInteractionResult.a(world.isClientSide); - } else { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CraftDefaultPermissions.java -@@ -0,0 +0,0 @@ public final class CraftDefaultPermissions { - DefaultPermissions.registerPermission(ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); - DefaultPermissions.registerPermission(ROOT + ".debugstick.always", "Gives the user the ability to use the debug stick in all game modes", org.bukkit.permissions.PermissionDefault.FALSE, parent); -+ DefaultPermissions.registerPermission(ROOT + ".commandblock", "Gives the user the ability to use command blocks.", org.bukkit.permissions.PermissionDefault.OP, parent); // Paper - // Spigot end - parent.recalculatePermissibles(); - } diff --git a/Spigot-Server-Patches/Add-phantom-creative-and-insomniac-controls.patch b/Spigot-Server-Patches/Add-phantom-creative-and-insomniac-controls.patch deleted file mode 100644 index 5dd8f81044..0000000000 --- a/Spigot-Server-Patches/Add-phantom-creative-and-insomniac-controls.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 25 Apr 2020 15:13:41 -0500 -Subject: [PATCH] Add phantom creative and insomniac controls - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void lightQueueSize() { - lightQueueSize = getInt("light-queue-size", lightQueueSize); - } -+ -+ public boolean phantomIgnoreCreative = true; -+ public boolean phantomOnlyAttackInsomniacs = true; -+ private void phantomSettings() { -+ phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); -+ phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -0,0 +0,0 @@ package net.minecraft.world.entity; - import com.google.common.base.Predicates; - import java.util.function.Predicate; - import javax.annotation.Nullable; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.stats.StatisticList; -+import net.minecraft.util.MathHelper; - import net.minecraft.world.EnumDifficulty; - import net.minecraft.world.IInventory; - import net.minecraft.world.entity.player.EntityHuman; -@@ -0,0 +0,0 @@ public final class IEntitySelector { - public static final Predicate g = (entity) -> { - return !entity.isSpectator(); - }; -+ public static Predicate isInsomniac = (player) -> MathHelper.clamp(((EntityPlayer) player).getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper - - // Paper start - public static final Predicate affectsSpawning = (entity) -> { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPhantom.java -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - EntityHuman entityhuman = (EntityHuman) iterator.next(); - - if (EntityPhantom.this.a((EntityLiving) entityhuman, PathfinderTargetCondition.a)) { -+ if (!world.paperConfig.phantomOnlyAttackInsomniacs || IEntitySelector.isInsomniac.test(entityhuman)) // Paper - EntityPhantom.this.setGoalTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason - return true; - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPhantom.java -@@ -0,0 +0,0 @@ public class MobSpawnerPhantom implements MobSpawner { - while (iterator.hasNext()) { - EntityHuman entityhuman = (EntityHuman) iterator.next(); - -- if (!entityhuman.isSpectator()) { -+ if (!entityhuman.isSpectator() && (!worldserver.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper - BlockPosition blockposition = entityhuman.getChunkCoordinates(); - - if (!worldserver.getDimensionManager().hasSkyLight() || blockposition.getY() >= worldserver.getSeaLevel() && worldserver.e(blockposition)) { diff --git a/Spigot-Server-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch b/Spigot-Server-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch deleted file mode 100644 index 3c35084a97..0000000000 --- a/Spigot-Server-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 19:36:22 +0200 -Subject: [PATCH] Add playPickupItemAnimation to LivingEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - ((EntityInsentient) getHandle()).getControllerJump().jump(); - } - } -+ -+ @Override -+ public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { -+ getHandle().receive(((CraftItem) item).getHandle(), quantity); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Spigot-Server-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch deleted file mode 100644 index db20b2fb7b..0000000000 --- a/Spigot-Server-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Connor Linfoot -Date: Wed, 12 May 2021 08:09:19 +0100 -Subject: [PATCH] Add raw address to AsyncPlayerPreLoginEvent - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - // Paper end - String playerName = i.getName(); - java.net.InetAddress address = ((java.net.InetSocketAddress) networkManager.getSocketAddress()).getAddress(); -+ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) networkManager.getRawAddress()).getAddress(); // Paper - java.util.UUID uniqueId = i.getId(); - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - - // Paper start - PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); -- AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); -+ AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); - profile.complete(true); diff --git a/Spigot-Server-Patches/Add-ray-tracing-methods-to-LivingEntity.patch b/Spigot-Server-Patches/Add-ray-tracing-methods-to-LivingEntity.patch deleted file mode 100644 index 63503b9a4f..0000000000 --- a/Spigot-Server-Patches/Add-ray-tracing-methods-to-LivingEntity.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 3 Sep 2018 18:20:03 -0500 -Subject: [PATCH] Add ray tracing methods to LivingEntity - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); - } - // Paper start -+ public MovingObjectPosition getRayTrace(int maxDistance) { -+ return getRayTrace(maxDistance, RayTrace.FluidCollisionOption.NONE); -+ } -+ -+ public MovingObjectPosition getRayTrace(int maxDistance, RayTrace.FluidCollisionOption fluidCollisionOption) { -+ if (maxDistance < 1 || maxDistance > 120) { -+ throw new IllegalArgumentException("maxDistance must be between 1-120"); -+ } -+ -+ Vec3D start = new Vec3D(locX(), locY() + getHeadHeight(), locZ()); -+ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); -+ Vec3D end = new Vec3D(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); -+ RayTrace raytrace = new RayTrace(start, end, RayTrace.BlockCollisionOption.OUTLINE, fluidCollisionOption, this); -+ -+ return world.rayTrace(raytrace); -+ } -+ - public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; - - public int getShieldBlockingDelay() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.block.TargetBlockInfo; - import com.google.common.base.Preconditions; - import com.google.common.collect.Sets; - import java.util.ArrayList; -@@ -0,0 +0,0 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.damagesource.DamageSource; -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.entity.projectile.EntityThrownTrident; - import net.minecraft.world.entity.projectile.EntityTippedArrow; - import net.minecraft.world.entity.projectile.EntityWitherSkull; -+import net.minecraft.world.phys.MovingObjectPosition; -+import net.minecraft.world.phys.MovingObjectPositionBlock; - import org.apache.commons.lang.Validate; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; -@@ -0,0 +0,0 @@ import org.bukkit.attribute.AttributeInstance; - import org.bukkit.block.Block; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryKey; - import org.bukkit.craftbukkit.entity.memory.CraftMemoryMapper; - import org.bukkit.craftbukkit.inventory.CraftEntityEquipment; -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return blocks.get(0); - } - -+ // Paper start -+ @Override -+ public Block getTargetBlock(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()); -+ } -+ -+ @Override -+ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection()); -+ } -+ -+ @Override -+ public TargetBlockInfo getTargetBlockInfo(int maxDistance, TargetBlockInfo.FluidMode fluidMode) { -+ MovingObjectPosition rayTrace = getHandle().getRayTrace(maxDistance, MCUtil.getNMSFluidCollisionOption(fluidMode)); -+ return !(rayTrace instanceof MovingObjectPositionBlock) ? null : -+ new TargetBlockInfo(CraftBlock.at(getHandle().world, ((MovingObjectPositionBlock)rayTrace).getBlockPosition()), -+ MCUtil.toBukkitBlockFace(((MovingObjectPositionBlock)rayTrace).getDirection())); -+ } -+ // Paper end -+ - @Override - public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { - return getLineOfSight(transparent, maxDistance, 2); diff --git a/Spigot-Server-Patches/Add-recipe-to-cook-events.patch b/Spigot-Server-Patches/Add-recipe-to-cook-events.patch deleted file mode 100644 index 18228f2224..0000000000 --- a/Spigot-Server-Patches/Add-recipe-to-cook-events.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> -Date: Wed, 6 Jan 2021 12:04:03 -0800 -Subject: [PATCH] Add recipe to cook events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -@@ -0,0 +0,0 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - - if (this.cookingTimes[i] >= this.cookingTotalTimes[i]) { - InventorySubcontainer inventorysubcontainer = new InventorySubcontainer(new ItemStack[]{itemstack}); -- ItemStack itemstack1 = (ItemStack) this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world).map((recipecampfire) -> { -+ // Paper start -+ Optional recipe = this.world.getCraftingManager().craft(Recipes.CAMPFIRE_COOKING, inventorysubcontainer, this.world); -+ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { -+ // Paper end - return recipecampfire.a(inventorysubcontainer); - }).orElse(itemstack); - BlockPosition blockposition = this.getPosition(); -@@ -0,0 +0,0 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result); -+ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(this.world, this.position), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(RecipeCampfire::toBukkitRecipe).orElse(null)); // Paper - this.world.getServer().getPluginManager().callEvent(blockCookEvent); - - if (blockCookEvent.isCancelled()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - -- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result); -+ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), source, result, (org.bukkit.inventory.CookingRecipe) irecipe.toBukkitRecipe()); // Paper - this.world.getServer().getPluginManager().callEvent(furnaceSmeltEvent); - - if (furnaceSmeltEvent.isCancelled()) { diff --git a/Spigot-Server-Patches/Add-sendOpLevel-API.patch b/Spigot-Server-Patches/Add-sendOpLevel-API.patch deleted file mode 100644 index fd9e335ef8..0000000000 --- a/Spigot-Server-Patches/Add-sendOpLevel-API.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Tue, 29 Dec 2020 15:03:03 +0100 -Subject: [PATCH] Add sendOpLevel API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - private void a(EntityPlayer entityplayer, int i) { -+ // Paper start - add recalculatePermissions parameter -+ this.sendPlayerOperatorStatus(entityplayer, i, true); -+ } -+ public void sendPlayerOperatorStatus(EntityPlayer entityplayer, int i, boolean recalculatePermissions) { -+ // Paper end - if (entityplayer.playerConnection != null) { - byte b0; - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, b0)); - } - -+ if (recalculatePermissions) { // Paper - entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit - this.server.getCommandDispatcher().a(entityplayer); -+ } // Paper - } - - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - ? (org.bukkit.entity.Firework) entity.getBukkitEntity() - : null; - } -+ -+ @Override -+ public void sendOpLevel(byte level) { -+ Preconditions.checkArgument(level >= 0 && level <= 4, "Level must be within [0, 4]"); -+ -+ this.getHandle().getMinecraftServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/Add-server-name-parameter.patch b/Spigot-Server-Patches/Add-server-name-parameter.patch deleted file mode 100644 index 26efaf6478..0000000000 --- a/Spigot-Server-Patches/Add-server-name-parameter.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Sat, 28 May 2016 16:54:03 +0200 -Subject: [PATCH] Add server-name parameter - - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - .defaultsTo(new File("paper.yml")) - .describedAs("Yml file"); - // Paper end -+ -+ // Paper start -+ acceptsAll(asList("server-name"), "Name of the server") -+ .withRequiredArg() -+ .ofType(String.class) -+ .defaultsTo("Unknown Server") -+ .describedAs("Name"); -+ // Paper end - } - }; - diff --git a/Spigot-Server-Patches/Add-setMaxPlayers-API.patch b/Spigot-Server-Patches/Add-setMaxPlayers-API.patch deleted file mode 100644 index 4feada0071..0000000000 --- a/Spigot-Server-Patches/Add-setMaxPlayers-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 22 Aug 2020 23:59:30 +0200 -Subject: [PATCH] Add #setMaxPlayers API - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - public final WorldNBTStorage playerFileData; - private boolean hasWhitelist; - private final IRegistryCustom.Dimension s; -- protected final int maxPlayers; -+ protected int maxPlayers; public final void setMaxPlayers(int maxPlayers) { this.maxPlayers = maxPlayers; } // Paper - remove final and add setter - private int viewDistance; - private EnumGamemode u; - private boolean v; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return playerList.getMaxPlayers(); - } - -+ // Paper start -+ @Override -+ public void setMaxPlayers(int maxPlayers) { -+ this.playerList.setMaxPlayers(maxPlayers); -+ } -+ // Paper end -+ - // NOTE: These are dependent on the corresponding call in MinecraftServer - // so if that changes this will need to as well - @Override diff --git a/Spigot-Server-Patches/Add-setPlayerProfile-API-for-Skulls.patch b/Spigot-Server-Patches/Add-setPlayerProfile-API-for-Skulls.patch deleted file mode 100644 index d38f2172eb..0000000000 --- a/Spigot-Server-Patches/Add-setPlayerProfile-API-for-Skulls.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 19 Jan 2018 00:36:25 -0500 -Subject: [PATCH] Add setPlayerProfile API for Skulls - -This allows you to create already filled textures on Skulls to avoid texture lookups -which commonly cause rate limit issues with Mojang API - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.block; - -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.base.Preconditions; - import com.mojang.authlib.GameProfile; - import net.minecraft.server.MinecraftServer; -@@ -0,0 +0,0 @@ import org.bukkit.block.data.BlockData; - import org.bukkit.block.data.Directional; - import org.bukkit.block.data.Rotatable; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import javax.annotation.Nullable; - - public class CraftSkull extends CraftBlockEntityState implements Skull { - -@@ -0,0 +0,0 @@ public class CraftSkull extends CraftBlockEntityState implement - } - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(PlayerProfile profile) { -+ Preconditions.checkNotNull(profile, "profile"); -+ this.profile = CraftPlayerProfile.asAuthlibCopy(profile); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public BlockFace getRotation() { - BlockData blockData = getBlockData(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.block.entity.TileEntitySkull; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.OfflinePlayer; -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.SkullMeta; - -+import javax.annotation.Nullable; - @DelegateDeserialization(SerializableMeta.class) - class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - -@@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - return hasOwner() ? profile.getName() : null; - } - -+ // Paper start -+ @Override -+ public void setPlayerProfile(@Nullable PlayerProfile profile) { -+ setProfile((profile == null) ? null : CraftPlayerProfile.asAuthlibCopy(profile)); -+ } -+ -+ @Nullable -+ @Override -+ public PlayerProfile getPlayerProfile() { -+ return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; -+ } -+ // Paper end -+ - @Override - public OfflinePlayer getOwningPlayer() { - if (hasOwner()) { -@@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } else { - // Paper start - Use Online Players Skull - GameProfile newProfile = null; -- net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); -+ net.minecraft.server.level.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); - if (player != null) newProfile = player.getProfile(); - if (newProfile == null) newProfile = new GameProfile(null, name); - setProfile(newProfile); diff --git a/Spigot-Server-Patches/Add-setting-for-proxy-online-mode-status.patch b/Spigot-Server-Patches/Add-setting-for-proxy-online-mode-status.patch deleted file mode 100644 index f7766069ab..0000000000 --- a/Spigot-Server-Patches/Add-setting-for-proxy-online-mode-status.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabriele C -Date: Fri, 5 Aug 2016 01:03:08 +0200 -Subject: [PATCH] Add setting for proxy online mode status - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; - import co.aikar.timings.Timings; - import co.aikar.timings.TimingsManager; -+import org.spigotmc.SpigotConfig; - - public class PaperConfig { - -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void saveEmptyScoreboardTeams() { - saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); - } -+ -+ public static boolean bungeeOnlineMode = true; -+ private static void bungeeOnlineMode() { -+ bungeeOnlineMode = getBoolean("settings.bungee-online-mode", true); -+ } -+ -+ public static boolean isProxyOnlineMode() { -+ return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); -+ } - } -diff --git a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -+++ b/src/main/java/net/minecraft/server/players/NameReferencingFileConverter.java -@@ -0,0 +0,0 @@ public class NameReferencingFileConverter { - return new String[i]; - }); - -- if (minecraftserver.getOnlineMode() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. -+ if (minecraftserver.getOnlineMode() -+ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting - minecraftserver.getGameProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, profilelookupcallback); - } else { - String[] astring1 = astring; -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -0,0 +0,0 @@ public class UserCache { - } - }; - -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL - gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -@@ -0,0 +0,0 @@ public class UserCache { - } - - private static boolean c() { -- return UserCache.b; -+ return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - - public synchronized void a(GameProfile gameprofile) { // Paper - synchronize -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - // Spigot Start - GameProfile profile = null; - // Only fetch an online UUID in online mode -- if ( getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) -+ if ( getOnlineMode() -+ || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting - { - profile = console.getUserCache().getProfile( name ); - } diff --git a/Spigot-Server-Patches/Add-some-Debug-to-Chunk-Entity-slices.patch b/Spigot-Server-Patches/Add-some-Debug-to-Chunk-Entity-slices.patch deleted file mode 100644 index 3b372d3805..0000000000 --- a/Spigot-Server-Patches/Add-some-Debug-to-Chunk-Entity-slices.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:44:23 -0400 -Subject: [PATCH] Add some Debug to Chunk Entity slices - -If we detect unexpected state, log and try to recover - -This should hopefully avoid duplicate entities ever being created -if the entity was to end up in 2 different chunk slices - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - } - }; -+ public List entitySlice = null; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ import net.minecraft.ReportedException; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - if (k >= this.entitySlices.length) { - k = this.entitySlices.length - 1; - } -+ // Paper - remove from any old list if its in one -+ List nextSlice = this.entitySlices[k]; // the next list to be added to -+ List currentSlice = entity.entitySlice; -+ if (nextSlice == currentSlice) { -+ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable()); -+ return; // ??? silly plugins -+ } -+ if (currentSlice != null && currentSlice.contains(entity)) { -+ // Still in an old chunk... -+ if (World.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable()); -+ Chunk chunk = entity.getCurrentChunk(); -+ if (chunk != null) { -+ chunk.removeEntity(entity); -+ } else { -+ removeEntity(entity); -+ } -+ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice -+ } -+ // Paper end - - if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ entity.entitySlice = this.entitySlices[k]; // Paper - this.markDirty(); // Paper - } - -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - // Paper start - if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (entitySlices[i] == entity.entitySlice) { -+ entity.entitySlice = null; -+ entity.inChunk = false; -+ } - if (!this.entitySlices[i].remove(entity)) { - return; - } diff --git a/Spigot-Server-Patches/Add-source-to-PlayerExpChangeEvent.patch b/Spigot-Server-Patches/Add-source-to-PlayerExpChangeEvent.patch deleted file mode 100644 index aef0fa1e84..0000000000 --- a/Spigot-Server-Patches/Add-source-to-PlayerExpChangeEvent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AlphaBlend -Date: Thu, 8 Sep 2016 08:48:33 -0700 -Subject: [PATCH] Add source to PlayerExpChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - } - - if (this.value > 0) { -- entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this.value).getAmount()); // CraftBukkit - this.value -> event.getAmount() -+ entityhuman.giveExp(CraftEventFactory.callPlayerExpChangeEvent(entityhuman, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object - } - - this.die(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; -+import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - Add orb -+ public static PlayerExpChangeEvent callPlayerExpChangeEvent(EntityHuman entity, EntityExperienceOrb entityOrb) { -+ Player player = (Player) entity.getBukkitEntity(); -+ ExperienceOrb source = (ExperienceOrb) entityOrb.getBukkitEntity(); -+ int expAmount = source.getExperience(); -+ PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, source, expAmount); -+ Bukkit.getPluginManager().callEvent(event); -+ return event; -+ } -+ // Paper end -+ - public static boolean handleBlockGrowEvent(World world, BlockPosition pos, IBlockData block) { - return handleBlockGrowEvent(world, pos, block, 3); - } diff --git a/Spigot-Server-Patches/Add-sun-related-API.patch b/Spigot-Server-Patches/Add-sun-related-API.patch deleted file mode 100644 index cc41e5cd6a..0000000000 --- a/Spigot-Server-Patches/Add-sun-related-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 Oct 2018 00:54:21 -0500 -Subject: [PATCH] Add sun related API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - - } - -+ public boolean isInDaylight() { return this.eG(); } // Paper - OBFHELPER - protected boolean eG() { - if (this.world.isDay() && !this.world.isClientSide) { - float f = this.aR(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - } - } - -+ // Paper start -+ @Override -+ public boolean isDayTime() { -+ return getHandle().isDay(); -+ } -+ // Paper end -+ - @Override - public long getGameTime() { - return world.worldData.getTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -0,0 +0,0 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { - public long getSeed() { - return getHandle().lootTableSeed; - } -+ -+ // Paper start -+ @Override -+ public boolean isInDaylight() { -+ return getHandle().isInDaylight(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-support-for-hex-color-codes-in-console.patch b/Spigot-Server-Patches/Add-support-for-hex-color-codes-in-console.patch deleted file mode 100644 index ca4d56563e..0000000000 --- a/Spigot-Server-Patches/Add-support-for-hex-color-codes-in-console.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Sat, 20 Feb 2021 13:09:59 -0500 -Subject: [PATCH] Add support for hex color codes in console - -Converts upstream's hex color code legacy format into actual hex color codes in the console. - -diff --git a/src/main/java/io/papermc/paper/console/HexFormattingConverter.java b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/HexFormattingConverter.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.console; -+ -+import net.minecrell.terminalconsole.TerminalConsoleAppender; -+import org.apache.logging.log4j.core.LogEvent; -+import org.apache.logging.log4j.core.config.Configuration; -+import org.apache.logging.log4j.core.config.plugins.Plugin; -+import org.apache.logging.log4j.core.layout.PatternLayout; -+import org.apache.logging.log4j.core.pattern.*; -+import org.apache.logging.log4j.util.PerformanceSensitive; -+import org.apache.logging.log4j.util.PropertiesUtil; -+ -+import java.util.List; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+import static net.minecrell.terminalconsole.MinecraftFormattingConverter.KEEP_FORMATTING_PROPERTY; -+ -+/** -+ * Modified version of -+ * TerminalConsoleAppender's MinecraftFormattingConverter to support hex color codes using the md_5 &x&r&r&g&g&b&b format. -+ */ -+@Plugin(name = "paperMinecraftFormatting", category = PatternConverter.CATEGORY) -+@ConverterKeys({ "paperMinecraftFormatting" }) -+@PerformanceSensitive("allocation") -+public final class HexFormattingConverter extends LogEventPatternConverter { -+ -+ private static final boolean KEEP_FORMATTING = PropertiesUtil.getProperties().getBooleanProperty(KEEP_FORMATTING_PROPERTY); -+ -+ private static final String ANSI_RESET = "\u001B[m"; -+ -+ private static final char COLOR_CHAR = '§'; -+ private static final String LOOKUP = "0123456789abcdefklmnor"; -+ -+ private static final String RGB_ANSI = "\u001B[38;2;%d;%d;%dm"; -+ private static final Pattern NAMED_PATTERN = Pattern.compile(COLOR_CHAR + "[0-9a-fk-orA-FK-OR]"); -+ private static final Pattern RGB_PATTERN = Pattern.compile(COLOR_CHAR + "x(" + COLOR_CHAR + "[0-9a-fA-F]){6}"); -+ -+ private static final String[] ansiCodes = new String[] { -+ "\u001B[0;30m", // Black §0 -+ "\u001B[0;34m", // Dark Blue §1 -+ "\u001B[0;32m", // Dark Green §2 -+ "\u001B[0;36m", // Dark Aqua §3 -+ "\u001B[0;31m", // Dark Red §4 -+ "\u001B[0;35m", // Dark Purple §5 -+ "\u001B[0;33m", // Gold §6 -+ "\u001B[0;37m", // Gray §7 -+ "\u001B[0;30;1m", // Dark Gray §8 -+ "\u001B[0;34;1m", // Blue §9 -+ "\u001B[0;32;1m", // Green §a -+ "\u001B[0;36;1m", // Aqua §b -+ "\u001B[0;31;1m", // Red §c -+ "\u001B[0;35;1m", // Light Purple §d -+ "\u001B[0;33;1m", // Yellow §e -+ "\u001B[0;37;1m", // White §f -+ "\u001B[5m", // Obfuscated §k -+ "\u001B[21m", // Bold §l -+ "\u001B[9m", // Strikethrough §m -+ "\u001B[4m", // Underline §n -+ "\u001B[3m", // Italic §o -+ ANSI_RESET, // Reset §r -+ }; -+ -+ private final boolean ansi; -+ private final List formatters; -+ -+ /** -+ * Construct the converter. -+ * -+ * @param formatters The pattern formatters to generate the text to manipulate -+ * @param strip If true, the converter will strip all formatting codes -+ */ -+ protected HexFormattingConverter(List formatters, boolean strip) { -+ super("paperMinecraftFormatting", null); -+ this.formatters = formatters; -+ this.ansi = !strip; -+ } -+ -+ @Override -+ public void format(LogEvent event, StringBuilder toAppendTo) { -+ int start = toAppendTo.length(); -+ //noinspection ForLoopReplaceableByForEach -+ for (int i = 0, size = formatters.size(); i < size; i++) { -+ formatters.get(i).format(event, toAppendTo); -+ } -+ -+ if (KEEP_FORMATTING || toAppendTo.length() == start) { -+ // Skip replacement if disabled or if the content is empty -+ return; -+ } -+ -+ boolean useAnsi = ansi && TerminalConsoleAppender.isAnsiSupported(); -+ String content = toAppendTo.substring(start); -+ content = useAnsi ? convertRGBColors(content) : stripRGBColors(content); -+ format(content, toAppendTo, start, useAnsi); -+ } -+ -+ private static String convertRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ String s = matcher.group().replace(String.valueOf(COLOR_CHAR), "").replace('x', '#'); -+ int hex = Integer.decode(s); -+ int red = (hex >> 16) & 0xFF; -+ int green = (hex >> 8) & 0xFF; -+ int blue = hex & 0xFF; -+ String replacement = String.format(RGB_ANSI, red, green, blue); -+ matcher.appendReplacement(buffer, replacement); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ private static String stripRGBColors(String input) { -+ Matcher matcher = RGB_PATTERN.matcher(input); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ matcher.appendReplacement(buffer, ""); -+ } -+ matcher.appendTail(buffer); -+ return buffer.toString(); -+ } -+ -+ static void format(String content, StringBuilder result, int start, boolean ansi) { -+ int next = content.indexOf(COLOR_CHAR); -+ int last = content.length() - 1; -+ if (next == -1 || next == last) { -+ result.setLength(start); -+ result.append(content); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ return; -+ } -+ -+ Matcher matcher = NAMED_PATTERN.matcher(content); -+ StringBuffer buffer = new StringBuffer(); -+ while (matcher.find()) { -+ int format = LOOKUP.indexOf(Character.toLowerCase(matcher.group().charAt(1))); -+ if (format != -1) { -+ matcher.appendReplacement(buffer, ansi ? ansiCodes[format] : ""); -+ } -+ } -+ matcher.appendTail(buffer); -+ -+ result.setLength(start); -+ result.append(buffer.toString()); -+ if (ansi) { -+ result.append(ANSI_RESET); -+ } -+ } -+ -+ /** -+ * Gets a new instance of the {@link HexFormattingConverter} with the -+ * specified options. -+ * -+ * @param config The current configuration -+ * @param options The pattern options -+ * @return The new instance -+ * -+ * @see HexFormattingConverter -+ */ -+ public static HexFormattingConverter newInstance(Configuration config, String[] options) { -+ if (options.length < 1 || options.length > 2) { -+ LOGGER.error("Incorrect number of options on paperMinecraftFormatting. Expected at least 1, max 2 received " + options.length); -+ return null; -+ } -+ if (options[0] == null) { -+ LOGGER.error("No pattern supplied on paperMinecraftFormatting"); -+ return null; -+ } -+ -+ PatternParser parser = PatternLayout.createPatternParser(config); -+ List formatters = parser.parse(options[0]); -+ boolean strip = options.length > 1 && "strip".equals(options[1]); -+ return new HexFormattingConverter(formatters, strip); -+ } -+ -+} -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -0,0 +0,0 @@ - - - -- -+ - - - -+ pattern="%highlightError{[%d{HH:mm:ss} %level]: %paperMinecraftFormatting{%msg}%n%xEx{full}}" /> - - - - - -- -+ - - - -+ pattern="[%d{HH:mm:ss}] [%t/%level]: %paperMinecraftFormatting{%msg}{strip}%n%xEx{full}" /> - - - diff --git a/Spigot-Server-Patches/Add-system-property-to-disable-book-size-limits.patch b/Spigot-Server-Patches/Add-system-property-to-disable-book-size-limits.patch deleted file mode 100644 index 9ace767d1f..0000000000 --- a/Spigot-Server-Patches/Add-system-property-to-disable-book-size-limits.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sat, 13 May 2017 20:11:21 -0500 -Subject: [PATCH] Add system property to disable book size limits - -If anyone comes in with a watchdog crash related to books after this patch -you will not only be publicly shamed but also made an example of. - -Disables the security limits on books entirely, allowing plugins AND players -to make books with as much data as they want. Do not use this without -limiting incoming data from packets in some other way. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - static final int MAX_PAGES = 100; - static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes - static final int MAX_TITLE_LENGTH = 32; -+ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override - - protected String title; - protected String author; -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - if (title == null) { - this.title = null; - return true; -- } else if (title.length() > MAX_TITLE_LENGTH) { -+ } else if (title.length() > MAX_TITLE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - return false; - } - -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - String validatePage(String page) { - if (page == null) { - page = ""; -- } else if (page.length() > MAX_PAGE_LENGTH) { -+ } else if (page.length() > MAX_PAGE_LENGTH && !OVERRIDE_CHECKS) { // Paper - Add override - page = page.substring(0, MAX_PAGE_LENGTH); - } - return page; -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - // asserted: page != null - if (this.pages == null) { - this.pages = new ArrayList(); -- } else if (this.pages.size() >= MAX_PAGES) { -+ } else if (this.pages.size() >= MAX_PAGES && !OVERRIDE_CHECKS) {// Paper - Add override - return; - } - this.pages.add(page); diff --git a/Spigot-Server-Patches/Add-tick-times-API-and-mspt-command.patch b/Spigot-Server-Patches/Add-tick-times-API-and-mspt-command.patch deleted file mode 100644 index 7be8315621..0000000000 --- a/Spigot-Server-Patches/Add-tick-times-API-and-mspt-command.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Apr 2020 22:23:14 -0500 -Subject: [PATCH] Add tick times API and /mspt command - - -diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+ -+import java.text.DecimalFormat; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collections; -+import java.util.List; -+ -+public class MSPTCommand extends Command { -+ private static final DecimalFormat DF = new DecimalFormat("########0.0"); -+ -+ public MSPTCommand(String name) { -+ super(name); -+ this.description = "View server tick times"; -+ this.usageMessage = "/mspt"; -+ this.setPermission("bukkit.command.mspt"); -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ return Collections.emptyList(); -+ } -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ List times = new ArrayList<>(); -+ times.addAll(eval(server.tickTimes5s.getTimes())); -+ times.addAll(eval(server.tickTimes10s.getTimes())); -+ times.addAll(eval(server.tickTimes60s.getTimes())); -+ -+ sender.sendMessage("§6Server tick times §e(§7avg§e/§7min§e/§7max§e)§6 from last 5s§7,§6 10s§7,§6 1m§e:"); -+ sender.sendMessage(String.format("§6◴ %s§7/%s§7/%s§e, %s§7/%s§7/%s§e, %s§7/%s§7/%s", times.toArray())); -+ return true; -+ } -+ -+ private static List eval(long[] times) { -+ long min = Integer.MAX_VALUE; -+ long max = 0L; -+ long total = 0L; -+ for (long value : times) { -+ if (value > 0L && value < min) min = value; -+ if (value > max) max = value; -+ total += value; -+ } -+ double avgD = ((double) total / (double) times.length) * 1.0E-6D; -+ double minD = ((double) min) * 1.0E-6D; -+ double maxD = ((double) max) * 1.0E-6D; -+ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD)); -+ } -+ -+ private static String getColor(double avg) { -+ return ChatColor.COLOR_CHAR + (avg >= 50 ? "c" : avg >= 40 ? "e" : "a") + DF.format(avg); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - - commands = new HashMap(); - commands.put("paper", new PaperCommand("paper")); -+ commands.put("mspt", new MSPTCommand("mspt")); - - version = getInt("config-version", 20); - set("config-version", 20); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Thu, 26 Nov 2020 11:47:24 +0000 -Subject: [PATCH] Add toggle for always placing the dragon egg - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - if (value != -1) entityPerChunkSaveLimits.put(type, value); - }); - } -+ -+ public boolean enderDragonsDeathAlwaysPlacesDragonEgg = false; -+ private void enderDragonsDeathAlwaysPlacesDragonEgg() { -+ enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -0,0 +0,0 @@ public class EnderDragonBattle { - this.bossBattle.setVisible(false); - this.generateExitPortal(true); - this.n(); -- if (!this.previouslyKilled) { -+ if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg - this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); - } - diff --git a/Spigot-Server-Patches/Add-velocity-warnings.patch b/Spigot-Server-Patches/Add-velocity-warnings.patch deleted file mode 100644 index 65df38ca0b..0000000000 --- a/Spigot-Server-Patches/Add-velocity-warnings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:48:12 -0600 -Subject: [PATCH] Add velocity warnings - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - public boolean ignoreVanillaPermissions = false; - private final List playerView; - public int reloadCount; -+ public static Exception excessiveVelEx; // Paper - Velocity warnings - - static { - ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public void setVelocity(Vector velocity) { - Preconditions.checkArgument(velocity != null, "velocity"); - velocity.checkFinite(); -+ // Paper start - Warn server owners when plugins try to set super high velocities -+ if (!(this instanceof org.bukkit.entity.Projectile) && isUnsafeVelocity(velocity)) { -+ CraftServer.excessiveVelEx = new Exception("Excessive velocity set detected: tried to set velocity of entity " + entity.getName() + " id #" + getEntityId() + " to (" + velocity.getX() + "," + velocity.getY() + "," + velocity.getZ() + ")."); -+ } -+ // Paper end -+ - entity.setMot(CraftVector.toNMS(velocity)); - entity.velocityChanged = true; - } - -+ // Paper start -+ /** -+ * Checks if the given velocity is not necessarily safe in all situations. -+ * This function returning true does not mean the velocity is dangerous or to be avoided, only that it may be -+ * a detriment to performance on the server. -+ * -+ * It is not to be used as a hard rule of any sort. -+ * Paper only uses it to warn server owners in watchdog crashes. -+ * -+ * @param vel incoming velocity to check -+ * @return if the velocity has the potential to be a performance detriment -+ */ -+ private static boolean isUnsafeVelocity(Vector vel) { -+ final double x = vel.getX(); -+ final double y = vel.getY(); -+ final double z = vel.getZ(); -+ -+ if (x > 4 || x < -4 || y > 4 || y < -4 || z > 4 || z < -4) { -+ return true; -+ } -+ -+ return false; -+ } -+ // Paper end -+ - @Override - public double getHeight() { - return getHandle().getHeight(); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); - log.log( Level.SEVERE, "near " + net.minecraft.world.level.World.lastPhysicsProblem ); - } -- // -+ // Paper start - Warn in watchdog if an excessive velocity was ever set -+ if ( org.bukkit.craftbukkit.CraftServer.excessiveVelEx != null ) -+ { -+ log.log( Level.SEVERE, "------------------------------" ); -+ log.log( Level.SEVERE, "During the run of the server, a plugin set an excessive velocity on an entity" ); -+ log.log( Level.SEVERE, "This may be the cause of the issue, or it may be entirely unrelated" ); -+ log.log( Level.SEVERE, org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getMessage()); -+ for ( StackTraceElement stack : org.bukkit.craftbukkit.CraftServer.excessiveVelEx.getStackTrace() ) -+ { -+ log.log( Level.SEVERE, "\t\t" + stack ); -+ } -+ } -+ // Paper end - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/Spigot-Server-Patches/Add-version-history-to-version-command.patch b/Spigot-Server-Patches/Add-version-history-to-version-command.patch deleted file mode 100644 index d732dae3c9..0000000000 --- a/Spigot-Server-Patches/Add-version-history-to-version-command.patch +++ /dev/null @@ -1,215 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Thu, 1 Mar 2018 19:37:52 -0600 -Subject: [PATCH] Add version history to version command - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -0,0 +0,0 @@ import com.google.common.base.Charsets; - import com.google.common.io.Resources; - import com.google.gson.*; - import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; - import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.format.TextDecoration; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -@@ -0,0 +0,0 @@ public class PaperVersionFetcher implements VersionFetcher { - @Override - public Component getVersionMessage(@Nonnull String serverVersion) { - String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -- return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ final Component history = getHistory(); -+ -+ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; - } - - private static @Nullable String getMinecraftVersion() { -@@ -0,0 +0,0 @@ public class PaperVersionFetcher implements VersionFetcher { - return -1; - } - } -+ -+ @Nullable -+ private Component getHistory() { -+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData(); -+ if (data == null) { -+ return null; -+ } -+ -+ final String oldVersion = data.getOldVersion(); -+ if (oldVersion == null) { -+ return null; -+ } -+ -+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/VersionHistoryManager.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.MoreObjects; -+import com.google.gson.Gson; -+import com.google.gson.JsonSyntaxException; -+import java.io.BufferedReader; -+import java.io.BufferedWriter; -+import java.io.IOException; -+import java.nio.charset.StandardCharsets; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.nio.file.Paths; -+import java.nio.file.StandardOpenOption; -+import java.util.Objects; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import org.bukkit.Bukkit; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+ -+public enum VersionHistoryManager { -+ INSTANCE; -+ -+ private final Gson gson = new Gson(); -+ -+ private final Logger logger = Bukkit.getLogger(); -+ -+ private VersionData currentData = null; -+ -+ VersionHistoryManager() { -+ final Path path = Paths.get("version_history.json"); -+ -+ if (Files.exists(path)) { -+ // Basic file santiy checks -+ if (!Files.isRegularFile(path)) { -+ if (Files.isDirectory(path)) { -+ logger.severe(path + " is a directory, cannot be used for version history"); -+ } else { -+ logger.severe(path + " is not a regular file, cannot be used for version history"); -+ } -+ // We can't continue -+ return; -+ } -+ -+ try (final BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { -+ currentData = gson.fromJson(reader, VersionData.class); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to read version history file '" + path + "'", e); -+ return; -+ } catch (final JsonSyntaxException e) { -+ logger.log(Level.SEVERE, "Invalid json syntax for file '" + path + "'", e); -+ return; -+ } -+ -+ final String version = Bukkit.getVersion(); -+ if (version == null) { -+ logger.severe("Failed to retrieve current version"); -+ return; -+ } -+ -+ if (!version.equals(currentData.getCurrentVersion())) { -+ // The version appears to have changed -+ currentData.setOldVersion(currentData.getCurrentVersion()); -+ currentData.setCurrentVersion(version); -+ writeFile(path); -+ } -+ } else { -+ // File doesn't exist, start fresh -+ currentData = new VersionData(); -+ // oldVersion is null -+ currentData.setCurrentVersion(Bukkit.getVersion()); -+ writeFile(path); -+ } -+ } -+ -+ private void writeFile(@Nonnull final Path path) { -+ try (final BufferedWriter writer = Files.newBufferedWriter( -+ path, -+ StandardCharsets.UTF_8, -+ StandardOpenOption.WRITE, -+ StandardOpenOption.CREATE, -+ StandardOpenOption.TRUNCATE_EXISTING -+ )) { -+ gson.toJson(currentData, writer); -+ } catch (final IOException e) { -+ logger.log(Level.SEVERE, "Failed to write to version history file", e); -+ } -+ } -+ -+ @Nullable -+ public VersionData getVersionData() { -+ return currentData; -+ } -+ -+ public static class VersionData { -+ private String oldVersion; -+ -+ private String currentVersion; -+ -+ @Nullable -+ public String getOldVersion() { -+ return oldVersion; -+ } -+ -+ public void setOldVersion(@Nullable String oldVersion) { -+ this.oldVersion = oldVersion; -+ } -+ -+ @Nullable -+ public String getCurrentVersion() { -+ return currentVersion; -+ } -+ -+ public void setCurrentVersion(@Nullable String currentVersion) { -+ this.currentVersion = currentVersion; -+ } -+ -+ @Override -+ public String toString() { -+ return MoreObjects.toStringHelper(this) -+ .add("oldVersion", oldVersion) -+ .add("currentVersion", currentVersion) -+ .toString(); -+ } -+ -+ @Override -+ public boolean equals(@Nullable Object o) { -+ if (this == o) { -+ return true; -+ } -+ if (o == null || getClass() != o.getClass()) { -+ return false; -+ } -+ final VersionData versionData = (VersionData) o; -+ return Objects.equals(oldVersion, versionData.oldVersion) && -+ Objects.equals(currentVersion, versionData.currentVersion); -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hash(oldVersion, currentVersion); -+ } -+ } -+} -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 IMinecraftServer - return false; - } - com.destroystokyo.paper.PaperConfig.registerCommands(); -+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - // Paper end - - this.setPVP(dedicatedserverproperties.pvp); diff --git a/Spigot-Server-Patches/Add-villager-reputation-API.patch b/Spigot-Server-Patches/Add-villager-reputation-API.patch deleted file mode 100644 index faf1f63d51..0000000000 --- a/Spigot-Server-Patches/Add-villager-reputation-API.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 22 Apr 2020 23:29:20 +0200 -Subject: [PATCH] Add villager reputation API - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/villager/ReputationConstructor.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity.villager; -+// Must have own package due to package-level constructor. -+ -+public final class ReputationConstructor { -+ // Abuse the package-level constructor. -+ public static Reputation construct(int[] values) { -+ return new Reputation(values); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -0,0 +0,0 @@ import net.minecraft.core.MinecraftSerializableUUID; - - public class Reputation { - -- private final Map a = Maps.newHashMap(); -+ private final Map a = Maps.newHashMap(); public Map getReputations() { return this.a; } // Paper - add getter for reputations - - public Reputation() {} - -@@ -0,0 +0,0 @@ public class Reputation { - return k > reputationtype.h ? Math.max(reputationtype.h, i) : k; - } - -- static class a { -+ public static class a { // Paper - make public - - private final Object2IntMap a; - -- private a() { -+ public a() { // Paper - make public - update CraftVillager setReputation on change - this.a = new Object2IntOpenHashMap(); - } - -@@ -0,0 +0,0 @@ public class Reputation { - public void b(ReputationType reputationtype) { - this.a.removeInt(reputationtype); - } -+ -+ // Paper start - Add villager reputation API -+ private static final com.destroystokyo.paper.entity.villager.ReputationType[] REPUTATION_TYPES = com.destroystokyo.paper.entity.villager.ReputationType.values(); -+ public com.destroystokyo.paper.entity.villager.Reputation getPaperReputation() { -+ int[] reputation = new int[REPUTATION_TYPES.length]; -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MAJOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_NEGATIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = a.getOrDefault(ReputationType.MINOR_POSITIVE, 0); -+ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = a.getOrDefault(ReputationType.TRADING, 0); -+ return com.destroystokyo.paper.entity.villager.ReputationConstructor.construct(reputation); -+ } -+ -+ public void assignFromPaperReputation(com.destroystokyo.paper.entity.villager.Reputation rep) { -+ int val; -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.a.put(ReputationType.MAJOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.a.put(ReputationType.MAJOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.a.put(ReputationType.MINOR_NEGATIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.a.put(ReputationType.MINOR_POSITIVE, val); -+ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.a.put(ReputationType.TRADING, val); -+ } -+ // Paper end - } - - static class b { -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - this.bD = 0; - } - -+ public Reputation getReputation() { return this.fj(); } // Paper - OBFHELPER - public Reputation fj() { - return this.by; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; - import org.bukkit.entity.Villager.Type; - -+// Paper start -+import com.destroystokyo.paper.entity.villager.Reputation; -+import com.google.common.collect.Maps; -+import java.util.Map; -+import java.util.UUID; -+// Paper end -+ - public class CraftVillager extends CraftAbstractVillager implements Villager { - - public CraftVillager(CraftServer server, EntityVillager entity) { -@@ -0,0 +0,0 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - public static VillagerProfession bukkitToNmsProfession(Profession bukkit) { - return IRegistry.VILLAGER_PROFESSION.get(CraftNamespacedKey.toMinecraft(bukkit.getKey())); - } -+ -+ // Paper start - Add villager reputation API -+ @Override -+ public Reputation getReputation(UUID uniqueId) { -+ net.minecraft.world.entity.ai.gossip.Reputation.a rep = getHandle().getReputation().getReputations().get(uniqueId); -+ if (rep == null) { -+ return new Reputation(Maps.newHashMap()); -+ } -+ -+ return rep.getPaperReputation(); -+ } -+ -+ @Override -+ public Map getReputations() { -+ return getHandle().getReputation().getReputations().entrySet() -+ .stream() -+ .collect(java.util.stream.Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getPaperReputation())); -+ } -+ -+ @Override -+ public void setReputation(UUID uniqueId, Reputation reputation) { -+ net.minecraft.world.entity.ai.gossip.Reputation.a nmsReputation = -+ getHandle().getReputation().getReputations().computeIfAbsent( -+ uniqueId, -+ key -> new net.minecraft.world.entity.ai.gossip.Reputation.a() -+ ); -+ nmsReputation.assignFromPaperReputation(reputation); -+ } -+ -+ @Override -+ public void setReputations(Map reputations) { -+ for (Map.Entry entry : reputations.entrySet()) { -+ setReputation(entry.getKey(), entry.getValue()); -+ } -+ } -+ -+ @Override -+ public void clearReputations() { -+ getHandle().getReputation().getReputations().clear(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Add-warning-for-servers-not-running-on-Java-16.patch b/Spigot-Server-Patches/Add-warning-for-servers-not-running-on-Java-16.patch deleted file mode 100644 index 0aff3e26c4..0000000000 --- a/Spigot-Server-Patches/Add-warning-for-servers-not-running-on-Java-16.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Kyle Wood -Date: Wed, 2 Dec 2020 21:58:45 -0800 -Subject: [PATCH] Add warning for servers not running on Java 16 - - -diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.util; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class PaperJvmChecker { -+ -+ private static int getJvmVersion() { -+ String javaVersion = System.getProperty("java.version"); -+ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); -+ if (!matcher.find()) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion); -+ return -1; -+ } -+ -+ final String version = matcher.group(1); -+ try { -+ return Integer.parseInt(version); -+ } catch (final NumberFormatException e) { -+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e); -+ return -1; -+ } -+ } -+ -+ public static void checkJvm() { -+ if (getJvmVersion() < 16) { -+ final Logger logger = LogManager.getLogger(); -+ logger.warn("************************************************************"); -+ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA."); -+ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF"); -+ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED."); -+ logger.warn("*"); -+ logger.warn("* Please update the version of Java you use to run Paper"); -+ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is"); -+ logger.warn("* released support for versions of Java before 16 will"); -+ logger.warn("* be dropped."); -+ logger.warn("*"); -+ logger.warn("* Current Java version: {}", System.getProperty("java.version")); -+ logger.warn("*"); -+ logger.warn("* Check this forum post for more information: "); -+ logger.warn("* https://papermc.io/java16"); -+ logger.warn("************************************************************"); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import org.bukkit.event.server.ServerLoadEvent; - - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot -+import io.papermc.paper.util.PaperJvmChecker; // Paper - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Mon, 4 Jan 2021 22:40:34 -0800 -Subject: [PATCH] Add worldborder events - - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.shapes.OperatorBoolean; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapes; -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent; // Paper -+import io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent; // Paper - - public class WorldBorder { - -@@ -0,0 +0,0 @@ public class WorldBorder { - } - - public void setCenter(double d0, double d1) { -- this.g = d0; -- this.h = d1; -+ // Paper start -+ WorldBorderCenterChangeEvent event = new WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), d0, 0, d1)); -+ if (!event.callEvent()) return; -+ this.g = event.getNewCenter().getX(); -+ this.h = event.getNewCenter().getZ(); -+ // Paper end - this.j.k(); - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0, d1); -+ iworldborderlistener.a(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper - } - - } -@@ -0,0 +0,0 @@ public class WorldBorder { - } - - public void setSize(double d0) { -- this.j = new WorldBorder.d(d0); -+ // Paper start -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), d0, 0); -+ if (!event.callEvent()) return; -+ if (event.getType() == WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition -+ transitionSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); -+ return; -+ } -+ this.j = new WorldBorder.d(event.getNewSize()); -+ // Paper end - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0); -+ iworldborderlistener.a(this, event.getNewSize()); // Paper - } - - } - - public void transitionSizeBetween(double d0, double d1, long i) { -- this.j = (WorldBorder.a) (d0 == d1 ? new WorldBorder.d(d1) : new WorldBorder.b(d0, d1, i)); -+ // Paper start -+ WorldBorderBoundsChangeEvent.Type type; -+ if (d0 == d1) { // new size = old size -+ type = WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. -+ } else { -+ type = WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; -+ } -+ WorldBorderBoundsChangeEvent event = new WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, d0, d1, i); -+ if (!event.callEvent()) return; -+ this.j = (WorldBorder.a) (d0 == event.getNewSize() ? new WorldBorder.d(event.getNewSize()) : new WorldBorder.b(d0, event.getNewSize(), event.getDuration())); -+ // Paper end - Iterator iterator = this.l().iterator(); - - while (iterator.hasNext()) { - IWorldBorderListener iworldborderlistener = (IWorldBorderListener) iterator.next(); - -- iworldborderlistener.a(this, d0, d1, i); -+ iworldborderlistener.a(this, d0, event.getNewSize(), event.getDuration()); // Paper - } - - } -@@ -0,0 +0,0 @@ public class WorldBorder { - - class b implements WorldBorder.a { - -- private final double b; -- private final double c; -+ private final double b; public final double getOldSize() { return this.b; } // Paper - OBFHELPER -+ private final double c; public final double getNewSize() { return this.c; } // Paper - OBFHELPER - private final long d; - private final long e; -- private final double f; -+ private final double f; public final double getDuration() { return this.f; } // Paper - OBFHELPER - - private b(double d0, double d1, long i) { - this.b = d0; -@@ -0,0 +0,0 @@ public class WorldBorder { - - @Override - public WorldBorder.a l() { -+ if (this.getLerpTimeRemaining() <= 0L) new WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), getOldSize(), getNewSize(), getDuration()).callEvent(); // Paper - return (WorldBorder.a) (this.g() <= 0L ? WorldBorder.this.new d(this.c) : this); - } - -@@ -0,0 +0,0 @@ public class WorldBorder { - - double e(); - -+ default long getLerpTimeRemaining() { return g(); } // Paper - OBFHELPER - long g(); - - double h(); diff --git a/Spigot-Server-Patches/Add-zombie-targets-turtle-egg-config.patch b/Spigot-Server-Patches/Add-zombie-targets-turtle-egg-config.patch deleted file mode 100644 index c1e5c0f3da..0000000000 --- a/Spigot-Server-Patches/Add-zombie-targets-turtle-egg-config.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Aug 2020 15:47:34 +0200 -Subject: [PATCH] Add zombie targets turtle egg config - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - maxLightningFlashDistance = 512; // Vanilla value - } - } -+ -+ public boolean zombiesTargetTurtleEggs = true; -+ private void zombiesTargetTurtleEggs() { -+ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - - @Override - protected void initPathfinder() { -- this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); -+ if (world.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.a(4, new EntityZombie.a(this, 1.0D, 3)); // Paper - this.goalSelector.a(8, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(8, new PathfinderGoalRandomLookaround(this)); - this.m(); diff --git a/Spigot-Server-Patches/Added-PlayerBedFailEnterEvent.patch b/Spigot-Server-Patches/Added-PlayerBedFailEnterEvent.patch deleted file mode 100644 index f48effc446..0000000000 --- a/Spigot-Server-Patches/Added-PlayerBedFailEnterEvent.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 24 Dec 2020 12:27:41 -0800 -Subject: [PATCH] Added PlayerBedFailEnterEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - this.g = ichatbasecomponent; - } - -+ public @Nullable IChatBaseComponent getChatComponent() { return this.a(); }; // Paper - OBFHELPER - @Nullable - public IChatBaseComponent a() { - return this.g; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBed.java b/src/main/java/net/minecraft/world/level/block/BlockBed.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBed.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBed.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapeCollision; - import net.minecraft.world.phys.shapes.VoxelShapes; - import org.apache.commons.lang3.ArrayUtils; -+import io.papermc.paper.event.player.PlayerBedFailEnterEvent; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - - public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - -@@ -0,0 +0,0 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity { - BlockPosition finalblockposition = blockposition; - // CraftBukkit end - entityhuman.sleep(blockposition).ifLeft((entityhuman_enumbedresult) -> { -+ // Paper start - PlayerBedFailEnterEvent -+ if (entityhuman_enumbedresult != null) { -+ PlayerBedFailEnterEvent event = new PlayerBedFailEnterEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE, PaperAdventure.asAdventure(entityhuman_enumbedresult.getChatComponent())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - // CraftBukkit start - handling bed explosion from below here -- if (entityhuman_enumbedresult == EntityHuman.EnumBedResult.NOT_POSSIBLE_HERE) { -+ if (event.getWillExplode()) { // Paper - this.explodeBed(finaliblockdata, world, finalblockposition); - } else - // CraftBukkit end - if (entityhuman_enumbedresult != null) { -- entityhuman.a(entityhuman_enumbedresult.a(), true); -+ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper -+ if(message != null) entityhuman.a(PaperAdventure.asVanilla(message), true); // Paper - } -+ } // Paper - - }); - return EnumInteractionResult.SUCCESS; diff --git a/Spigot-Server-Patches/Added-PlayerDeepSleepEvent.patch b/Spigot-Server-Patches/Added-PlayerDeepSleepEvent.patch deleted file mode 100644 index a84a2d4299..0000000000 --- a/Spigot-Server-Patches/Added-PlayerDeepSleepEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 21 Apr 2021 15:58:19 -0700 -Subject: [PATCH] Added PlayerDeepSleepEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - - if (this.isSleeping()) { - ++this.sleepTicks; -+ // Paper start -+ if (this.sleepTicks == 100) { -+ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((Player) getBukkitEntity()).callEvent()) { this.sleepTicks = Integer.MIN_VALUE; } -+ } -+ // Paper end - if (this.sleepTicks > 100) { - this.sleepTicks = 100; - } diff --git a/Spigot-Server-Patches/Added-PlayerLecternPageChangeEvent.patch b/Spigot-Server-Patches/Added-PlayerLecternPageChangeEvent.patch deleted file mode 100644 index c6483f1fa3..0000000000 --- a/Spigot-Server-Patches/Added-PlayerLecternPageChangeEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 23 Nov 2020 12:58:51 -0800 -Subject: [PATCH] Added PlayerLecternPageChangeEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -0,0 +0,0 @@ public abstract class Container { - this.getSlot(i).set(itemstack); - } - -+ public void setData(int index, int value) { this.a(index, value); } // Paper - OBFHELPER - public void a(int i, int j) { - ((ContainerProperty) this.d.get(i)).set(j); - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLectern.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - import org.bukkit.event.player.PlayerTakeLecternBookEvent; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; // Paper - - public class ContainerLectern extends Container { - -@@ -0,0 +0,0 @@ public class ContainerLectern extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - int j; -+ PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper - - if (i >= 100) { - j = i - 100; -@@ -0,0 +0,0 @@ public class ContainerLectern extends Container { - switch (i) { - case 1: - j = this.containerProperties.getProperty(0); -- this.a(0, j - 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 2: - j = this.containerProperties.getProperty(0); -- this.a(0, j + 1); -+ // Paper start -+ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); -+ playerLecternPageChangeEvent = new PlayerLecternPageChangeEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); -+ if (!playerLecternPageChangeEvent.callEvent()) { -+ return false; -+ } -+ this.setData(0, playerLecternPageChangeEvent.getNewPage()); -+ // Paper end - return true; - case 3: - if (!entityhuman.eK()) { diff --git a/Spigot-Server-Patches/Added-PlayerLoomPatternSelectEvent.patch b/Spigot-Server-Patches/Added-PlayerLoomPatternSelectEvent.patch deleted file mode 100644 index 0a28ecbdd2..0000000000 --- a/Spigot-Server-Patches/Added-PlayerLoomPatternSelectEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 25 Nov 2020 16:33:27 -0800 -Subject: [PATCH] Added PlayerLoomPatternSelectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerLoom.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryLoom; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; // Paper - - public class ContainerLoom extends Container { - -@@ -0,0 +0,0 @@ public class ContainerLoom extends Container { - } - // CraftBukkit end - private final ContainerAccess containerAccess; -- private final ContainerProperty d; -+ private final ContainerProperty d; public final ContainerProperty getSelectedBannerPattern() { return this.d; }; // Paper - OBFHELPER - private Runnable e; - private final Slot f; - private final Slot g; -@@ -0,0 +0,0 @@ public class ContainerLoom extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - if (i > 0 && i <= EnumBannerPatternType.R) { -- this.d.set(i); -+ // Paper start -+ int enumBannerPatternTypeOrdinal = i; -+ PlayerLoomPatternSelectEvent event = new PlayerLoomPatternSelectEvent((Player) entityhuman.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(EnumBannerPatternType.values()[i].getIdentifier())); -+ if (!event.callEvent()) { -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ for (EnumBannerPatternType nms : EnumBannerPatternType.values()) { -+ if (event.getPatternType().getIdentifier().equals(nms.getIdentifier())) { -+ enumBannerPatternTypeOrdinal = nms.ordinal(); -+ break; -+ } -+ } -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ this.getSelectedBannerPattern().set(enumBannerPatternTypeOrdinal); -+ // Paper end - this.j(); - return true; - } else { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/EnumBannerPatternType.java -@@ -0,0 +0,0 @@ public enum EnumBannerPatternType { - this.T = flag; - } - -+ public String getIdentifier() { return this.b(); } // Paper - OBFHELPER - public String b() { - return this.V; - } diff --git a/Spigot-Server-Patches/Added-PlayerStonecutterRecipeSelectEvent.patch b/Spigot-Server-Patches/Added-PlayerStonecutterRecipeSelectEvent.patch deleted file mode 100644 index 0adfa6d6c5..0000000000 --- a/Spigot-Server-Patches/Added-PlayerStonecutterRecipeSelectEvent.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 27 Nov 2020 17:14:27 -0800 -Subject: [PATCH] Added PlayerStonecutterRecipeSelectEvent - -Co-Authored-By: MiniDigger | Martin - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -0,0 +0,0 @@ public abstract class Container { - return slot; - } - -- protected ContainerProperty a(ContainerProperty containerproperty) { -+ protected ContainerProperty addDataSlot(ContainerProperty containerproperty) { return a(containerproperty); } protected ContainerProperty a(ContainerProperty containerproperty) { // Paper - OBFHELPER - this.d.add(containerproperty); - return containerproperty; - } -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerProperty.java -@@ -0,0 +0,0 @@ public abstract class ContainerProperty { - }; - } - -- public static ContainerProperty a(final int[] aint, final int i) { -+ public static ContainerProperty shared(final int[] aint, final int i) { return a(aint, i); } public static ContainerProperty a(final int[] aint, final int i) { // Paper - OBFHELPER - return new ContainerProperty() { - @Override - public int get() { -@@ -0,0 +0,0 @@ public abstract class ContainerProperty { - - public abstract void set(int i); - -- public boolean c() { -+ public boolean checkAndClearUpdateFlag() { return c(); } public boolean c() { // Paper - OBFHELPER - int i = this.get(); - boolean flag = i != this.a; - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryStonecutter; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - import org.bukkit.entity.Player; - // CraftBukkit end -+import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; // Paper - - public class ContainerStonecutter extends Container { - - private final ContainerAccess containerAccess; - private final ContainerProperty containerProperty; - private final World world; -- private List i; -+ private List i; public final List getRecipes() { return this.i; } // Paper - OBFHELPER - private ItemStack j; - private long k; - final Slot c; -@@ -0,0 +0,0 @@ public class ContainerStonecutter extends Container { - - public ContainerStonecutter(int i, PlayerInventory playerinventory, final ContainerAccess containeraccess) { - super(Containers.STONECUTTER, i); -- this.containerProperty = ContainerProperty.a(); -+ this.containerProperty = addDataSlot(ContainerProperty.shared(new int[1], 0)); // Paper - allow replication - this.i = Lists.newArrayList(); - this.j = ItemStack.b; - this.l = () -> { -@@ -0,0 +0,0 @@ public class ContainerStonecutter extends Container { - @Override - public boolean a(EntityHuman entityhuman, int i) { - if (this.d(i)) { -- this.containerProperty.set(i); -+ // Paper start -+ int recipeIndex = i; -+ this.containerProperty.set(recipeIndex); -+ this.containerProperty.checkAndClearUpdateFlag(); // mark as changed -+ if (this.isValidRecipeIndex(i)) { -+ PlayerStonecutterRecipeSelectEvent event = new PlayerStonecutterRecipeSelectEvent((Player) entityhuman.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(i).toBukkitRecipe()); -+ if (!event.callEvent()) { -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ return false; -+ } -+ int newRecipeIndex; -+ if (!this.getRecipes().get(recipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { // If the recipe did NOT stay the same -+ for (newRecipeIndex = 0; newRecipeIndex < this.getRecipes().size(); newRecipeIndex++) { -+ if (this.getRecipes().get(newRecipeIndex).getKey().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { -+ recipeIndex = newRecipeIndex; -+ break; -+ } -+ } -+ } -+ } -+ ((Player) entityhuman.getBukkitEntity()).updateInventory(); -+ this.containerProperty.set(recipeIndex); // set new index, so that listeners can read it -+ // Paper end - this.i(); - } - - return true; - } - -+ private boolean isValidRecipeIndex(int index) { return this.d(index); } // Paper - OBFHELPER - private boolean d(int i) { - return i >= 0 && i < this.i.size(); - } diff --git a/Spigot-Server-Patches/Added-ServerResourcesReloadedEvent.patch b/Spigot-Server-Patches/Added-ServerResourcesReloadedEvent.patch deleted file mode 100644 index 5c979fa7d8..0000000000 --- a/Spigot-Server-Patches/Added-ServerResourcesReloadedEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:04:01 -0800 -Subject: [PATCH] Added ServerResourcesReloadedEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; --import co.aikar.timings.Timings; --import com.destroystokyo.paper.event.server.PaperServerListPingEvent; --import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -0,0 +0,0 @@ import org.bukkit.event.server.ServerLoadEvent; - import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - import io.papermc.paper.util.PaperJvmChecker; // Paper -+import io.papermc.paper.event.server.ServerResourcesReloadedEvent; // Paper - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant a(Collection collection) { -+ return this.reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.PLUGIN); -+ } -+ public CompletableFuture reloadServerResources(Collection collection, ServerResourcesReloadedEvent.Cause cause) { -+ // Paper end - CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { - Stream stream = collection.stream(); // CraftBukkit - decompile error - ResourcePackRepository resourcepackrepository = this.resourcePackRepository; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant collection, CommandListenerWrapper commandlistenerwrapper) { -- commandlistenerwrapper.getServer().a(collection).exceptionally((throwable) -> { -+ commandlistenerwrapper.getServer().reloadServerResources(collection, ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { // Paper - CommandReload.LOGGER.warn("Failed to execute reload", throwable); - commandlistenerwrapper.sendFailureMessage(new ChatMessage("commands.reload.failure")); - return null; -@@ -0,0 +0,0 @@ public class CommandReload { - SaveData savedata = minecraftserver.getSaveData(); - Collection collection = resourcepackrepository.d(); - Collection collection1 = a(resourcepackrepository, savedata, collection); -- minecraftserver.a(collection1); -+ minecraftserver.reloadServerResources(collection1, ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/Added-Vanilla-Entity-Tags.patch b/Spigot-Server-Patches/Added-Vanilla-Entity-Tags.patch deleted file mode 100644 index 65f5f03299..0000000000 --- a/Spigot-Server-Patches/Added-Vanilla-Entity-Tags.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 20:03:35 -0800 -Subject: [PATCH] Added Vanilla Entity Tags - - -diff --git a/src/main/java/io/papermc/paper/CraftEntityTag.java b/src/main/java/io/papermc/paper/CraftEntityTag.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/CraftEntityTag.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper; -+ -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.tags.Tags; -+import net.minecraft.world.entity.EntityTypes; -+import org.bukkit.craftbukkit.tag.CraftTag; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.entity.EntityType; -+ -+import java.util.Collections; -+import java.util.Set; -+import java.util.stream.Collectors; -+ -+public class CraftEntityTag extends CraftTag, EntityType> { -+ -+ public CraftEntityTag(Tags> registry, MinecraftKey tag) { -+ super(registry, tag); -+ } -+ -+ @Override -+ public boolean isTagged(EntityType item) { -+ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); -+ } -+ -+ @Override -+ public Set getValues() { -+ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - Preconditions.checkArgument(clazz == org.bukkit.Fluid.class, "Fluid namespace must have fluid type"); - - return (org.bukkit.Tag) new CraftFluidTag(console.getTagRegistry().getFluidTags(), key); -+ // Paper start -+ case org.bukkit.Tag.REGISTRY_ENTITIES: -+ Preconditions.checkArgument(clazz == org.bukkit.entity.EntityType.class, "Entity namespace must have entitytype type"); -+ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(console.getTagRegistry().getEntityTags(), key); -+ // Paper end - default: - throw new IllegalArgumentException(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - private static final Map MATERIAL_ITEM = new HashMap<>(); - private static final Map MATERIAL_BLOCK = new HashMap<>(); - private static final Map MATERIAL_FLUID = new HashMap<>(); -+ // Paper start -+ private static final Map> ENTITY_TYPE_ENTITY_TYPES = new HashMap<>(); -+ private static final Map, org.bukkit.entity.EntityType> ENTITY_TYPES_ENTITY_TYPE = new HashMap<>(); - - static { -+ for (org.bukkit.entity.EntityType type : org.bukkit.entity.EntityType.values()) { -+ if (type == org.bukkit.entity.EntityType.UNKNOWN) continue; -+ ENTITY_TYPE_ENTITY_TYPES.put(type, IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); -+ ENTITY_TYPES_ENTITY_TYPE.put(IRegistry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey())), type); -+ } -+ // Paper end - for (Block block : IRegistry.BLOCK) { - BLOCK_MATERIAL.put(block, Material.getMaterial(IRegistry.BLOCK.getKey(block).getKey().toUpperCase(Locale.ROOT))); - } -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public static MinecraftKey key(Material mat) { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } -+ // Paper start -+ public static net.minecraft.world.entity.EntityTypes getEntityTypes(org.bukkit.entity.EntityType type) { -+ return ENTITY_TYPE_ENTITY_TYPES.get(type); -+ } -+ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityTypes entityTypes) { -+ return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); -+ } -+ // Paper end - // ======================================================================== - // Paper start - @Override diff --git a/Spigot-Server-Patches/Added-WorldGameRuleChangeEvent.patch b/Spigot-Server-Patches/Added-WorldGameRuleChangeEvent.patch deleted file mode 100644 index f2ee830b76..0000000000 --- a/Spigot-Server-Patches/Added-WorldGameRuleChangeEvent.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 20 Dec 2020 16:41:44 -0800 -Subject: [PATCH] Added WorldGameRuleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamerule.java b/src/main/java/net/minecraft/server/commands/CommandGamerule.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamerule.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamerule.java -@@ -0,0 +0,0 @@ public class CommandGamerule { - CommandListenerWrapper commandlistenerwrapper = (CommandListenerWrapper) commandcontext.getSource(); - T t0 = commandlistenerwrapper.getWorld().getGameRules().get(gamerules_gamerulekey); // CraftBukkit - -- t0.b(commandcontext, "value"); -+ t0.setValue(commandcontext, "value", gamerules_gamerulekey); // Paper - commandlistenerwrapper.sendMessage(new ChatMessage("commands.gamerule.set", new Object[]{gamerules_gamerulekey.a(), t0.toString()}), true); - return t0.getIntValue(); - } -diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/GameRules.java -+++ b/src/main/java/net/minecraft/world/level/GameRules.java -@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.world.WorldGameRuleChangeEvent; // Paper - - public class GameRules { - -@@ -0,0 +0,0 @@ public class GameRules { - } - - @Override -- protected void a(CommandContext commandcontext, String s) { -- this.b = BoolArgumentType.getBool(commandcontext, s); -+ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.b = Boolean.parseBoolean(event.getValue()); -+ // Paper end - } - - public boolean a() { -@@ -0,0 +0,0 @@ public class GameRules { - } - - @Override -- protected void a(CommandContext commandcontext, String s) { -- this.b = IntegerArgumentType.getInteger(commandcontext, s); -+ protected void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper start -+ WorldGameRuleChangeEvent event = new WorldGameRuleChangeEvent(commandcontext.getSource().getBukkitWorld(), commandcontext.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(commandcontext, s))); -+ if (!event.callEvent()) return; -+ this.b = Integer.parseInt(event.getValue()); -+ // Paper end - } - - public int a() { -@@ -0,0 +0,0 @@ public class GameRules { - this.a = gamerules_gameruledefinition; - } - -- protected abstract void a(CommandContext commandcontext, String s); -+ protected void updateValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.a(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ protected abstract void a(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey); // Paper - -- public void b(CommandContext commandcontext, String s) { -- this.a(commandcontext, s); -+ public void setValue(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { this.b(commandcontext, s, gameRuleKey); } // Paper - OBFHELPER -+ public void b(CommandContext commandcontext, String s, GameRules.GameRuleKey gameRuleKey) { // Paper -+ this.updateValue(commandcontext, s, gameRuleKey); // Paper - this.onChange(((CommandListenerWrapper) commandcontext.getSource()).getServer()); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - if (!isGameRule(rule)) return false; - -+ // Paper start -+ GameRule gameRule = GameRule.getByName(rule); -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, gameRule, value); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule)); -- handle.setValue(value); -+ handle.setValue(event.getValue().toString()); // Paper - handle.onChange(getHandle().getMinecraftServer()); - return true; - } -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - if (!isGameRule(rule.getName())) return false; - -+ // Paper start -+ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(this, null, rule, String.valueOf(newValue)); -+ if (!event.callEvent()) return false; -+ // Paper end - GameRules.GameRuleValue handle = getHandle().getGameRules().get(getGameRulesNMS().get(rule.getName())); -- handle.setValue(newValue.toString()); -+ handle.setValue(event.getValue().toString()); // Paper - handle.onChange(getHandle().getMinecraftServer()); - return true; - } diff --git a/Spigot-Server-Patches/Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/Spigot-Server-Patches/Added-firing-of-PlayerChangeBeaconEffectEvent.patch deleted file mode 100644 index 586d57f720..0000000000 --- a/Spigot-Server-Patches/Added-firing-of-PlayerChangeBeaconEffectEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 15:14:51 -0600 -Subject: [PATCH] Added firing of PlayerChangeBeaconEffectEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerBeacon.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.player.PlayerInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryView; - // CraftBukkit end - -+// Paper start -+import io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent; -+// Paper end -+ - public class ContainerBeacon extends Container { - - private final IInventory beacon; -@@ -0,0 +0,0 @@ public class ContainerBeacon extends Container { - - public void c(int i, int j) { - if (this.d.hasItem()) { -- this.containerProperties.setProperty(1, i); -- this.containerProperties.setProperty(2, j); -+ // Paper start -+ PlayerChangeBeaconEffectEvent event = new PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(i), org.bukkit.potion.PotionEffectType.getById(j), this.containerAccess.getLocation().getBlock()); -+ if (event.callEvent()) { -+ this.containerProperties.setProperty(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); -+ this.containerProperties.setProperty(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); -+ if (!event.willConsumeItem()) return; - this.d.a(1); -+ } -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/Added-missing-default-perms-for-commands.patch b/Spigot-Server-Patches/Added-missing-default-perms-for-commands.patch deleted file mode 100644 index 063e919c7b..0000000000 --- a/Spigot-Server-Patches/Added-missing-default-perms-for-commands.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 16 Nov 2020 12:01:52 -0800 -Subject: [PATCH] Added missing default perms for commands - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/permissions/CommandPermissions.java -@@ -0,0 +0,0 @@ public final class CommandPermissions { - DefaultPermissions.registerPermission(PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); - DefaultPermissions.registerPermission(PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); -+ // Paper start -+ DefaultPermissions.registerPermission(PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "replaceitem", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) -+ DefaultPermissions.registerPermission(PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); -+ DefaultPermissions.registerPermission(PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); -+ DefaultPermissions.registerPermission(PREFIX + "worldborder", "Allows the user to manage the world border", PermissionDefault.OP, commands); -+ // Paper end - - DefaultPermissions.registerPermission("minecraft.admin.command_feedback", "Receive command broadcasts when sendCommandFeedback is true", PermissionDefault.OP, commands); - diff --git a/Spigot-Server-Patches/Added-world-settings-for-mobs-picking-up-loot.patch b/Spigot-Server-Patches/Added-world-settings-for-mobs-picking-up-loot.patch deleted file mode 100644 index d5f02bcb45..0000000000 --- a/Spigot-Server-Patches/Added-world-settings-for-mobs-picking-up-loot.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 28 Nov 2020 18:43:52 -0800 -Subject: [PATCH] Added world settings for mobs picking up loot - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } - -+ public boolean zombiesAlwaysCanPickUpLoot; -+ public boolean skeletonsAlwaysCanPickUpLoot; -+ private void setMobsAlwaysCanPickUpLoot() { -+ zombiesAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.zombies", false); -+ skeletonsAlwaysCanPickUpLoot = getBoolean("mobs-can-always-pick-up-loot.skeletons", false); -+ log("Zombies can always pick up loot: " + zombiesAlwaysCanPickUpLoot + ". Skeletons can always pick up loot: " + skeletonsAlwaysCanPickUpLoot + "."); -+ } -+ - public int expMergeMaxValue; - private void expMergeMaxValue() { - expMergeMaxValue = getInt("experience-merge-max-value", -1); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - this.a(difficultydamagescaler); - this.b(difficultydamagescaler); - this.eL(); -- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); -+ this.setCanPickupLoot(this.world.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficultydamagescaler.d()); // Paper - if (this.getEquipment(EnumItemSlot.HEAD).isEmpty()) { - LocalDate localdate = LocalDate.now(); - int i = localdate.get(ChronoField.DAY_OF_MONTH); -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - Object object = super.prepare(worldaccess, difficultydamagescaler, enummobspawn, groupdataentity, nbttagcompound); - float f = difficultydamagescaler.d(); - -- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * f); -+ this.setCanPickupLoot(this.world.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper - if (object == null) { - object = new EntityZombie.GroupDataZombie(a(worldaccess.getRandom()), true); - } diff --git a/Spigot-Server-Patches/Additional-Block-Material-API-s.patch b/Spigot-Server-Patches/Additional-Block-Material-API-s.patch deleted file mode 100644 index 969de70cfa..0000000000 --- a/Spigot-Server-Patches/Additional-Block-Material-API-s.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Dec 2020 19:43:01 -0500 -Subject: [PATCH] Additional Block Material API's - -Faster version for isSolid() that utilizes NMS's state for isSolid instead of the slower -process to do this in the Bukkit API - -Adds API for buildable, replaceable, burnable too. - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - return getNMS().getMaterial().isLiquid(); - } - -+ // Paper start -+ @Override -+ public boolean isBuildable() { -+ return getNMS().getMaterial().isBuildable(); -+ } -+ @Override -+ public boolean isBurnable() { -+ return getNMS().getMaterial().isBurnable(); -+ } -+ @Override -+ public boolean isReplaceable() { -+ return getNMS().getMaterial().isReplaceable(); -+ } -+ @Override -+ public boolean isSolid() { -+ return getNMS().getMaterial().isSolid(); -+ } -+ // Paper end -+ - @Override - public PistonMoveReaction getPistonMoveReaction() { - return PistonMoveReaction.getById(getNMS().getPushReaction().ordinal()); diff --git a/Spigot-Server-Patches/Adventure.patch b/Spigot-Server-Patches/Adventure.patch deleted file mode 100644 index 86e34385cf..0000000000 --- a/Spigot-Server-Patches/Adventure.patch +++ /dev/null @@ -1,3278 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Fri, 29 Jan 2021 17:54:03 +0100 -Subject: [PATCH] Adventure - -Co-authored-by: zml -Co-authored-by: Jake Potrebic - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + - " - Server Name: " + timingsServerName); - } -+ -+ public static boolean useDisplayNameInQuit = false; -+ private static void useDisplayNameInQuit() { -+ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import com.google.gson.JsonElement; -+import com.google.gson.JsonSerializationContext; -+import com.google.gson.JsonSerializer; -+import java.lang.reflect.Type; -+import java.util.List; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextComponent; -+import net.minecraft.network.chat.ChatModifier; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.network.chat.IChatMutableComponent; -+import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class AdventureComponent implements IChatBaseComponent { -+ final Component wrapped; -+ private @MonotonicNonNull IChatBaseComponent converted; -+ -+ public AdventureComponent(final Component wrapped) { -+ this.wrapped = wrapped; -+ } -+ -+ public IChatBaseComponent deepConverted() { -+ IChatBaseComponent converted = this.converted; -+ if (converted == null) { -+ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); -+ this.converted = converted; -+ } -+ return converted; -+ } -+ -+ public @Nullable IChatBaseComponent deepConvertedIfPresent() { -+ return this.converted; -+ } -+ -+ @Override -+ public ChatModifier getChatModifier() { -+ return this.deepConverted().getChatModifier(); -+ } -+ -+ @Override -+ public String getText() { -+ if (this.wrapped instanceof TextComponent) { -+ return ((TextComponent) this.wrapped).content(); -+ } else { -+ return this.deepConverted().getText(); -+ } -+ } -+ -+ @Override -+ public String getString() { -+ return PaperAdventure.PLAIN.serialize(this.wrapped); -+ } -+ -+ @Override -+ public List getSiblings() { -+ return this.deepConverted().getSiblings(); -+ } -+ -+ @Override -+ public IChatMutableComponent g() { -+ return this.deepConverted().g(); -+ } -+ -+ @Override -+ public IChatMutableComponent mutableCopy() { -+ return this.deepConverted().mutableCopy(); -+ } -+ -+ public static class Serializer implements JsonSerializer { -+ @Override -+ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) { -+ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class); -+ } -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import io.papermc.paper.chat.ChatRenderer; -+import io.papermc.paper.event.player.AbstractChatEvent; -+import io.papermc.paper.event.player.AsyncChatEvent; -+import io.papermc.paper.event.player.ChatEvent; -+import java.util.Set; -+import java.util.concurrent.ExecutionException; -+import java.util.function.Consumer; -+import java.util.regex.Pattern; -+ -+import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.audience.MessageType; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextReplacementConfig; -+import net.kyori.adventure.text.event.ClickEvent; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.util.LazyPlayerSet; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.bukkit.entity.Player; -+import org.bukkit.event.Event; -+import org.bukkit.event.HandlerList; -+import org.bukkit.event.player.AsyncPlayerChatEvent; -+import org.bukkit.event.player.PlayerChatEvent; -+ -+public final class ChatProcessor { -+ // <-- copied from adventure-text-serializer-legacy -+ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?"); -+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:"); -+ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder() -+ .match(DEFAULT_URL_PATTERN) -+ .replacement(url -> { -+ String clickUrl = url.content(); -+ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) { -+ clickUrl = "http://" + clickUrl; -+ } -+ return url.clickEvent(ClickEvent.openUrl(clickUrl)); -+ }) -+ .build(); -+ // copied from adventure-text-serializer-legacy --> -+ final MinecraftServer server; -+ final EntityPlayer player; -+ final String message; -+ final boolean async; -+ final Component originalMessage; -+ -+ public ChatProcessor(final MinecraftServer server, final EntityPlayer player, final String message, final boolean async) { -+ this.server = server; -+ this.player = player; -+ this.message = message; -+ this.async = async; -+ this.originalMessage = Component.text(message); -+ } -+ -+ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) -+ public void process() { -+ this.processingLegacyFirst( -+ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // continuing from AsyncPlayerChatEvent and PlayerChatEvent -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ event.getRecipients(), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // no legacy events called, all nice and fresh! -+ () -> { -+ this.processModern( -+ ChatRenderer.defaultRenderer(), -+ new LazyPlayerSet(this.server), -+ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), -+ false -+ ); -+ } -+ ); -+ } -+ -+ @SuppressWarnings("deprecation") -+ private void processingLegacyFirst( -+ final Consumer continueAfterAsync, -+ final Consumer continueAfterAsyncAndSync, -+ final Runnable modernOnly -+ ) { -+ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); -+ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); -+ if (listenersOnAsyncEvent || listenersOnSyncEvent) { -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); -+ post(ae); -+ if (listenersOnSyncEvent) { -+ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ post(se); -+ return null; -+ } -+ }); -+ continueAfterAsyncAndSync.accept(se); -+ } else { -+ continueAfterAsync.accept(ae); -+ } -+ } else { -+ modernOnly.run(); -+ } -+ } -+ -+ private void processModern(final ChatRenderer renderer, final Set recipients, final Component message, final boolean cancelled) { -+ final AsyncChatEvent ae = this.createAsync(renderer, recipients, new LazyChatAudienceSet(), message); -+ ae.setCancelled(cancelled); // propagate cancelled state -+ post(ae); -+ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); -+ if (listenersOnSyncEvent) { -+ this.continueWithSyncFromWhereAsyncLeftOff(ae); -+ } else { -+ this.complete(ae); -+ } -+ } -+ -+ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.recipients(), ae.viewers(), ae.message()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ post(se); -+ ChatProcessor.this.complete(se); -+ return null; -+ } -+ }); -+ } -+ -+ private void complete(final AbstractChatEvent event) { -+ if (event.isCancelled()) { -+ return; -+ } -+ -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final Component displayName = displayName(player); -+ final Component message = event.message(); -+ final ChatRenderer renderer = event.renderer(); -+ -+ final Set viewers = event.viewers(); -+ final Set recipients = event.recipients(); -+ if (viewers instanceof LazyChatAudienceSet && recipients instanceof LazyPlayerSet && -+ (!((LazyChatAudienceSet) viewers).isLazy() || ((LazyPlayerSet) recipients).isLazy())) { -+ for (final Audience viewer : viewers) { -+ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT); -+ } -+ } else { -+ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); -+ for (final Player recipient : recipients) { -+ recipient.sendMessage(player, renderer.render(player, displayName, message, recipient), MessageType.CHAT); -+ } -+ } -+ } -+ -+ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { -+ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); -+ } -+ -+ private ChatEvent createSync(final ChatRenderer renderer, final Set recipients, final Set viewers, final Component message) { -+ return new ChatEvent(this.player.getBukkitEntity(), recipients, viewers, renderer, message, this.originalMessage); -+ } -+ -+ private static String legacyDisplayName(final CraftPlayer player) { -+ return player.getDisplayName(); -+ } -+ -+ private static Component displayName(final CraftPlayer player) { -+ return player.displayName(); -+ } -+ -+ private static ChatRenderer legacyRenderer(final String format) { -+ return (player, displayName, message, recipient) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG); -+ } -+ -+ private void queueIfAsyncOrRunImmediately(final Waitable waitable) { -+ if (this.async) { -+ this.server.processQueue.add(waitable); -+ } else { -+ waitable.run(); -+ } -+ try { -+ waitable.get(); -+ } catch (final InterruptedException e) { -+ Thread.currentThread().interrupt(); // tag, you're it -+ } catch (final ExecutionException e) { -+ throw new RuntimeException("Exception processing chat", e.getCause()); -+ } -+ } -+ -+ private static void post(final Event event) { -+ Bukkit.getPluginManager().callEvent(event); -+ } -+ -+ private static boolean anyListeners(final HandlerList handlers) { -+ return handlers.getRegisteredListeners().length > 0; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public final class DisplayNames { -+ private DisplayNames() { -+ } -+ -+ public static String getLegacy(final CraftPlayer player) { -+ return getLegacy(player.getHandle()); -+ } -+ -+ public static String getLegacy(final EntityPlayer player) { -+ final String legacy = player.displayName; -+ if (legacy != null) { -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import net.kyori.adventure.audience.Audience; -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.LazyHashSet; -+import org.bukkit.craftbukkit.util.LazyPlayerSet; -+import org.bukkit.entity.Player; -+ -+import java.util.HashSet; -+import java.util.Set; -+ -+final class LazyChatAudienceSet extends LazyHashSet { -+ @Override -+ protected Set makeReference() { -+ final Set playerSet = LazyPlayerSet.makePlayerSet(MinecraftServer.getServer()); -+ final HashSet audiences = new HashSet<>(playerSet); -+ audiences.add(Bukkit.getConsoleSender()); -+ return audiences; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import java.io.IOException; -+import java.util.UUID; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.event.HoverEvent; -+import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.nbt.MojangsonParser; -+import net.minecraft.nbt.NBTBase; -+import net.minecraft.nbt.NBTTagCompound; -+ -+final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { -+ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); -+ private static final Codec SNBT_CODEC = Codec.of(MojangsonParser::parse, NBTBase::toString); -+ -+ static final String ITEM_TYPE = "id"; -+ static final String ITEM_COUNT = "Count"; -+ static final String ITEM_TAG = "tag"; -+ -+ static final String ENTITY_NAME = "name"; -+ static final String ENTITY_TYPE = "type"; -+ static final String ENTITY_ID = "id"; -+ -+ NBTLegacyHoverEventSerializer() { -+ } -+ -+ @Override -+ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final NBTTagCompound contents = SNBT_CODEC.decode(raw); -+ final NBTTagCompound tag = contents.getCompound(ITEM_TAG); -+ return HoverEvent.ShowItem.of( -+ Key.key(contents.getString(ITEM_TYPE)), -+ contents.hasKey(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, -+ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder componentCodec) throws IOException { -+ final String raw = PlainComponentSerializer.plain().serialize(input); -+ try { -+ final NBTTagCompound contents = SNBT_CODEC.decode(raw); -+ return HoverEvent.ShowEntity.of( -+ Key.key(contents.getString(ENTITY_TYPE)), -+ UUID.fromString(contents.getString(ENTITY_ID)), -+ componentCodec.decode(contents.getString(ENTITY_NAME)) -+ ); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ -+ @Override -+ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException { -+ final NBTTagCompound tag = new NBTTagCompound(); -+ tag.setString(ITEM_TYPE, input.item().asString()); -+ tag.setByte(ITEM_COUNT, (byte) input.count()); -+ if (input.nbt() != null) { -+ try { -+ tag.set(ITEM_TAG, input.nbt().get(SNBT_CODEC)); -+ } catch (final CommandSyntaxException ex) { -+ throw new IOException(ex); -+ } -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+ -+ @Override -+ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder componentCodec) throws IOException { -+ final NBTTagCompound tag = new NBTTagCompound(); -+ tag.setString(ENTITY_ID, input.id().toString()); -+ tag.setString(ENTITY_TYPE, input.type().asString()); -+ if (input.name() != null) { -+ tag.setString(ENTITY_NAME, componentCodec.encode(input.name())); -+ } -+ return Component.text(SNBT_CODEC.encode(tag)); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import io.netty.util.AttributeKey; -+import java.io.IOException; -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Locale; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.inventory.Book; -+import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; -+import net.kyori.adventure.sound.Sound; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TranslatableComponent; -+import net.kyori.adventure.text.flattener.ComponentFlattener; -+import net.kyori.adventure.text.format.TextColor; -+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; -+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; -+import net.kyori.adventure.translation.GlobalTranslator; -+import net.kyori.adventure.util.Codec; -+import net.minecraft.EnumChatFormat; -+import net.minecraft.locale.LocaleLanguage; -+import net.minecraft.nbt.MojangsonParser; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; -+import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.sounds.SoundCategory; -+import net.minecraft.world.BossBattle; -+import net.minecraft.world.item.ItemStack; -+import org.bukkit.ChatColor; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; -+ -+public final class PaperAdventure { -+ public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); -+ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); -+ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() -+ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { -+ final @NonNull String translated = LocaleLanguage.a().a(translatable.key()); -+ -+ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); -+ final List args = translatable.args(); -+ int argPosition = 0; -+ int lastIdx = 0; -+ while (matcher.find()) { -+ // append prior -+ if (lastIdx < matcher.start()) { -+ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start()))); -+ } -+ lastIdx = matcher.end(); -+ -+ final @Nullable String argIdx = matcher.group(1); -+ // calculate argument position -+ if (argIdx != null) { -+ try { -+ final int idx = Integer.parseInt(argIdx) - 1; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } catch (final NumberFormatException ex) { -+ // ignore, drop the format placeholder -+ } -+ } else { -+ final int idx = argPosition++; -+ if (idx < args.size()) { -+ consumer.accept(args.get(idx)); -+ } -+ } -+ } -+ -+ // append tail -+ if (lastIdx < translated.length()) { -+ consumer.accept(Component.text(translated.substring(lastIdx))); -+ } -+ }) -+ .build(); -+ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); -+ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); -+ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .build(); -+ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder() -+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) -+ .downsampleColors() -+ .build(); -+ private static final Codec NBT_CODEC = new Codec() { -+ @Override -+ public @NonNull NBTTagCompound decode(final @NonNull String encoded) throws IOException { -+ try { -+ return MojangsonParser.parse(encoded); -+ } catch (final CommandSyntaxException e) { -+ throw new IOException(e); -+ } -+ } -+ -+ @Override -+ public @NonNull String encode(final @NonNull NBTTagCompound decoded) { -+ return decoded.toString(); -+ } -+ }; -+ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); -+ -+ private PaperAdventure() { -+ } -+ -+ // Key -+ -+ public static MinecraftKey asVanilla(final Key key) { -+ return new MinecraftKey(key.namespace(), key.value()); -+ } -+ -+ public static MinecraftKey asVanillaNullable(final Key key) { -+ if (key == null) { -+ return null; -+ } -+ return new MinecraftKey(key.namespace(), key.value()); -+ } -+ -+ // Component -+ -+ public static Component asAdventure(final IChatBaseComponent component) { -+ return component == null ? Component.empty() : GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(component), Component.class); -+ } -+ -+ public static ArrayList asAdventure(final List vanillas) { -+ final ArrayList adventures = new ArrayList<>(vanillas.size()); -+ for (final IChatBaseComponent vanilla : vanillas) { -+ adventures.add(asAdventure(vanilla)); -+ } -+ return adventures; -+ } -+ -+ public static ArrayList asAdventureFromJson(final List jsonStrings) { -+ final ArrayList adventures = new ArrayList<>(jsonStrings.size()); -+ for (final String json : jsonStrings) { -+ adventures.add(GsonComponentSerializer.gson().deserialize(json)); -+ } -+ return adventures; -+ } -+ -+ public static List asJson(final List adventures) { -+ final List jsons = new ArrayList<>(adventures.size()); -+ for (final Component component : adventures) { -+ jsons.add(GsonComponentSerializer.gson().serialize(component)); -+ } -+ return jsons; -+ } -+ -+ public static IChatBaseComponent asVanilla(final Component component) { -+ if (true) return new AdventureComponent(component); -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(GSON.serializer().toJsonTree(component)); -+ } -+ -+ public static List asVanilla(final List adventures) { -+ final List vanillas = new ArrayList<>(adventures.size()); -+ for (final Component adventure : adventures) { -+ vanillas.add(asVanilla(adventure)); -+ } -+ return vanillas; -+ } -+ -+ public static String asJsonString(final Component component, final Locale locale) { -+ return GSON.serialize( -+ GlobalTranslator.render( -+ component, -+ // play it safe -+ locale != null -+ ? locale -+ : Locale.US -+ ) -+ ); -+ } -+ -+ public static String asJsonString(final IChatBaseComponent component, final Locale locale) { -+ if (component instanceof AdventureComponent) { -+ return asJsonString(((AdventureComponent) component).wrapped, locale); -+ } -+ return IChatBaseComponent.ChatSerializer.componentToJson(component); -+ } -+ -+ // thank you for being worse than wet socks, Bukkit -+ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { -+ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); -+ } -+ -+ // BossBar -+ -+ public static BossBattle.BarColor asVanilla(final BossBar.Color color) { -+ if (color == BossBar.Color.PINK) { -+ return BossBattle.BarColor.PINK; -+ } else if (color == BossBar.Color.BLUE) { -+ return BossBattle.BarColor.BLUE; -+ } else if (color == BossBar.Color.RED) { -+ return BossBattle.BarColor.RED; -+ } else if (color == BossBar.Color.GREEN) { -+ return BossBattle.BarColor.GREEN; -+ } else if (color == BossBar.Color.YELLOW) { -+ return BossBattle.BarColor.YELLOW; -+ } else if (color == BossBar.Color.PURPLE) { -+ return BossBattle.BarColor.PURPLE; -+ } else if (color == BossBar.Color.WHITE) { -+ return BossBattle.BarColor.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossBar.Color asAdventure(final BossBattle.BarColor color) { -+ if(color == BossBattle.BarColor.PINK) { -+ return BossBar.Color.PINK; -+ } else if(color == BossBattle.BarColor.BLUE) { -+ return BossBar.Color.BLUE; -+ } else if(color == BossBattle.BarColor.RED) { -+ return BossBar.Color.RED; -+ } else if(color == BossBattle.BarColor.GREEN) { -+ return BossBar.Color.GREEN; -+ } else if(color == BossBattle.BarColor.YELLOW) { -+ return BossBar.Color.YELLOW; -+ } else if(color == BossBattle.BarColor.PURPLE) { -+ return BossBar.Color.PURPLE; -+ } else if(color == BossBattle.BarColor.WHITE) { -+ return BossBar.Color.WHITE; -+ } -+ throw new IllegalArgumentException(color.name()); -+ } -+ -+ public static BossBattle.BarStyle asVanilla(final BossBar.Overlay overlay) { -+ if (overlay == BossBar.Overlay.PROGRESS) { -+ return BossBattle.BarStyle.PROGRESS; -+ } else if (overlay == BossBar.Overlay.NOTCHED_6) { -+ return BossBattle.BarStyle.NOTCHED_6; -+ } else if (overlay == BossBar.Overlay.NOTCHED_10) { -+ return BossBattle.BarStyle.NOTCHED_10; -+ } else if (overlay == BossBar.Overlay.NOTCHED_12) { -+ return BossBattle.BarStyle.NOTCHED_12; -+ } else if (overlay == BossBar.Overlay.NOTCHED_20) { -+ return BossBattle.BarStyle.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static BossBar.Overlay asAdventure(final BossBattle.BarStyle overlay) { -+ if (overlay == BossBattle.BarStyle.PROGRESS) { -+ return BossBar.Overlay.PROGRESS; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_6) { -+ return BossBar.Overlay.NOTCHED_6; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_10) { -+ return BossBar.Overlay.NOTCHED_10; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_12) { -+ return BossBar.Overlay.NOTCHED_12; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_20) { -+ return BossBar.Overlay.NOTCHED_20; -+ } -+ throw new IllegalArgumentException(overlay.name()); -+ } -+ -+ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) { -+ if (value) { -+ bar.addFlag(flag); -+ } else { -+ bar.removeFlag(flag); -+ } -+ } -+ -+ // Book -+ -+ public static ItemStack asItemStack(final Book book, final Locale locale) { -+ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); -+ final NBTTagCompound tag = item.getOrCreateTag(); -+ tag.setString("title", asJsonString(book.title(), locale)); -+ tag.setString("author", asJsonString(book.author(), locale)); -+ final NBTTagList pages = new NBTTagList(); -+ for (final Component page : book.pages()) { -+ pages.add(NBTTagString.create(asJsonString(page, locale))); -+ } -+ tag.set("pages", pages); -+ return item; -+ } -+ -+ // Sounds -+ -+ public static SoundCategory asVanilla(final Sound.Source source) { -+ if (source == Sound.Source.MASTER) { -+ return SoundCategory.MASTER; -+ } else if (source == Sound.Source.MUSIC) { -+ return SoundCategory.MUSIC; -+ } else if (source == Sound.Source.RECORD) { -+ return SoundCategory.RECORDS; -+ } else if (source == Sound.Source.WEATHER) { -+ return SoundCategory.WEATHER; -+ } else if (source == Sound.Source.BLOCK) { -+ return SoundCategory.BLOCKS; -+ } else if (source == Sound.Source.HOSTILE) { -+ return SoundCategory.HOSTILE; -+ } else if (source == Sound.Source.NEUTRAL) { -+ return SoundCategory.NEUTRAL; -+ } else if (source == Sound.Source.PLAYER) { -+ return SoundCategory.PLAYERS; -+ } else if (source == Sound.Source.AMBIENT) { -+ return SoundCategory.AMBIENT; -+ } else if (source == Sound.Source.VOICE) { -+ return SoundCategory.VOICE; -+ } -+ throw new IllegalArgumentException(source.name()); -+ } -+ -+ public static @Nullable SoundCategory asVanillaNullable(final Sound.@Nullable Source source) { -+ if (source == null) { -+ return null; -+ } -+ return asVanilla(source); -+ } -+ -+ // NBT -+ -+ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable NBTTagCompound tag) { -+ if (tag == null) { -+ return null; -+ } -+ try { -+ return BinaryTagHolder.encode(tag, NBT_CODEC); -+ } catch (final IOException e) { -+ return null; -+ } -+ } -+ -+ // Colors -+ -+ public static @NonNull TextColor asAdventure(EnumChatFormat minecraftColor) { -+ if (minecraftColor.e() == null) { -+ throw new IllegalArgumentException("Not a valid color"); -+ } -+ return TextColor.color(minecraftColor.e()); -+ } -+ -+ public static @Nullable EnumChatFormat asVanilla(TextColor color) { -+ return EnumChatFormat.getByHexValue(color.value()); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import java.util.Set; -+import java.util.function.Consumer; -+import net.kyori.adventure.bossbar.BossBar; -+import net.kyori.adventure.text.Component; -+import net.minecraft.network.protocol.game.PacketPlayOutBoss; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+public final class VanillaBossBarListener implements BossBar.Listener { -+ private final Consumer action; -+ -+ public VanillaBossBarListener(final Consumer action) { -+ this.action = action; -+ } -+ -+ @Override -+ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_NAME); -+ } -+ -+ @Override -+ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PCT); -+ } -+ -+ @Override -+ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_STYLE); -+ } -+ -+ @Override -+ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PROPERTIES); -+ } -+} -diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.adventure; -+ -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.serializer.ComponentSerializer; -+import net.minecraft.network.chat.IChatBaseComponent; -+ -+final class WrapperAwareSerializer implements ComponentSerializer { -+ @Override -+ public Component deserialize(final IChatBaseComponent input) { -+ if (input instanceof AdventureComponent) { -+ return ((AdventureComponent) input).wrapped; -+ } -+ return PaperAdventure.GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(input), Component.class); -+ } -+ -+ @Override -+ public IChatBaseComponent serialize(final Component component) { -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); -+ } -+} -diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java -@@ -0,0 +0,0 @@ -+package net.kyori.adventure.bossbar; -+ -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.adventure.VanillaBossBarListener; -+import net.minecraft.server.level.BossBattleServer; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+ -+public abstract class HackyBossBarPlatformBridge { -+ public BossBattleServer vanilla$bar; -+ private VanillaBossBarListener vanilla$listener; -+ -+ public final void paper$playerShow(final CraftPlayer player) { -+ if (this.vanilla$bar == null) { -+ final BossBar $this = (BossBar) this; -+ this.vanilla$bar = new BossBattleServer( -+ PaperAdventure.asVanilla($this.name()), -+ PaperAdventure.asVanilla($this.color()), -+ PaperAdventure.asVanilla($this.overlay()) -+ ); -+ this.vanilla$bar.adventure = $this; -+ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::sendUpdate); -+ $this.addListener(this.vanilla$listener); -+ } -+ this.vanilla$bar.addPlayer(player.getHandle()); -+ } -+ -+ public final void paper$playerHide(final CraftPlayer player) { -+ if (this.vanilla$bar != null) { -+ this.vanilla$bar.removePlayer(player.getHandle()); -+ if (this.vanilla$bar.getPlayers().isEmpty()) { -+ ((BossBar) this).removeListener(this.vanilla$listener); -+ this.vanilla$bar = null; -+ } -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/EnumChatFormat.java b/src/main/java/net/minecraft/EnumChatFormat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/EnumChatFormat.java -+++ b/src/main/java/net/minecraft/EnumChatFormat.java -@@ -0,0 +0,0 @@ public enum EnumChatFormat { - return !this.A && this != EnumChatFormat.RESET; - } - -+ @Nullable public Integer getHexValue() { return this.e(); } // Paper - OBFHELPER - @Nullable - public Integer e() { - return this.D; -@@ -0,0 +0,0 @@ public enum EnumChatFormat { - return s == null ? null : (EnumChatFormat) EnumChatFormat.w.get(c(s)); - } - -+ // Paper start -+ @Nullable public static EnumChatFormat getByHexValue(int i) { -+ for (EnumChatFormat value : values()) { -+ if (value.getHexValue() != null && value.getHexValue() == i) { -+ return value; -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Nullable - public static EnumChatFormat a(int i) { - if (i < 0) { -diff --git a/src/main/java/net/minecraft/nbt/NBTTagString.java b/src/main/java/net/minecraft/nbt/NBTTagString.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagString.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagString.java -@@ -0,0 +0,0 @@ public class NBTTagString implements NBTBase { - this.data = s; - } - -+ public static NBTTagString create(final String value) { return a(value); } // Paper - OBFHELPER - public static NBTTagString a(String s) { - return s.isEmpty() ? NBTTagString.b : new NBTTagString(s); - } -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -0,0 +0,0 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.handler.codec.DecoderException; - import io.netty.handler.codec.EncoderException; - import io.netty.util.ByteProcessor; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.DataInput; - import java.io.DataOutput; - import java.io.IOException; -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit - public class PacketDataSerializer extends ByteBuf { - - private final ByteBuf a; -+ public java.util.Locale adventure$locale; // Paper - - public PacketDataSerializer(ByteBuf bytebuf) { - this.a = bytebuf; -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - return IChatBaseComponent.ChatSerializer.a(this.e(262144)); - } - -+ // Paper start -+ public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { -+ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); -+ } -+ // Paper end -+ - public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { -- return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); -+ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment -+ return this.writeUtf(PaperAdventure.asJsonString(ichatbasecomponent, this.adventure$locale), 262144); // Paper - } - - public > T a(Class oclass) { -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - return this.a(s, 32767); - } - -+ public PacketDataSerializer writeUtf(final String string, final int maxLength) { return this.a(string, maxLength); } // Paper - OBFHELPER - public PacketDataSerializer a(String s, int i) { - byte[] abyte = s.getBytes(StandardCharsets.UTF_8); - -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -0,0 +0,0 @@ package net.minecraft.network; - import io.netty.buffer.ByteBuf; - import io.netty.channel.ChannelHandlerContext; - import io.netty.handler.codec.MessageToByteEncoder; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.io.IOException; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -@@ -0,0 +0,0 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw new IOException("Can't serialize unregistered packet"); - } else { - PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf); -+ packetdataserializer.adventure$locale = channelhandlercontext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper - - packetdataserializer.d(integer); - -diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -+++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -@@ -0,0 +0,0 @@ - package net.minecraft.network.chat; - -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; - import com.google.gson.JsonArray; -@@ -0,0 +0,0 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { - - private IChatBaseComponent a; -+ public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot - private ChatMessageType b; - private UUID c; -@@ -0,0 +0,0 @@ public class PacketPlayOutChat implements Packet { - - @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { -+ // Paper start -+ if (this.adventure$message != null) { -+ packetdataserializer.writeComponent(this.adventure$message); -+ } else -+ // Paper end - // Spigot start - if (components != null) { - packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutPlayerListHeaderFooter.java -@@ -0,0 +0,0 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet 0 && flag) { // TODO: allow plugins to override? -- IChatBaseComponent ichatbasecomponent; -- if (deathMessage.equals(deathmessage)) { -- ichatbasecomponent = this.getCombatTracker().getDeathMessage(); -- } else { -- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); -- } -+ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override? -+ IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure - - this.playerConnection.a((Packet) (new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent)), (future) -> { - if (!future.isSuccess()) { -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.a(ichatbasecomponent, ChatMessageType.SYSTEM, uuid); - } - -+ public void sendMessage(final IChatBaseComponent message, final ChatMessageType type, final UUID sender) { this.a(message, type, sender); } // Paper - OBFHELPER - public void a(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { - this.playerConnection.a((Packet) (new PacketPlayOutChat(ichatbasecomponent, chatmessagetype, uuid)), (future) -> { - if (!future.isSuccess() && (chatmessagetype == ChatMessageType.GAME_INFO || chatmessagetype == ChatMessageType.SYSTEM)) { -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { - // CraftBukkit start - if (getMainHand() != packetplayinsettings.getMainHand()) { -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.server.server.getPluginManager().callEvent(event); - } - this.locale = packetplayinsettings.locale; -+ // Paper start -+ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale); -+ this.playerConnection.networkManager.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); -+ // Paper end - this.clientViewDistance = packetplayinsettings.viewDistance; - // CraftBukkit end - this.bY = packetplayinsettings.d(); -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - - // CraftBukkit start - import net.minecraft.network.chat.ChatComponentText; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.event.player.AsyncPlayerPreLoginEvent; - import org.bukkit.event.player.PlayerPreLoginEvent; -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { - final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId); - if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) { -- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage()); -+ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure - } - Waitable waitable = new Waitable() { - @Override -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - - LoginListener.this.server.processQueue.add(waitable); - if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(event.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return; - } - } else { - if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { -- disconnect(asyncEvent.getKickMessage()); -+ disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure - return; - } - } -diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -@@ -0,0 +0,0 @@ public class PacketStatusListener implements PacketStatusInListener { - CraftIconCache icon = minecraftServer.server.getServerIcon(); - - ServerListPingEvent() { -- super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.getMotd(), minecraftServer.getPlayerList().getMaxPlayers()); -+ super(((InetSocketAddress) networkManager.getSocketAddress()).getAddress(), minecraftServer.server.motd(), minecraftServer.getPlayerList().getMaxPlayers()); // Paper - Adventure - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.ChatProcessor; // Paper -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.concurrent.ExecutionException; - import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - import net.minecraft.network.protocol.game.PacketPlayOutAttachEntity; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - return this.minecraftServer.a(this.player.getProfile()); - } - -- // CraftBukkit start -- @Deprecated -- public void disconnect(IChatBaseComponent ichatbasecomponent) { -- disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); -+ public void disconnect(String s) { -+ // Paper start -+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); - } -- // CraftBukkit end - -- public void disconnect(String s) { -+ public void disconnect(final IChatBaseComponent reason) { -+ this.disconnect(PaperAdventure.asAdventure(reason)); -+ } -+ -+ public void disconnect(net.kyori.adventure.text.Component reason) { -+ // Paper end - // CraftBukkit start - fire PlayerKickEvent - if (this.processedDisconnect) { - return; - } -- String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; -+ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure - -- PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), s, leaveMessage); -+ PlayerKickEvent event = new PlayerKickEvent(this.server.getPlayer(this.player), reason, leaveMessage); // Paper - Adventure - - if (this.server.getServer().isRunning()) { - this.server.getPluginManager().callEvent(event); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - return; - } - // Send the possibly modified leave message -- s = event.getReason(); -- final IChatBaseComponent ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; -+ final IChatBaseComponent ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure - // CraftBukkit end - - this.networkManager.sendPacket(new PacketPlayOutKickDisconnect(ichatbasecomponent), (future) -> { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - */ - - this.player.p(); -- String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); -- if ((quitMessage != null) && (quitMessage.length() > 0)) { -- this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); -+ // Paper start - Adventure -+ net.kyori.adventure.text.Component quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); -+ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { -+ this.minecraftServer.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); -+ // Paper end - } - // CraftBukkit end - ITextFilter itextfilter = this.player.Q(); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { - // Do nothing, this is coming from a plugin -- } else { -- Player player = this.getPlayer(); -+ // Paper start -+ } else if (true) { -+ final ChatProcessor cp = new ChatProcessor(this.minecraftServer, this.player, s, async); -+ cp.process(); -+ // Paper end -+ } else if (false) { // Paper -+ Player player = this.getPlayer(); // Paper - AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer)); - this.server.getPluginManager().callEvent(event); - -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - return; - } - -- // CraftBukkit start -- Player player = this.server.getPlayer(this.player); -- int x = packetplayinupdatesign.b().getX(); -- int y = packetplayinupdatesign.b().getY(); -- int z = packetplayinupdatesign.b().getZ(); -- String[] lines = new String[4]; -+ // CraftBukkit start // Paper start - Adventure -+ List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines[i] = EnumChatFormat.a(new ChatComponentText(EnumChatFormat.a((String) list.get(i))).getString()); -+ lines.add(net.kyori.adventure.text.Component.text(list.get(i))); - } -- SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.server.getPlayer(this.player), lines); -+ SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); -+ for (int i = 0; i < 4; i++) { -+ tileentitysign.a(i, PaperAdventure.asVanilla(event.line(i))); -+ } -+ // Paper end - tileentitysign.isEditable = false; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import com.mojang.authlib.GameProfile; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; - import java.io.File; - import java.net.SocketAddress; - import java.text.SimpleDateFormat; -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - // CraftBukkit start - chatmessage.a(EnumChatFormat.YELLOW); -- String joinMessage = CraftChatMessage.fromComponent(chatmessage); -+ IChatBaseComponent joinMessage = chatmessage; // Paper - Adventure - - playerconnection.a(entityplayer.locX(), entityplayer.locY(), entityplayer.locZ(), entityplayer.yaw, entityplayer.pitch); - this.players.add(entityplayer); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - - // CraftBukkit start -- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(entityplayer), joinMessage); -+ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); - - if (!entityplayer.playerConnection.networkManager.isConnected()) { - return; - } - -- joinMessage = playerJoinEvent.getJoinMessage(); -+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - -- if (joinMessage != null && joinMessage.length() > 0) { -- for (IChatBaseComponent line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { -- server.getPlayerList().sendAll(new PacketPlayOutChat(line, ChatMessageType.SYSTEM, SystemUtils.b)); -- } -+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -+ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -+ server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure - } - // CraftBukkit end - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - } - -- public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string -+ public net.kyori.adventure.text.Component disconnect(EntityPlayer entityplayer) { // Paper - return Component - WorldServer worldserver = entityplayer.getWorldServer(); - - entityplayer.a(StatisticList.LEAVE_GAME); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.closeInventory(); - } - -- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getName() + " left the game"); -+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.getQuitMessage(); // CraftBukkit -+ return playerQuitEvent.quitMessage(); // Paper - Adventure - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - // return chatmessage; -- if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); // Spigot -+ if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure - } else if (!this.isWhitelisted(gameprofile)) { - chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure - } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { - IpBanEntry ipbanentry = this.l.get(socketaddress); - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - // return chatmessage; -- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage)); -+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - } else { - // return this.players.size() >= this.maxPlayers && !this.f(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; - if (this.players.size() >= this.maxPlayers && !this.f(gameprofile)) { -- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot -+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure - } - } - - cserver.getPluginManager().callEvent(event); - if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { -- loginlistener.disconnect(event.getKickMessage()); -+ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure - return null; - } - return entity; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - public void shutdown() { - // CraftBukkit start - disconnect safely - for (EntityPlayer player : this.players) { -- player.playerConnection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message -+ player.playerConnection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/BossBattle.java b/src/main/java/net/minecraft/world/BossBattle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/BossBattle.java -+++ b/src/main/java/net/minecraft/world/BossBattle.java -@@ -0,0 +0,0 @@ - package net.minecraft.world; - -+import io.papermc.paper.adventure.PaperAdventure; - import java.util.UUID; - import net.minecraft.EnumChatFormat; - import net.minecraft.network.chat.IChatBaseComponent; -@@ -0,0 +0,0 @@ public abstract class BossBattle { - protected boolean e; - protected boolean f; - protected boolean g; -+ public net.kyori.adventure.bossbar.BossBar adventure; // Paper - - public BossBattle(UUID uuid, IChatBaseComponent ichatbasecomponent, BossBattle.BarColor bossbattle_barcolor, BossBattle.BarStyle bossbattle_barstyle) { - this.h = uuid; -@@ -0,0 +0,0 @@ public abstract class BossBattle { - } - - public IChatBaseComponent j() { -+ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.name()); // Paper - return this.title; - } - - public void a(IChatBaseComponent ichatbasecomponent) { -+ if (this.adventure != null) this.adventure.name(PaperAdventure.asAdventure(ichatbasecomponent)); // Paper - this.title = ichatbasecomponent; - } - - public float getProgress() { -+ if (this.adventure != null) return this.adventure.progress(); // Paper - return this.b; - } - - public void a(float f) { -+ if (this.adventure != null) this.adventure.progress(f); // Paper - this.b = f; - } - - public BossBattle.BarColor l() { -+ if (this.adventure != null) return PaperAdventure.asVanilla(this.adventure.color()); // Paper - return this.color; - } - - public void a(BossBattle.BarColor bossbattle_barcolor) { -+ if(this.adventure != null) this.adventure.color(PaperAdventure.asAdventure(bossbattle_barcolor)); // Paper - this.color = bossbattle_barcolor; - } - - public BossBattle.BarStyle m() { -+ if(this.adventure != null) return PaperAdventure.asVanilla(this.adventure.overlay()); // Paper - return this.style; - } - - public void a(BossBattle.BarStyle bossbattle_barstyle) { -+ if(this.adventure != null) this.adventure.overlay(PaperAdventure.asAdventure(bossbattle_barstyle)); // Paper - this.style = bossbattle_barstyle; - } - - public boolean isDarkenSky() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN); // Paper - return this.e; - } - - public BossBattle a(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.DARKEN_SCREEN, flag); // Paper - this.e = flag; - return this; - } - - public boolean isPlayMusic() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC); // Paper - return this.f; - } - - public BossBattle b(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.PLAY_BOSS_MUSIC, flag); // Paper - this.f = flag; - return this; - } - - public BossBattle c(boolean flag) { -+ if(this.adventure != null) PaperAdventure.setFlag(this.adventure, net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG, flag); // Paper - this.g = flag; - return this; - } - - public boolean isCreateFog() { -+ if(this.adventure != null) return this.adventure.hasFlag(net.kyori.adventure.bossbar.BossBar.Flag.CREATE_WORLD_FOG); // Paper - return this.g; - } - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - } - // CraftBukkit end - -+ public IChatBaseComponent displayName() { return this.C(); } // Paper - OBFHELPER - public IChatBaseComponent C() { - IChatMutableComponent ichatmutablecomponent = (new ChatComponentText("")).addSibling(this.getName()); - -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -0,0 +0,0 @@ public abstract class Enchantment { - return this.f(); - } - -+ public final IChatBaseComponent getTranslationComponentForLevel(int level) { return this.d(level); } // Paper - OBFHELPER - public IChatBaseComponent d(int i) { - ChatMessage chatmessage = new ChatMessage(this.g()); - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - // CraftBukkit start -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import java.util.UUID; - - import org.bukkit.craftbukkit.CraftServer; -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - - if (cursor.isVisible()) { -- icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); -+ icons.add(new MapIcon(MapIcon.Type.a(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper start - public int broadcastMessage(String message) { -- return broadcast(message, BROADCAST_CHANNEL_USERS); -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); -+ // Paper end - } - - public Player getPlayer(final EntityPlayer entity) { -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return configuration.getInt("settings.spawn-radius", -1); - } - -+ // Paper start - @Override -+ public net.kyori.adventure.text.Component shutdownMessage() { -+ String msg = getShutdownMessage(); -+ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null; -+ } -+ // Paper end -+ @Override -+ @Deprecated // Paper - public String getShutdownMessage() { - return configuration.getString("settings.shutdown-message"); - } -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - - @Override -+ @Deprecated // Paper - public int broadcast(String message, String permission) { -+ // Paper start - Adventure -+ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission); -+ } -+ -+ @Override -+ public int broadcast(net.kyori.adventure.text.Component message) { -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); -+ } -+ -+ @Override -+ public int broadcast(net.kyori.adventure.text.Component message, String permission) { -+ // Paper end - Set recipients = new HashSet<>(); - for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { - if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - } - -- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); -+ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure - getPluginManager().callEvent(broadcastMessageEvent); - - if (broadcastMessageEvent.isCancelled()) { - return 0; - } - -- message = broadcastMessageEvent.getMessage(); -+ message = broadcastMessageEvent.message(); // Paper - Adventure - - for (CommandSender recipient : recipients) { - recipient.sendMessage(message); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return CraftInventoryCreator.INSTANCE.createInventory(owner, size); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException { -+ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); -+ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException { - Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")"); - return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title); - } - -+ // Paper start -+ @Override -+ public Merchant createMerchant(net.kyori.adventure.text.Component title) { -+ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); -+ } -+ // Paper end - @Override -+ @Deprecated // Paper - public Merchant createMerchant(String title) { - return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); - } -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return Thread.currentThread().equals(console.serverThread) || console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog) - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component motd() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.ChatComponentText(console.getMotd())); -+ } -+ // Paper end - @Override - public String getMotd() { - return console.getMotd(); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return null; - } - } -+ -+ // Paper start -+ private Iterable adventure$audiences; -+ @Override -+ public Iterable audiences() { -+ if (this.adventure$audiences == null) { -+ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers()); -+ } -+ return this.adventure$audiences; -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - public static boolean useConsole = true; - - public static void main(String[] args) { -+ // Paper start -+ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected"); -+ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) { -+ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true)); -+ } -+ // Paper end - // Todo: Installation script - OptionParser parser = new OptionParser() { - { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -0,0 +0,0 @@ public class CraftBeacon extends CraftBlockEntityState impleme - this.getSnapshot().secondaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null; - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final TileEntityBeacon be = this.getSnapshot(); -+ return be.customName != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.customName) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - TileEntityBeacon beacon = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java -@@ -0,0 +0,0 @@ public abstract class CraftContainer extends Craf - this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final T be = this.getSnapshot(); -+ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public String getCustomName() { - T container = this.getSnapshot(); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java -@@ -0,0 +0,0 @@ public class CraftEnchantingTable extends CraftBlockEntityState implements Sign { - - // Lazily initialized only if requested: -- private String[] originalLines = null; -- private String[] lines = null; -+ // Paper start -+ private java.util.ArrayList originalLines = null; // ArrayList for RandomAccess -+ private java.util.ArrayList lines = null; // ArrayList for RandomAccess -+ // Paper end - - public CraftSign(final Block block) { - super(block, TileEntitySign.class); -@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockEntityState implements - super(material, te); - } - -+ // Paper start - @Override -- public String[] getLines() { -- if (lines == null) { -- // Lazy initialization: -- TileEntitySign sign = this.getSnapshot(); -- lines = new String[sign.lines.length]; -- System.arraycopy(revertComponents(sign.lines), 0, lines, 0, lines.length); -- originalLines = new String[lines.length]; -- System.arraycopy(lines, 0, originalLines, 0, originalLines.length); -+ public java.util.List lines() { -+ this.loadLines(); -+ return this.lines; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component line(int index) { -+ this.loadLines(); -+ return this.lines.get(index); -+ } -+ -+ @Override -+ public void line(int index, net.kyori.adventure.text.Component line) { -+ this.loadLines(); -+ this.lines.set(index, line); -+ } -+ -+ private void loadLines() { -+ if (lines != null) { -+ return; - } -- return lines; -+ -+ // Lazy initialization: -+ TileEntitySign sign = this.getSnapshot(); -+ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.lines)); -+ originalLines = new java.util.ArrayList<>(lines); -+ } -+ // Paper end -+ @Override -+ public String[] getLines() { -+ this.loadLines(); -+ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper - } - - @Override - public String getLine(int index) throws IndexOutOfBoundsException { -- return getLines()[index]; -+ this.loadLines(); -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper - } - - @Override - public void setLine(int index, String line) throws IndexOutOfBoundsException { -- getLines()[index] = line; -+ this.loadLines(); -+ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockEntityState implements - super.applyTo(sign); - - if (lines != null) { -- for (int i = 0; i < lines.length; i++) { -- String line = (lines[i] == null) ? "" : lines[i]; -- if (line.equals(originalLines[i])) { -+ // Paper start -+ for (int i = 0; i < this.lines.size(); ++i) { -+ net.kyori.adventure.text.Component component = this.lines.get(i); -+ net.kyori.adventure.text.Component origComp = this.originalLines.get(i); -+ if (component.equals(origComp)) { - continue; // The line contents are still the same, skip. - } -- sign.lines[i] = CraftChatMessage.fromString(line)[0]; -+ sign.lines[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component); - } -+ // Paper end - } - } - -+ // Paper start -+ public static IChatBaseComponent[] sanitizeLines(java.util.List lines) { -+ IChatBaseComponent[] components = new IChatBaseComponent[4]; -+ for (int i = 0; i < 4; i++) { -+ if (i < lines.size() && lines.get(i) != null) { -+ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i)); -+ } else { -+ components[i] = new ChatComponentText(""); -+ } -+ } -+ return components; -+ } -+ // Paper end - public static IChatBaseComponent[] sanitizeLines(String[] lines) { - IChatBaseComponent[] components = new IChatBaseComponent[4]; - -diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java -@@ -0,0 +0,0 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co - public boolean isConversing() { - return conversationTracker.isConversing(); - } -+ -+ // Paper start -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message))); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -0,0 +0,0 @@ public class CraftEnchantment extends Enchantment { - CraftEnchantment ench = (CraftEnchantment) other; - return !target.isCompatible(ench.target); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName(int level) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); -+ } -+ // Paper end - - public net.minecraft.world.item.enchantment.Enchantment getHandle() { - return target; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return getHandle().getVehicle().getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component customName() { -+ final IChatBaseComponent name = this.getHandle().getCustomName(); -+ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; -+ } -+ -+ @Override -+ public void customName(final net.kyori.adventure.text.Component customName) { -+ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null); -+ } -+ // Paper end -+ - @Override - public void setCustomName(String name) { - // sane limit for name length -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - container = CraftEventFactory.callInventoryOpenEvent(player, container); - if (container == null) return; - -- String title = container.getBukkitView().getTitle(); -+ //String title = container.getBukkitView().getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -+ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().activeContainer = container; - getHandle().activeContainer.addSlotListener(player); - } -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - // Now open the window - Containers windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); -- String title = inventory.getTitle(); -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); -+ -+ //String title = inventory.getTitle(); // Paper - comment -+ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper -+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper -+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -+ player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.activeContainer = container; - player.activeContainer.addSlotListener(player); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getDisplayName() { -+ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper - return getHandle().displayName; - } - - @Override - public void setDisplayName(final String name) { -+ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper - getHandle().displayName = name == null ? getName() : name; - } - -+ // Paper start -+ @Override -+ public void playerListName(net.kyori.adventure.text.Component name) { -+ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name); -+ for (EntityPlayer player : server.getHandle().players) { -+ if (player.getBukkitEntity().canSee(this)) { -+ player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle())); -+ } -+ } -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListName() { -+ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName); -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListHeader() { -+ return playerListHeader; -+ } -+ @Override -+ public net.kyori.adventure.text.Component playerListFooter() { -+ return playerListFooter; -+ } -+ // Paper end - @Override - public String getPlayerListName() { - return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - } - -- private IChatBaseComponent playerListHeader; -- private IChatBaseComponent playerListFooter; -+ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure -+ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure - - @Override - public String getPlayerListHeader() { -- return (playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); -+ return (playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); // Paper - Adventure - } - - @Override - public String getPlayerListFooter() { -- return (playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); -+ return (playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure - } - - @Override - public void setPlayerListHeader(String header) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListFooter(String footer) { -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - - @Override - public void setPlayerListHeaderFooter(String header, String footer) { -- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true); -- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true); -+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure -+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure - updatePlayerListHeaderFooter(); - } - -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (getHandle().playerConnection == null) return; - - PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); -- packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : this.playerListHeader; -- packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : this.playerListFooter; -+ packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader); // Paper - Adventure -+ packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter); // Paper - Adventure - getHandle().playerConnection.sendPacket(packet); - } - -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().playerConnection.disconnect(message == null ? "" : message); - } - -+ // Paper start -+ @Override -+ public void kick(final net.kyori.adventure.text.Component message) { -+ org.spigotmc.AsyncCatcher.catchOp("player kick"); -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ if (connection != null) { -+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); -+ } -+ } -+ // Paper end -+ - @Override - public void setCompassTarget(Location loc) { - if (getHandle().playerConnection == null) return; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().playerConnection.sendPacket(packet); - } - -+ // Paper start -+ @Override -+ public void sendSignChange(Location loc, List lines) { -+ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK); -+ } -+ @Override -+ public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { -+ if (getHandle().playerConnection == null) { -+ return; -+ } -+ if (lines == null) { -+ lines = new java.util.ArrayList<>(4); -+ } -+ Validate.notNull(loc, "Location cannot be null"); -+ Validate.notNull(dyeColor, "DyeColor cannot be null"); -+ if (lines.size() < 4) { -+ throw new IllegalArgumentException("Must have at least 4 lines"); -+ } -+ IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); -+ this.sendSignChange0(components, loc, dyeColor); -+ } -+ -+ private void sendSignChange0(IChatBaseComponent[] components, Location loc, DyeColor dyeColor) { -+ TileEntitySign sign = new TileEntitySign(); -+ sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); -+ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); -+ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); -+ -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); -+ } -+ // Paper end - @Override - public void sendSignChange(Location loc, String[] lines) { - sendSignChange(loc, lines, DyeColor.BLACK); -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); -- TileEntitySign sign = new TileEntitySign(); -+ /*TileEntitySign sign = new TileEntitySign(); // Paper - sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); - sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData())); - System.arraycopy(components, 0, sign.lines, 0, sign.lines.length); - -- getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket());*/ // Paper -+ this.sendSignChange0(components, loc, dyeColor); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return (getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : getHandle().clientViewDistance; - } - -+ // Paper start -+ @Override -+ public java.util.Locale locale() { -+ return getHandle().adventure$locale; -+ } -+ // Paper end - @Override - public int getPing() { - return getHandle().ping; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getInventory().setItemInMainHand(hand); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return this.getHandle().adventure$displayName; -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName()); -+ this.getHandle().displayName = null; -+ } -+ -+ @Override -+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) { -+ final PacketPlayOutChat packet = new PacketPlayOutChat(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatMessageType.CHAT : net.minecraft.network.chat.ChatMessageType.SYSTEM, identity.uuid()); -+ packet.adventure$message = message; -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ -+ @Override -+ public void sendActionBar(final net.kyori.adventure.text.Component message) { -+ final PacketPlayOutTitle packet = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, null); -+ packet.adventure$text = message; -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ -+ @Override -+ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) { -+ this.playerListHeader = header; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) { -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ @Override -+ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) { -+ this.playerListHeader = header; -+ this.playerListFooter = footer; -+ this.adventure$sendPlayerListHeaderAndFooter(); -+ } -+ -+ private void adventure$sendPlayerListHeaderAndFooter() { -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ if (connection == null) return; -+ final PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); -+ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader; -+ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter; -+ connection.sendPacket(packet); -+ } -+ -+ @Override -+ public void showTitle(final net.kyori.adventure.title.Title title) { -+ final PlayerConnection connection = this.getHandle().playerConnection; -+ final net.kyori.adventure.title.Title.Times times = title.times(); -+ if (times != null) { -+ connection.sendPacket(new PacketPlayOutTitle(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); -+ } -+ final PacketPlayOutTitle sp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, null); -+ sp.adventure$text = title.subtitle(); -+ connection.sendPacket(sp); -+ final PacketPlayOutTitle tp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, null); -+ tp.adventure$text = title.title(); -+ connection.sendPacket(tp); -+ } -+ -+ private static int ticks(final java.time.Duration duration) { -+ if (duration == null) { -+ return -1; -+ } -+ return (int) (duration.toMillis() / 50L); -+ } -+ -+ @Override -+ public void clearTitle() { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, null)); -+ } -+ -+ // resetTitle implemented above -+ -+ @Override -+ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this); -+ } -+ -+ @Override -+ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) { -+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound) { -+ final Vec3D pos = this.getHandle().getPositionVector(); -+ this.playSound(sound, pos.x, pos.y, pos.z); -+ } -+ -+ @Override -+ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) { -+ final MinecraftKey name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); -+ final java.util.Optional event = net.minecraft.core.IRegistry.SOUND_EVENT.getOptional(name); -+ if (event.isPresent()) { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch())); -+ } else { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutCustomSoundEffect(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3D(x, y, z), sound.volume(), sound.pitch())); -+ } -+ } -+ -+ @Override -+ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutStopSound( -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), -+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) -+ )); -+ } -+ -+ @Override -+ public void openBook(final net.kyori.adventure.inventory.Book book) { -+ final java.util.Locale locale = this.getHandle().adventure$locale; -+ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale); -+ final EntityPlayer player = this.getHandle(); -+ final PlayerConnection connection = player.playerConnection; -+ final net.minecraft.world.entity.player.PlayerInventory inventory = player.inventory; -+ final int slot = inventory.items.size() + inventory.itemInHandIndex; -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, item)); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return event; - } - -- public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, String deathMessage, boolean keepInventory) { -+ public static PlayerDeathEvent callPlayerDeathEvent(EntityPlayer victim, List drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure - CraftPlayer entity = victim.getBukkitEntity(); -- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage); -+ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -@@ -0,0 +0,0 @@ public class CraftEventFactory { - * Server methods - */ - public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) { -- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers); -+ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure - craftServer.getPluginManager().callEvent(event); - return event; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java -@@ -0,0 +0,0 @@ public class CraftContainer extends Container { - - private final InventoryView view; - private InventoryType cachedType; -+ private net.kyori.adventure.text.Component adventure$title; // Paper - private String cachedTitle; - private Container delegate; - private final int cachedSize; -@@ -0,0 +0,0 @@ public class CraftContainer extends Container { - IInventory top = ((CraftInventory) view.getTopInventory()).getInventory(); - PlayerInventory bottom = (PlayerInventory) ((CraftInventory) view.getBottomInventory()).getInventory(); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - cachedSize = getSize(); - setupSlots(top, bottom, player); - } -@@ -0,0 +0,0 @@ public class CraftContainer extends Container { - return inventory.getType(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); -@@ -0,0 +0,0 @@ public class CraftContainer extends Container { - - @Override - public boolean c(EntityHuman entityhuman) { -- if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { -+ if (cachedType == view.getType() && cachedSize == getSize() && this.adventure$title.equals(view.title())) { // Paper -+ //if (cachedType == view.getType() && cachedSize == getSize() && cachedTitle.equals(view.getTitle())) { // Paper - comment - return true; - } - // If the window type has changed for some reason, update the player -@@ -0,0 +0,0 @@ public class CraftContainer extends Container { - // as good a place as any to put something like this. - boolean typeChanged = (cachedType != view.getType()); - cachedType = view.getType(); -- cachedTitle = view.getTitle(); -+ this.adventure$title = view.title(); // Paper -+ if (this.adventure$title == null) this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(view.getTitle()); // Paper -+ //cachedTitle = view.getTitle(); // Paper - comment - if (view.getPlayer() instanceof CraftPlayer) { - CraftPlayer player = (CraftPlayer) view.getPlayer(); - Containers type = getNotchInventoryType(view.getTopInventory()); -@@ -0,0 +0,0 @@ public class CraftContainer extends Container { - setupSlots(top, bottom, player.getHandle()); - } - int size = getSize(); -- player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); -+ player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, io.papermc.paper.adventure.PaperAdventure.asVanilla(this.adventure$title))); // Paper -+ //player.getHandle().playerConnection.sendPacket(new PacketPlayOutOpenWindow(this.windowId, type, new ChatComponentText(cachedTitle))); // Paper - comment - player.updateInventory(); - } - return true; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java -@@ -0,0 +0,0 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, type)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, type, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) { - super(new MinecraftInventory(owner, type, title)); - } -@@ -0,0 +0,0 @@ public class CraftInventoryCustom extends CraftInventory { - super(new MinecraftInventory(owner, size)); - } - -+ // Paper start -+ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ super(new MinecraftInventory(owner, size, title)); -+ } -+ // Paper end -+ - public CraftInventoryCustom(InventoryHolder owner, int size, String title) { - super(new MinecraftInventory(owner, size, title)); - } -@@ -0,0 +0,0 @@ public class CraftInventoryCustom extends CraftInventory { - private int maxStack = MAX_STACK; - private final List viewers; - private final String title; -+ private final net.kyori.adventure.text.Component adventure$title; // Paper - private InventoryType type; - private final InventoryHolder owner; - -+ // Paper start -+ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ this(owner, type.getDefaultSize(), title); -+ this.type = type; -+ } -+ // Paper end -+ - public MinecraftInventory(InventoryHolder owner, InventoryType type) { - this(owner, type.getDefaultSize(), type.getDefaultTitle()); - this.type = type; -@@ -0,0 +0,0 @@ public class CraftInventoryCustom extends CraftInventory { - Validate.notNull(title, "Title cannot be null"); - this.items = NonNullList.a(size, ItemStack.b); - this.title = title; -+ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); - this.viewers = new ArrayList(); - this.owner = owner; - this.type = InventoryType.CHEST; - } - -+ // Paper start -+ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.items = NonNullList.a(size, ItemStack.b); -+ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.adventure$title = title; -+ this.viewers = new ArrayList(); -+ this.owner = owner; -+ this.type = InventoryType.CHEST; -+ } -+ // Paper end -+ - @Override - public int getSize() { - return items.size(); -@@ -0,0 +0,0 @@ public class CraftInventoryCustom extends CraftInventory { - return null; - } - -+ // Paper start -+ public net.kyori.adventure.text.Component title() { -+ return this.adventure$title; -+ } -+ // Paper end -+ - public String getTitle() { - return title; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java -@@ -0,0 +0,0 @@ public class CraftInventoryView extends InventoryView { - return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle()); -+ } -+ // Paper end -+ - @Override - public String getTitle() { - return CraftChatMessage.fromComponent(container.getTitle()); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory { - public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException { - return ((CraftMetaItem) meta).updateMaterial(material); - } -+ -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { -+ final net.minecraft.nbt.NBTTagCompound tag = CraftItemStack.asNMSCopy(item).getTag(); -+ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag)))); -+ } -+ -+ @Override -+ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -@@ -0,0 +0,0 @@ import org.apache.commons.lang.Validate; - - public class CraftMerchantCustom extends CraftMerchant { - -+ @Deprecated // Paper - Adventure - public CraftMerchantCustom(String title) { - super(new MinecraftMerchant(title)); - getMerchant().craftMerchant = this; - } -+ // Paper start -+ public CraftMerchantCustom(net.kyori.adventure.text.Component title) { -+ super(new MinecraftMerchant(title)); -+ getMerchant().craftMerchant = this; -+ } -+ // Paper end - - @Override - public String toString() { -@@ -0,0 +0,0 @@ public class CraftMerchantCustom extends CraftMerchant { - private World tradingWorld; - protected CraftMerchant craftMerchant; - -+ @Deprecated // Paper - Adventure - public MinecraftMerchant(String title) { - Validate.notNull(title, "Title cannot be null"); - this.title = new ChatComponentText(title); - } -+ // Paper start -+ public MinecraftMerchant(net.kyori.adventure.text.Component title) { -+ Validate.notNull(title, "Title cannot be null"); -+ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); -+ } -+ // Paper end - - @Override - public CraftMerchant getCraftMerchant() { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.inventory; - - import com.google.common.collect.ImmutableList; --import com.google.common.collect.ImmutableMap.Builder; - import com.google.common.collect.Lists; -+ -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.ArrayList; - import java.util.Arrays; - import java.util.List; -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.CraftChatMessage; - import org.bukkit.craftbukkit.util.CraftMagicNumbers; - import org.bukkit.inventory.meta.BookMeta; - import org.bukkit.inventory.meta.BookMeta.Generation; -+import org.checkerframework.checker.nullness.qual.NonNull; - - // Spigot start - import static org.spigotmc.ValidateUtils.*; -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - this.generation = (generation == null) ? null : generation.ordinal(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component title() { -+ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) { -+ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component author() { -+ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author); -+ } -+ -+ @Override -+ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) { -+ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author)); -+ return this; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.Component page(final int page) { -+ Validate.isTrue(isValidPage(page), "Invalid page number"); -+ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1)); -+ } -+ -+ @Override -+ public void page(final int page, net.kyori.adventure.text.Component data) { -+ if (!isValidPage(page)) { -+ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size()); -+ } -+ if (data == null) { -+ data = net.kyori.adventure.text.Component.empty(); -+ } -+ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data)); -+ } -+ -+ @Override -+ public List pages() { -+ if (this.pages == null) return ImmutableList.of(); -+ if (this instanceof CraftMetaBookSigned) -+ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList()); -+ else -+ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList()); -+ } -+ -+ @Override -+ public BookMeta pages(List pages) { -+ if (this.pages != null) this.pages.clear(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ addPages(page); -+ } -+ return this; -+ } -+ -+ @Override -+ public BookMeta pages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages != null) this.pages.clear(); -+ addPages(pages); -+ return this; -+ } -+ -+ @Override -+ public void addPages(net.kyori.adventure.text.Component... pages) { -+ if (this.pages == null) this.pages = new ArrayList<>(); -+ for (net.kyori.adventure.text.Component page : pages) { -+ if (this.pages.size() >= MAX_PAGES) { -+ return; -+ } -+ -+ if (page == null) { -+ page = net.kyori.adventure.text.Component.empty(); -+ } -+ -+ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page)); -+ } -+ } -+ -+ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List pages) { -+ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK)); -+ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); -+ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author); -+ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList()); -+ } -+ -+ static final class CraftMetaBookBuilder implements BookMetaBuilder { -+ private net.kyori.adventure.text.Component title = null; -+ private net.kyori.adventure.text.Component author = null; -+ private final List pages = new java.util.ArrayList<>(); -+ -+ @Override -+ public BookMetaBuilder title(net.kyori.adventure.text.Component title) { -+ this.title = title; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder author(net.kyori.adventure.text.Component author) { -+ this.author = author; -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) { -+ this.pages.add(page); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) { -+ java.util.Collections.addAll(this.pages, pages); -+ return this; -+ } -+ -+ @Override -+ public BookMetaBuilder pages(java.util.Collection pages) { -+ this.pages.addAll(pages); -+ return this; -+ } -+ -+ @Override -+ public BookMeta build() { -+ return new CraftMetaBook(title, author, pages); -+ } -+ } -+ -+ @Override -+ public BookMetaBuilder toBuilder() { -+ return new CraftMetaBookBuilder(); -+ } -+ -+ // Paper end - @Override - public String getPage(final int page) { - Validate.isTrue(isValidPage(page), "Invalid page number"); -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - - if (hasTitle()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.inventory; - --import com.google.common.collect.ImmutableMap.Builder; -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.Map; - import net.minecraft.nbt.NBTTagCompound; - import org.bukkit.Material; -@@ -0,0 +0,0 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { - } - - @Override -- Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { - super.serialize(builder); - return builder; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName); -+ } -+ -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName); -+ } -+ // Paper end -+ - @Override - public String getDisplayName() { - return CraftChatMessage.fromJSONComponent(displayName); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore != null && !this.lore.isEmpty(); - } - -+ // Paper start -+ @Override -+ public List lore() { -+ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null; -+ } -+ -+ @Override -+ public void lore(final List lore) { -+ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasRepairCost() { - return repairCost > 0; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java -@@ -0,0 +0,0 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(holder, type); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, type, title); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - return new CraftInventoryCustom(owner, type, title); -@@ -0,0 +0,0 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve - return new CraftInventoryCustom(owner, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) { -+ return new CraftInventoryCustom(owner, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder owner, int size, String title) { - return new CraftInventoryCustom(owner, size, title); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -0,0 +0,0 @@ public final class CraftInventoryCreator { - return converterMap.get(type).createInventory(holder, type); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end -+ return converterMap.get(type).createInventory(holder, type, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - return converterMap.get(type).createInventory(holder, type, title); - } -@@ -0,0 +0,0 @@ public final class CraftInventoryCreator { - return DEFAULT_CONVERTER.createInventory(holder, size); - } - -+ // Paper start -+ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) { -+ return DEFAULT_CONVERTER.createInventory(holder, size, title); -+ } -+ // Paper end -+ - public Inventory createInventory(InventoryHolder holder, int size, String title) { - return DEFAULT_CONVERTER.createInventory(holder, size, title); - } -@@ -0,0 +0,0 @@ public final class CraftInventoryCreator { - - Inventory createInventory(InventoryHolder holder, InventoryType type); - -+ // Paper start -+ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title); -+ // Paper end -+ - Inventory createInventory(InventoryHolder holder, InventoryType type, String title); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java -@@ -0,0 +0,0 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return getInventory(getTileEntity()); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ IInventory te = getTileEntity(); -+ if (te instanceof TileEntityLootable) { -+ ((TileEntityLootable) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ -+ return getInventory(te); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - IInventory te = getTileEntity(); -@@ -0,0 +0,0 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return furnace; - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ IInventory tileEntity = getTileEntity(); -+ ((TileEntityFurnace) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { - IInventory tileEntity = getTileEntity(); -@@ -0,0 +0,0 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return new TileEntityBrewingStand(); - } - -+ // Paper start -+ @Override -+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { -+ // BrewingStand does not extend TileEntityLootable -+ IInventory tileEntity = getTileEntity(); -+ if (tileEntity instanceof TileEntityBrewingStand) { -+ ((TileEntityBrewingStand) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); -+ } -+ return getInventory(tileEntity); -+ } -+ // Paper end -+ - @Override - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - // BrewingStand does not extend TileEntityLootable -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java -@@ -0,0 +0,0 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective - return objective.getName(); - } - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ CraftScoreboard scoreboard = checkState(); -+ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ // Paper end - @Override - public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -0,0 +0,0 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException { - return registerNewObjective(name, criteria, name); - } -+ // Paper start -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) { -+ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER); -+ } -+ @Override -+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) { -+ if (displayName == null) { -+ displayName = net.kyori.adventure.text.Component.empty(); -+ } -+ Validate.notNull(name, "Objective name cannot be null"); -+ Validate.notNull(criteria, "Criteria cannot be null"); -+ Validate.notNull(displayName, "Display name cannot be null"); -+ Validate.notNull(renderType, "RenderType cannot be null"); -+ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); -+ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); -+ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -+ return new CraftObjective(this, objective); -+ } -+ // Paper end - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException { -@@ -0,0 +0,0 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - - @Override - public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException { -- Validate.notNull(name, "Objective name cannot be null"); -+ /*Validate.notNull(name, "Objective name cannot be null"); // Paper - Validate.notNull(criteria, "Criteria cannot be null"); - Validate.notNull(displayName, "Display name cannot be null"); - Validate.notNull(renderType, "RenderType cannot be null"); -@@ -0,0 +0,0 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); -- return new CraftObjective(this, objective); -+ return new CraftObjective(this, objective);*/ // Paper -+ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - return team.getName(); - } -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName()); -+ } -+ @Override -+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException { -+ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component prefix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPrefix()); -+ } -+ @Override -+ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException { -+ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix)); -+ } -+ @Override -+ public net.kyori.adventure.text.Component suffix() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getSuffix()); -+ } -+ @Override -+ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException { -+ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty(); -+ CraftScoreboard scoreboard = checkState(); -+ team.setSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix)); -+ } -+ @Override -+ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException { -+ CraftScoreboard scoreboard = checkState(); -+ if (team.getColor().getHexValue() == null) throw new IllegalStateException("Team colors must have hex values"); -+ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getHexValue()); -+ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor"); -+ return (net.kyori.adventure.text.format.NamedTextColor) color; -+ } -+ @Override -+ public void color(net.kyori.adventure.text.format.NamedTextColor color) { -+ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE; -+ CraftScoreboard scoreboard = checkState(); -+ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color)); -+ } -+ // Paper end - - @Override - public String getDisplayName() throws IllegalStateException { -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -0,0 +0,0 @@ public final class CraftChatMessage { - - public static String fromComponent(IChatBaseComponent component) { - if (component == null) return ""; -+ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted(); - StringBuilder out = new StringBuilder(); - - boolean hadFormat = false; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - - private CraftMagicNumbers() {} - -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() { -+ return io.papermc.paper.adventure.PaperAdventure.FLATTENER; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.GSON; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.PLAIN; -+ } -+ -+ @Override -+ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() { -+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC; -+ } -+ // Paper end -+ - public static IBlockData getBlock(MaterialData material) { - return getBlock(material.getItemType(), material.getData()); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java -@@ -0,0 +0,0 @@ public abstract class LazyHashSet implements Set { - return this.reference = makeReference(); - } - -- abstract Set makeReference(); -+ protected abstract Set makeReference(); // Paper - protected - - public boolean isLazy() { - return reference == null; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java -@@ -0,0 +0,0 @@ public class LazyPlayerSet extends LazyHashSet { - } - - @Override -- HashSet makeReference() { -+ protected HashSet makeReference() { // Paper - protected - if (reference != null) { - throw new IllegalStateException("Reference already created!"); - } -+ // Paper start -+ return makePlayerSet(this.server); -+ } -+ public static HashSet makePlayerSet(final MinecraftServer server) { -+ // Paper end - List players = server.getPlayerList().players; - HashSet reference = new HashSet(players.size()); - for (EntityPlayer player : players) { diff --git a/Spigot-Server-Patches/All-chunks-are-slime-spawn-chunks-toggle.patch b/Spigot-Server-Patches/All-chunks-are-slime-spawn-chunks-toggle.patch deleted file mode 100644 index 48cbaf37cf..0000000000 --- a/Spigot-Server-Patches/All-chunks-are-slime-spawn-chunks-toggle.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Thu, 3 Mar 2016 01:19:22 -0600 -Subject: [PATCH] All chunks are slime spawn chunks toggle - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableChestCatDetection() { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } -+ -+ public boolean allChunksAreSlimeChunks; -+ private void allChunksAreSlimeChunks() { -+ allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(blockposition); -- boolean flag = SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot -+ boolean flag = generatoraccess.getMinecraftWorld().paperConfig.allChunksAreSlimeChunks || SeededRandom.a(chunkcoordintpair.x, chunkcoordintpair.z, ((GeneratorAccessSeed) generatoraccess).getSeed(), generatoraccess.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper - - if (random.nextInt(10) == 0 && flag && blockposition.getY() < 40) { - return a(entitytypes, generatoraccess, enummobspawn, blockposition, random); diff --git a/Spigot-Server-Patches/Allow-Reloading-of-Command-Aliases.patch b/Spigot-Server-Patches/Allow-Reloading-of-Command-Aliases.patch deleted file mode 100644 index 173c14fab5..0000000000 --- a/Spigot-Server-Patches/Allow-Reloading-of-Command-Aliases.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Mon, 28 Nov 2016 10:21:52 -0500 -Subject: [PATCH] Allow Reloading of Command Aliases - -Reload the aliases stored in commands.yml - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); - } -+ -+ @Override -+ public boolean reloadCommandAliases() { -+ Set removals = getCommandAliases().keySet().stream() -+ .map(key -> key.toLowerCase(java.util.Locale.ENGLISH)) -+ .collect(java.util.stream.Collectors.toSet()); -+ getCommandMap().getKnownCommands().keySet().removeIf(removals::contains); -+ File file = getCommandsConfigFile(); -+ try { -+ commandsConfiguration.load(file); -+ } catch (FileNotFoundException ex) { -+ return false; -+ } catch (IOException | org.bukkit.configuration.InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Cannot load " + file, ex); -+ return false; -+ } -+ commandMap.registerServerAliases(); -+ return true; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Allow-Reloading-of-Custom-Permissions.patch b/Spigot-Server-Patches/Allow-Reloading-of-Custom-Permissions.patch deleted file mode 100644 index a2c4d63f75..0000000000 --- a/Spigot-Server-Patches/Allow-Reloading-of-Custom-Permissions.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William -Date: Fri, 18 Mar 2016 03:30:17 -0400 -Subject: [PATCH] Allow Reloading of Custom Permissions - -https://github.com/PaperMC/Paper/issues/49 - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - return this.adventure$audiences; - } -+ -+ @Override -+ public void reloadPermissions() { -+ pluginManager.clearPermissions(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ for (Plugin plugin : pluginManager.getPlugins()) { -+ for (Permission perm : plugin.getDescription().getPermissions()) { -+ try { -+ pluginManager.addPermission(perm); -+ } catch (IllegalArgumentException ex) { -+ getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); -+ } -+ } -+ } -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); -+ DefaultPermissions.registerCorePermissions(); -+ CraftDefaultPermissions.registerCorePermissions(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch b/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch deleted file mode 100644 index 03a45e81d4..0000000000 --- a/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch +++ /dev/null @@ -1,272 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Feb 2019 01:08:19 -0500 -Subject: [PATCH] Allow Saving of Oversized Chunks - -The Minecraft World Region File format has a hard cap of 1MB per chunk. -This is due to the fact that the header of the file format only allocates -a single byte for sector count, meaning a maximum of 256 sectors, at 4k per sector. - -This limit can be reached fairly easily with books, resulting in the chunk being unable -to save to the world. Worse off, is that nothing printed when this occured, and silently -performed a chunk rollback on next load. - -This leads to security risk with duplication and is being actively exploited. - -This patch catches the too large scenario, falls back and moves any large Entity -or Tile Entity into a new compound, and this compound is saved into a different file. - -On Chunk Load, we check for oversized status, and if so, we load the extra file and -merge the Entities and Tile Entities from the oversized chunk back into the level to -then be loaded as normal. - -Once a chunk is returned back to normal size, the oversized flag will clear, and no -extra data file will exist. - -This fix maintains compatability with all existing Anvil Region Format tools as it -does not alter the save format. They will just not know about the extra entities. - -This fix also maintains compatability if someone switches server jars to one without -this fix, as the data will remain in the oversized file. Once the server returns -to a jar with this fix, the data will be restored. - -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -0,0 +0,0 @@ public class NBTCompressedStreamTools { - - } - -+ public static NBTTagCompound readNBT(DataInput datainput) throws IOException { return a(datainput); } // Paper - OBFHELPER - public static NBTTagCompound a(DataInput datainput) throws IOException { - return a(datainput, NBTReadLimiter.a); - } -@@ -0,0 +0,0 @@ public class NBTCompressedStreamTools { - } - } - -+ public static void writeNBT(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { a(nbttagcompound, dataoutput); } // Paper - OBFHELPER - public static void a(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { - a((NBTBase) nbttagcompound, dataoutput); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -0,0 +0,0 @@ import java.nio.file.LinkOption; - import java.nio.file.Path; - import java.nio.file.StandardCopyOption; - import java.nio.file.StandardOpenOption; -+import java.util.zip.InflaterInputStream; // Paper -+ - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; -+import net.minecraft.nbt.NBTCompressedStreamTools; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.ChunkCoordIntPair; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - private final IntBuffer i; - @VisibleForTesting - protected final RegionFileBitSet freeSectors; -+ public final File file; // Paper - - public RegionFile(File file, File file1, boolean flag) throws IOException { - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - - public RegionFile(Path path, Path path1, RegionFileCompression regionfilecompression, boolean flag) throws IOException { - this.g = ByteBuffer.allocateDirect(8192); -+ this.file = path.toFile(); // Paper -+ initOversizedState(); // Paper - this.freeSectors = new RegionFileBitSet(); - this.f = regionfilecompression; - if (!Files.isDirectory(path1, new LinkOption[0])) { -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - void run() throws IOException; - } - -+ // Paper start -+ private final byte[] oversized = new byte[1024]; -+ private int oversizedCount = 0; -+ -+ private synchronized void initOversizedState() throws IOException { -+ File metaFile = getOversizedMetaFile(); -+ if (metaFile.exists()) { -+ final byte[] read = java.nio.file.Files.readAllBytes(metaFile.toPath()); -+ System.arraycopy(read, 0, oversized, 0, oversized.length); -+ for (byte temp : oversized) { -+ oversizedCount += temp; -+ } -+ } -+ } -+ -+ private static int getChunkIndex(int x, int z) { -+ return (x & 31) + (z & 31) * 32; -+ } -+ synchronized boolean isOversized(int x, int z) { -+ return this.oversized[getChunkIndex(x, z)] == 1; -+ } -+ synchronized void setOversized(int x, int z, boolean oversized) throws IOException { -+ final int offset = getChunkIndex(x, z); -+ boolean previous = this.oversized[offset] == 1; -+ this.oversized[offset] = (byte) (oversized ? 1 : 0); -+ if (!previous && oversized) { -+ oversizedCount++; -+ } else if (!oversized && previous) { -+ oversizedCount--; -+ } -+ if (previous && !oversized) { -+ File oversizedFile = getOversizedFile(x, z); -+ if (oversizedFile.exists()) { -+ oversizedFile.delete(); -+ } -+ } -+ if (oversizedCount > 0) { -+ if (previous != oversized) { -+ writeOversizedMeta(); -+ } -+ } else if (previous) { -+ File oversizedMetaFile = getOversizedMetaFile(); -+ if (oversizedMetaFile.exists()) { -+ oversizedMetaFile.delete(); -+ } -+ } -+ } -+ -+ private void writeOversizedMeta() throws IOException { -+ java.nio.file.Files.write(getOversizedMetaFile().toPath(), oversized); -+ } -+ -+ private File getOversizedMetaFile() { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); -+ } -+ -+ private File getOversizedFile(int x, int z) { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); -+ } -+ -+ synchronized NBTTagCompound getOversizedData(int x, int z) throws IOException { -+ File file = getOversizedFile(x, z); -+ try (DataInputStream out = new DataInputStream(new BufferedInputStream(new InflaterInputStream(new java.io.FileInputStream(file))))) { -+ return NBTCompressedStreamTools.readNBT((java.io.DataInput) out); -+ } -+ -+ } -+ // Paper end - class ChunkBuffer extends ByteArrayOutputStream { - - private final ChunkCoordIntPair b; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -0,0 +0,0 @@ import java.io.DataOutputStream; - import java.io.File; - import java.io.IOException; - import javax.annotation.Nullable; -+import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; - import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - } - } - -+ // Paper start -+ private static void printOversizedLog(String msg, File file, int x, int z) { -+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); -+ } -+ -+ private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; -+ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; -+ private static final int OVERZEALOUS_THRESHOLD = 1024; -+ private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; -+ private static void resetFilterThresholds() { -+ SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); -+ } -+ static { -+ resetFilterThresholds(); -+ } -+ -+ static boolean isOverzealous() { -+ return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; -+ } -+ -+ -+ private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException { -+ synchronized (regionfile) { -+ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { -+ NBTTagCompound oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); -+ NBTTagCompound chunk = NBTCompressedStreamTools.readNBT((DataInput) datainputstream); -+ if (oversizedData == null) { -+ return chunk; -+ } -+ NBTTagCompound oversizedLevel = oversizedData.getCompound("Level"); -+ NBTTagCompound level = chunk.getCompound("Level"); -+ -+ mergeChunkList(level, oversizedLevel, "Entities"); -+ mergeChunkList(level, oversizedLevel, "TileEntities"); -+ -+ chunk.set("Level", level); -+ -+ return chunk; -+ } catch (Throwable throwable) { -+ throwable.printStackTrace(); -+ throw throwable; -+ } -+ } -+ } -+ -+ private static void mergeChunkList(NBTTagCompound level, NBTTagCompound oversizedLevel, String key) { -+ NBTTagList levelList = level.getList(key, 10); -+ NBTTagList oversizedList = oversizedLevel.getList(key, 10); -+ -+ if (!oversizedList.isEmpty()) { -+ levelList.addAll(oversizedList); -+ level.set(key, levelList); -+ } -+ } -+ -+ private static int getNBTSize(NBTBase nbtBase) { -+ DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); -+ try { -+ nbtBase.write(test); -+ return test.size(); -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return 0; -+ } -+ } -+ -+ // Paper End -+ - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - } - // CraftBukkit end - DataInputStream datainputstream = regionfile.a(chunkcoordintpair); -+ // Paper start -+ if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { -+ printOversizedLog("Loading Oversized Chunk!", regionfile.file, chunkcoordintpair.x, chunkcoordintpair.z); -+ return readOversizedChunk(regionfile, chunkcoordintpair); -+ } -+ // Paper end - Throwable throwable = null; - - NBTTagCompound nbttagcompound; -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - - try { - NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); -+ regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; diff --git a/Spigot-Server-Patches/Allow-adding-items-to-BlockDropItemEvent.patch b/Spigot-Server-Patches/Allow-adding-items-to-BlockDropItemEvent.patch deleted file mode 100644 index 151563104d..0000000000 --- a/Spigot-Server-Patches/Allow-adding-items-to-BlockDropItemEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 20 Jan 2021 14:23:37 -0600 -Subject: [PATCH] Allow adding items to BlockDropItemEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - } - - public static void handleBlockDropItemEvent(Block block, BlockState state, EntityPlayer player, List items) { -- BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), Lists.transform(items, (item) -> (org.bukkit.entity.Item) item.getBukkitEntity())); -+ // Paper start -+ List list = new ArrayList<>(); -+ for (EntityItem item : items) { -+ list.add((Item) item.getBukkitEntity()); -+ } -+ BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); -+ // Paper end - Bukkit.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { -- for (EntityItem item : items) { -- item.world.addEntity(item); -+ // Paper start -+ for (Item bukkit : list) { -+ if (!bukkit.isValid()) { -+ Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); -+ item.world.addEntity(item); -+ } -+ } -+ } else { -+ for (Item bukkit : list) { -+ if (bukkit.isValid()) { -+ bukkit.remove(); -+ } - } -+ // Paper end - } - } - diff --git a/Spigot-Server-Patches/Allow-chests-to-be-placed-with-NBT-data.patch b/Spigot-Server-Patches/Allow-chests-to-be-placed-with-NBT-data.patch deleted file mode 100644 index f0dfa2fde8..0000000000 --- a/Spigot-Server-Patches/Allow-chests-to-be-placed-with-NBT-data.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Sep 2018 18:43:31 -0500 -Subject: [PATCH] Allow chests to be placed with NBT data - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - enuminteractionresult = EnumInteractionResult.FAIL; // cancel placement - // PAIL: Remove this when MC-99075 fixed - placeEvent.getPlayer().updateInventory(); -+ world.capturedTileEntities.clear(); // Paper - clear out tile entities as chests and such will pop loot - // revert back all captured blocks - for (BlockState blockstate : blocks) { - blockstate.update(true, false); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic - // CraftBukkit start - @Override - public boolean isFilteredNBT() { -- return true; -+ return false; // Paper - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/Allow-delegation-to-vanilla-chunk-gen.patch b/Spigot-Server-Patches/Allow-delegation-to-vanilla-chunk-gen.patch deleted file mode 100644 index 48120a2daf..0000000000 --- a/Spigot-Server-Patches/Allow-delegation-to-vanilla-chunk-gen.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger | Martin -Date: Wed, 29 Apr 2020 02:10:32 +0200 -Subject: [PATCH] Allow delegation to vanilla chunk gen - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkConverter.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - public class ChunkConverter { - - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ChunkConverter a = new ChunkConverter(); -+ public static final ChunkConverter a = new ChunkConverter(); public static ChunkConverter getEmptyConverter() { return a; } // Paper - obfhelper - private static final EnumDirection8[] c = EnumDirection8.values(); - private final EnumSet d; - private final int[][] e; -@@ -0,0 +0,0 @@ public class ChunkConverter { - if ((Integer) iblockdata.get(BlockProperties.an) >= j) { - generatoraccess.setTypeAndData(blockposition, (IBlockData) iblockdata.set(BlockProperties.an, j), 18); - if (i != 7) { -- EnumDirection[] aenumdirection = null.f; -+ EnumDirection[] aenumdirection = f; // Paper - decomp fix - int k = aenumdirection.length; - - for (int l = 0; l < k; ++l) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return new CraftChunkData(world); - } - -+ // Paper start -+ @Override -+ public ChunkGenerator.ChunkData createVanillaChunkData(World world, int x, int z) { -+ // get empty object -+ CraftChunkData data = (CraftChunkData) createChunkData(world); -+ // do bunch of vanilla shit -+ net.minecraft.server.level.WorldServer nmsWorld = ((CraftWorld) world).getHandle(); -+ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkCoordIntPair(x, z), net.minecraft.world.level.chunk.ChunkConverter.getEmptyConverter(), nmsWorld); -+ List list = new ArrayList<>(); -+ list.add(protoChunk); -+ net.minecraft.server.level.RegionLimitedWorldAccess genRegion = new net.minecraft.server.level.RegionLimitedWorldAccess(nmsWorld, list); -+ // call vanilla generator, one feature after another. Order here is important! -+ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkProvider().chunkGenerator; -+ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { -+ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; -+ } -+ chunkGenerator.createBiomes(nmsWorld.r().b(IRegistry.ay), protoChunk); -+ chunkGenerator.buildNoise(genRegion, nmsWorld.getStructureManager(), protoChunk); -+ chunkGenerator.buildBase(genRegion, protoChunk); -+ // copy over generated sections -+ data.setRawChunkData(protoChunk.getSections()); -+ // hooray! -+ return data; -+ } -+ // Paper end -+ - @Override - public BossBar createBossBar(String title, BarColor color, BarStyle style, BarFlag... flags) { - return new CraftBossBar(title, color, style, flags); -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -0,0 +0,0 @@ import org.bukkit.material.MaterialData; - */ - public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; -- private final ChunkSection[] sections; -+ private ChunkSection[] sections; // Paper - remove final - private Set tiles; - private World world; // Paper - Anti-Xray - Add world - -@@ -0,0 +0,0 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - return sections; - } - -+ // Paper start -+ public void setRawChunkData(ChunkSection[] sections) { -+ this.sections = sections; -+ } -+ // Paper end -+ - Set getTiles() { - return tiles; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CustomChunkGenerator.java -@@ -0,0 +0,0 @@ import org.bukkit.generator.ChunkGenerator.ChunkData; - - public class CustomChunkGenerator extends InternalChunkGenerator { - -- private final net.minecraft.world.level.chunk.ChunkGenerator delegate; -+ public final net.minecraft.world.level.chunk.ChunkGenerator delegate; // Paper - public - private final ChunkGenerator generator; - private final WorldServer world; - private final Random random = new Random(); diff --git a/Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch b/Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch deleted file mode 100644 index fd6e3e16c7..0000000000 --- a/Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Wed, 15 Aug 2018 01:26:09 -0700 -Subject: [PATCH] Allow disabling armour stand ticking - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void armorStandEntityLookups() { - armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); - } -+ -+ public boolean armorStandTick = true; -+ private void armorStandTick() { -+ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); -+ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - public Vector3f leftLegPose; - public Vector3f rightLegPose; - public boolean canMove = true; // Paper -+ // Paper start - Allow ArmorStands not to tick -+ public boolean canTick = true; -+ public boolean canTickSetByAPI = false; -+ private boolean noTickPoseDirty = false; -+ private boolean noTickEquipmentDirty = false; -+ // Paper end - - public EntityArmorStand(EntityTypes entitytypes, World world) { - super(entitytypes, world); -+ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking - this.handItems = NonNullList.a(2, ItemStack.b); - this.armorItems = NonNullList.a(4, ItemStack.b); - this.headPose = EntityArmorStand.bj; -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - this.armorItems.set(enumitemslot.b(), itemstack); - } - -+ this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled - } - - @Override -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - } - - nbttagcompound.set("Pose", this.B()); -+ if (this.canTickSetByAPI) nbttagcompound.setBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting - } - - @Override -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - this.setBasePlate(nbttagcompound.getBoolean("NoBasePlate")); - this.setMarker(nbttagcompound.getBoolean("Marker")); - this.noclip = !this.A(); -+ // Paper start - persist no tick -+ if (nbttagcompound.hasKey("Paper.CanTickOverride")) { -+ this.canTick = nbttagcompound.getBoolean("Paper.CanTickOverride"); -+ this.canTickSetByAPI = true; -+ } -+ // Paper end - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Pose"); - - this.g(nbttagcompound1); -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - - @Override - public void tick() { -+ // Paper start -+ if (!this.canTick) { -+ if (this.noTickPoseDirty) { -+ this.noTickPoseDirty = false; -+ this.updatePose(); -+ } -+ -+ if (this.noTickEquipmentDirty) { -+ this.noTickEquipmentDirty = false; -+ this.updateEquipment(); -+ } -+ -+ return; -+ } -+ // Paper end -+ - super.tick(); -+ // Paper start - Split into separate method -+ updatePose(); -+ } -+ -+ public void updatePose() { -+ // Paper end - Vector3f vector3f = (Vector3f) this.datawatcher.get(EntityArmorStand.c); - - if (!this.headPose.equals(vector3f)) { -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - public void setHeadPose(Vector3f vector3f) { - this.headPose = vector3f; - this.datawatcher.set(EntityArmorStand.c, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setBodyPose(Vector3f vector3f) { - this.bodyPose = vector3f; - this.datawatcher.set(EntityArmorStand.d, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftArmPose(Vector3f vector3f) { - this.leftArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.e, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setRightArmPose(Vector3f vector3f) { - this.rightArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.f, vector3f); -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - } - - public void setLeftLegPose(Vector3f vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.leftLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.g, vector3f); -+ - } - - public void setRightLegPose(Vector3f vector3f) { -+ this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.rightLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.bh, vector3f); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -0,0 +0,0 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { - return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); - } -+ -+ @Override -+ public boolean canTick() { -+ return this.getHandle().canTick; -+ } -+ -+ @Override -+ public void setCanTick(final boolean tick) { -+ this.getHandle().canTick = tick; -+ this.getHandle().canTickSetByAPI = true; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/Spigot-Server-Patches/Allow-disabling-mob-spawner-spawn-egg-transformation.patch deleted file mode 100644 index b9ed7a75bb..0000000000 --- a/Spigot-Server-Patches/Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Fri, 9 Oct 2020 20:30:12 -0400 -Subject: [PATCH] Allow disabling mob spawner spawn egg transformation - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void fixCuringExploit() { - fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); - } -+ -+ public boolean disableMobSpawnerSpawnEggTransformation = false; -+ private void disableMobSpawnerSpawnEggTransformation() { -+ disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); -+ } - } -diff --git a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -+++ b/src/main/java/net/minecraft/world/item/ItemMonsterEgg.java -@@ -0,0 +0,0 @@ public class ItemMonsterEgg extends Item { - EnumDirection enumdirection = itemactioncontext.getClickedFace(); - IBlockData iblockdata = world.getType(blockposition); - -- if (iblockdata.a(Blocks.SPAWNER)) { -+ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.a(Blocks.SPAWNER)) { // Paper - TileEntity tileentity = world.getTileEntity(blockposition); - - if (tileentity instanceof TileEntityMobSpawner) { diff --git a/Spigot-Server-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Spigot-Server-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch deleted file mode 100644 index 6ce190411e..0000000000 --- a/Spigot-Server-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Thu, 1 Apr 2021 00:34:02 -0700 -Subject: [PATCH] Allow for Component suggestion tooltips in - AsyncTabCompleteEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - // Paper start - async tab completion - com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); - String buffer = packetplayintabcomplete.c(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), - buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ java.util.List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server - if (!event.isHandled()) { - if (!event.isCancelled()) { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - }); - } - } else if (!completions.isEmpty()) { -- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); - -- builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -- completions.forEach(builder::suggest); -+ final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(completion -> { -+ if (completion.tooltip() == null) { -+ builder.suggest(completion.suggestion()); -+ } else { -+ builder.suggest(completion.suggestion(), PaperAdventure.asVanilla(completion.tooltip())); -+ } -+ }); - com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); - com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); - suggestEvent.setCancelled(suggestions.isEmpty()); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - final CraftServer server = this.server.server; - final String buffer = line.line(); - // Async Tab Complete -- com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -- java.util.List completions = new java.util.ArrayList<>(); -- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -- buffer, true, null); -+ final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = -+ new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), buffer, true, null); - event.callEvent(); -- completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ final List completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.completions(); - - if (event.isCancelled() || event.isHandled()) { - // Still fire sync event with the provided completions, if someone is listening - if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -- List finalCompletions = completions; -+ List finalCompletions = new java.util.ArrayList<>(completions); - Waitable> syncCompletions = new Waitable>() { - @Override - protected List evaluate() { -- org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, -+ finalCompletions.stream() -+ .map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::suggestion) -+ .collect(java.util.stream.Collectors.toList())); - return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); - } - }; - server.getServer().processQueue.add(syncCompletions); - try { -- completions = syncCompletions.get(); -+ final List legacyCompletions = syncCompletions.get(); -+ completions.removeIf(it -> !legacyCompletions.contains(it.suggestion())); // remove any suggestions that were removed -+ // add any new suggestions -+ for (final String completion : legacyCompletions) { -+ if (notNewSuggestion(completions, completion)) { -+ continue; -+ } -+ completions.add(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion(completion)); -+ } - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } - } - - if (!completions.isEmpty()) { -- candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(new Candidate( -+ completion.suggestion(), -+ completion.suggestion(), -+ null, -+ io.papermc.paper.adventure.PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null), -+ null, -+ null, -+ false -+ )); -+ } - } - return; - } -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - Thread.currentThread().interrupt(); - } - } -+ -+ // Paper start -+ private boolean notNewSuggestion(final List completions, final String completion) { -+ for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion it : completions) { -+ if (it.suggestion().equals(completion)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch b/Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch deleted file mode 100644 index 40ada8ba8a..0000000000 --- a/Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Thu, 3 Mar 2016 03:53:43 -0600 -Subject: [PATCH] Allow for toggling of spawn chunks - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - softDespawnDistance = softDespawnDistance*softDespawnDistance; - hardDespawnDistance = hardDespawnDistance*hardDespawnDistance; - } -+ -+ public boolean keepSpawnInMemory; -+ private void keepSpawnInMemory() { -+ keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); -+ log("Keep spawn chunk loaded: " + keepSpawnInMemory); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - }); - // CraftBukkit end - timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings -+ this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } diff --git a/Spigot-Server-Patches/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/Spigot-Server-Patches/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch deleted file mode 100644 index 2fee86152b..0000000000 --- a/Spigot-Server-Patches/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Apr 2020 03:51:53 -0400 -Subject: [PATCH] Allow multiple callbacks to schedule for Callback Executor - -ChunkMapDistance polls multiple entries for pendingChunkUpdates - -Each of these have the potential to move a chunk in and out of -"Loaded" state, which will result in multiple callbacks being -needed within a single tick of ChunkMapDistance - -Use an ArrayDeque to store this Queue - -We make sure to also implement a pattern that is recursion safe too. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); - public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { - -- private Runnable queued; -+ // Paper start - replace impl with recursive safe multi entry queue -+ // it's possible to schedule multiple tasks currently, so it's vital we change this impl -+ // If we recurse into the executor again, we will append to another queue, ensuring task order consistency -+ private java.util.ArrayDeque queued = new java.util.ArrayDeque<>(); - - @Override - public void execute(Runnable runnable) { -- if (queued != null) { -- throw new IllegalStateException("Already queued"); -+ if (queued == null) { -+ queued = new java.util.ArrayDeque<>(); - } -- queued = runnable; -+ queued.add(runnable); - } - - @Override - public void run() { -- Runnable task = queued; -+ if (queued == null) { -+ return; -+ } -+ java.util.ArrayDeque queue = queued; - queued = null; -- if (task != null) { -+ Runnable task; -+ while ((task = queue.pollFirst()) != null) { - task.run(); - } - } -+ // Paper end - }; - // CraftBukkit end - diff --git a/Spigot-Server-Patches/Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/Spigot-Server-Patches/Allow-nerfed-mobs-to-jump-and-take-water-damage.patch deleted file mode 100644 index 2b7b3fd0c1..0000000000 --- a/Spigot-Server-Patches/Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 1 Mar 2016 13:24:16 -0600 -Subject: [PATCH] Allow nerfed mobs to jump and take water damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); - log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); - } -+ -+ public boolean nerfedMobsShouldJump; -+ private void nerfedMobsShouldJump() { -+ nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.isInWater() || this.isInRain(); - } - -+ public final boolean isInWaterOrRainOrBubble() { return aG(); } // Paper - OBFHELPER - public boolean aG() { - return this.isInWater() || this.isInRain() || this.k(); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - private final EntityAIBodyControl c; - protected NavigationAbstract navigation; - public PathfinderGoalSelector goalSelector; -+ @Nullable public PathfinderGoalFloat goalFloat; // Paper - public PathfinderGoalSelector targetSelector; - private EntityLiving goalTarget; - private final EntitySenses bo; -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - @Override - protected final void doTick() { - ++this.ticksFarFromPlayer; -- if (!this.aware) return; // CraftBukkit -+ if (!this.aware) { // Paper start - Allow nerfed mobs to jump, float and take water damage -+ if (goalFloat != null) { -+ if (goalFloat.validConditions()) goalFloat.update(); -+ this.getControllerJump().jumpIfSet(); -+ } -+ if ((this instanceof EntityBlaze || this instanceof EntityEnderman) && isInWaterOrRainOrBubble()) { -+ damageEntity(DamageSource.DROWN, 1.0F); -+ } -+ return; -+ } -+ // Paper end - this.world.getMethodProfiler().enter("sensing"); - this.bo.a(); - this.world.getMethodProfiler().exit(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerJump.java -@@ -0,0 +0,0 @@ public class ControllerJump { - this.a = true; - } - -+ public final void jumpIfSet() { this.b(); } // Paper - OBFHELPER - public void b() { - this.b.setJumping(this.a); - this.a = false; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalFloat.java -@@ -0,0 +0,0 @@ public class PathfinderGoalFloat extends PathfinderGoal { - - public PathfinderGoalFloat(EntityInsentient entityinsentient) { - this.a = entityinsentient; -+ if (entityinsentient.getWorld().paperConfig.nerfedMobsShouldJump) entityinsentient.goalFloat = this; // Paper - this.a(EnumSet.of(PathfinderGoal.Type.JUMP)); - entityinsentient.getNavigation().d(true); - } - -+ public final boolean validConditions() { return this.a(); } // Paper - OBFHELPER - @Override - public boolean a() { - return this.a.isInWater() && this.a.b((Tag) TagsFluid.WATER) > this.a.cx() || this.a.aQ(); - } - -+ public void update() { this.e(); } // Paper - OBFHELPER - @Override - public void e() { - if (this.a.getRandom().nextFloat() < 0.8F) { diff --git a/Spigot-Server-Patches/Allow-overriding-the-java-version-check.patch b/Spigot-Server-Patches/Allow-overriding-the-java-version-check.patch deleted file mode 100644 index 9ee5f8b776..0000000000 --- a/Spigot-Server-Patches/Allow-overriding-the-java-version-check.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sat, 8 Feb 2020 18:02:24 -0600 -Subject: [PATCH] Allow overriding the java version check - --DPaper.IgnoreJavaVersion=true - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); - if (javaVersion > 60.0) { - System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); -- return; -+ if (!Boolean.getBoolean("Paper.IgnoreJavaVersion")) return; // Paper - } - - try { diff --git a/Spigot-Server-Patches/Allow-setting-the-vex-s-summoner.patch b/Spigot-Server-Patches/Allow-setting-the-vex-s-summoner.patch deleted file mode 100644 index 38790f5f2b..0000000000 --- a/Spigot-Server-Patches/Allow-setting-the-vex-s-summoner.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 6 Oct 2018 21:47:44 -0500 -Subject: [PATCH] Allow setting the vex's summoner - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -0,0 +0,0 @@ public class EntityVex extends EntityMonster { - this.a(1, flag); - } - -+ public void setOwner(EntityInsentient entityinsentient) { a(entityinsentient); } // Paper - OBFHELPER - public void a(EntityInsentient entityinsentient) { - this.c = entityinsentient; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -0,0 +0,0 @@ public class CraftVex extends CraftMonster implements Vex { - net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); - return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; - } -+ -+ public void setSummoner(org.bukkit.entity.Mob summoner) { -+ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/Allow-spawning-Item-entities-with-World.spawnEntity.patch b/Spigot-Server-Patches/Allow-spawning-Item-entities-with-World.spawnEntity.patch deleted file mode 100644 index 859a04e3df..0000000000 --- a/Spigot-Server-Patches/Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Jun 2018 20:39:20 -0400 -Subject: [PATCH] Allow spawning Item entities with World.spawnEntity - -This API has more capabilities than .dropItem with the Consumer function - -Item can be set inside of the Consumer pre spawn function. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - if (Boat.class.isAssignableFrom(clazz)) { - entity = new EntityBoat(world, x, y, z); - entity.setPositionRotation(x, y, z, yaw, pitch); -+ // Paper start -+ } else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) { -+ entity = new EntityItem(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.getItemOf(net.minecraft.world.level.block.Blocks.DIRT))); -+ // Paper end - } else if (FallingBlock.class.isAssignableFrom(clazz)) { - entity = new EntityFallingBlock(world, x, y, z, world.getType(new BlockPosition(x, y, z))); - } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/Spigot-Server-Patches/Allow-specifying-a-custom-authentication-servers-dow.patch b/Spigot-Server-Patches/Allow-specifying-a-custom-authentication-servers-dow.patch deleted file mode 100644 index 75e8645bd5..0000000000 --- a/Spigot-Server-Patches/Allow-specifying-a-custom-authentication-servers-dow.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Thu, 17 Aug 2017 16:08:20 -0700 -Subject: [PATCH] Allow specifying a custom "authentication servers down" kick - message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper; - -+import com.google.common.base.Strings; - import com.google.common.base.Throwables; - - import java.io.File; -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void suggestPlayersWhenNull() { - suggestPlayersWhenNullTabCompletions = getBoolean("settings.suggest-player-names-when-null-tab-completions", suggestPlayersWhenNullTabCompletions); - } -+ -+ public static String authenticationServersDownKickMessage = ""; // empty = use translatable message -+ private static void authenticationServersDownKickMessage() { -+ authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - LoginListener.this.i = LoginListener.this.a(gameprofile); - LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; - } else { -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { -+ LoginListener.this.disconnect(new ChatComponentText(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); -+ } else // Paper end - LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.authservers_down")); - LoginListener.LOGGER.error("Couldn't verify username because servers are unavailable"); - } diff --git a/Spigot-Server-Patches/Allow-using-signs-inside-spawn-protection.patch b/Spigot-Server-Patches/Allow-using-signs-inside-spawn-protection.patch deleted file mode 100644 index e7f3c9d812..0000000000 --- a/Spigot-Server-Patches/Allow-using-signs-inside-spawn-protection.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Anton Lindroth -Date: Wed, 15 Apr 2020 01:54:02 +0200 -Subject: [PATCH] Allow using signs inside spawn protection - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); - log("Withers properly target players: " + fixWitherTargetingBug); - } -+ -+ public boolean allowUsingSignsInsideSpawnProtection = false; -+ private void allowUsingSignsInsideSpawnProtection() { -+ allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.IWorldReader; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.BlockCommand; -+import net.minecraft.world.level.block.BlockSign; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntityCommand; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player.resetIdleTimer(); - if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { -- if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { -+ if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.a((EntityHuman) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getType(blockposition).getBlock() instanceof BlockSign))) { // Paper - // CraftBukkit start - Check if we can actually do something over this large a distance - // Paper - move check up - this.player.clearActiveItem(); // SPIGOT-4706 diff --git a/Spigot-Server-Patches/Always-tick-falling-blocks.patch b/Spigot-Server-Patches/Always-tick-falling-blocks.patch deleted file mode 100644 index d1254a90b5..0000000000 --- a/Spigot-Server-Patches/Always-tick-falling-blocks.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Wed, 2 Mar 2016 00:32:25 -0600 -Subject: [PATCH] Always tick falling blocks - - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ public class ActivationRange - || entity instanceof EntityFireball - || entity instanceof EntityLightning - || entity instanceof EntityTNTPrimed -+ || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks - || entity instanceof EntityEnderCrystal - || entity instanceof EntityFireworks - || entity instanceof EntityThrownTrident ) diff --git a/Spigot-Server-Patches/Anti-Xray.patch b/Spigot-Server-Patches/Anti-Xray.patch deleted file mode 100644 index 21fb569980..0000000000 --- a/Spigot-Server-Patches/Anti-Xray.patch +++ /dev/null @@ -1,1567 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: stonar96 -Date: Mon, 20 Aug 2018 03:03:58 +0200 -Subject: [PATCH] Anti-Xray - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper; - -+import java.util.Arrays; - import java.util.List; - -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void maxAutoSaveChunksPerTick() { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } -+ -+ public boolean antiXray; -+ public EngineMode engineMode; -+ public int maxChunkSectionIndex; -+ public int updateRadius; -+ public boolean lavaObscures; -+ public boolean usePermission; -+ public List hiddenBlocks; -+ public List replacementBlocks; -+ private void antiXray() { -+ antiXray = getBoolean("anti-xray.enabled", false); -+ engineMode = EngineMode.getById(getInt("anti-xray.engine-mode", EngineMode.HIDE.getId())); -+ engineMode = engineMode == null ? EngineMode.HIDE : engineMode; -+ maxChunkSectionIndex = getInt("anti-xray.max-chunk-section-index", 3); -+ maxChunkSectionIndex = maxChunkSectionIndex > 15 ? 15 : maxChunkSectionIndex; -+ updateRadius = getInt("anti-xray.update-radius", 2); -+ lavaObscures = getBoolean("anti-xray.lava-obscures", false); -+ usePermission = getBoolean("anti-xray.use-permission", false); -+ hiddenBlocks = getList("anti-xray.hidden-blocks", Arrays.asList("gold_ore", "iron_ore", "coal_ore", "lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "redstone_ore", "clay", "emerald_ore", "ender_chest")); -+ replacementBlocks = getList("anti-xray.replacement-blocks", Arrays.asList("stone", "oak_planks")); -+ if (PaperConfig.version < 19) { -+ hiddenBlocks.remove("lit_redstone_ore"); -+ int index = replacementBlocks.indexOf("planks"); -+ if (index != -1) { -+ replacementBlocks.set(index, "oak_planks"); -+ } -+ set("anti-xray.hidden-blocks", hiddenBlocks); -+ set("anti-xray.replacement-blocks", replacementBlocks); -+ } -+ log("Anti-Xray: " + (antiXray ? "enabled" : "disabled") + " / Engine Mode: " + engineMode.getDescription() + " / Up to " + ((maxChunkSectionIndex + 1) * 16) + " blocks / Update Radius: " + updateRadius); -+ if (antiXray && usePermission) { -+ Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockController.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.IChunkAccess; -+ -+public class ChunkPacketBlockController { -+ -+ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); -+ -+ protected ChunkPacketBlockController() { -+ -+ } -+ -+ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { -+ return null; -+ } -+ -+ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { -+ return false; -+ } -+ -+ public ChunkPacketInfo getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ return null; -+ } -+ -+ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ packetPlayOutMapChunk.setReady(true); -+ } -+ -+ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { -+ -+ } -+ -+ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.antixray; -+ -+import java.util.ArrayList; -+import java.util.LinkedHashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Set; -+import java.util.concurrent.Executor; -+import java.util.concurrent.ThreadLocalRandom; -+import java.util.function.IntSupplier; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.core.IRegistry; -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.Blocks; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.ChunkEmpty; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.DataPalette; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import org.bukkit.Bukkit; -+import org.bukkit.World.Environment; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+ -+public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockController { -+ -+ private final Executor executor; -+ private final EngineMode engineMode; -+ private final int maxChunkSectionIndex; -+ private final int updateRadius; -+ private final boolean usePermission; -+ private final IBlockData[] predefinedBlockData; -+ private final IBlockData[] predefinedBlockDataFull; -+ private final IBlockData[] predefinedBlockDataStone; -+ private final IBlockData[] predefinedBlockDataNetherrack; -+ private final IBlockData[] predefinedBlockDataEndStone; -+ private final int[] predefinedBlockDataBitsGlobal; -+ private final int[] predefinedBlockDataBitsStoneGlobal; -+ private final int[] predefinedBlockDataBitsNetherrackGlobal; -+ private final int[] predefinedBlockDataBitsEndStoneGlobal; -+ private final boolean[] solidGlobal = new boolean[Block.REGISTRY_ID.size()]; -+ private final boolean[] obfuscateGlobal = new boolean[Block.REGISTRY_ID.size()]; -+ private final ChunkSection[] emptyNearbyChunkSections = {Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION, Chunk.EMPTY_CHUNK_SECTION}; -+ private final int maxBlockYUpdatePosition; -+ -+ public ChunkPacketBlockControllerAntiXray(World world, Executor executor) { -+ PaperWorldConfig paperWorldConfig = world.paperConfig; -+ engineMode = paperWorldConfig.engineMode; -+ maxChunkSectionIndex = paperWorldConfig.maxChunkSectionIndex; -+ updateRadius = paperWorldConfig.updateRadius; -+ usePermission = paperWorldConfig.usePermission; -+ -+ this.executor = executor; -+ -+ List toObfuscate; -+ -+ if (engineMode == EngineMode.HIDE) { -+ toObfuscate = paperWorldConfig.hiddenBlocks; -+ predefinedBlockData = null; -+ predefinedBlockDataFull = null; -+ predefinedBlockDataStone = new IBlockData[] {Blocks.STONE.getBlockData()}; -+ predefinedBlockDataNetherrack = new IBlockData[] {Blocks.NETHERRACK.getBlockData()}; -+ predefinedBlockDataEndStone = new IBlockData[] {Blocks.END_STONE.getBlockData()}; -+ predefinedBlockDataBitsGlobal = null; -+ predefinedBlockDataBitsStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.STONE.getBlockData())}; -+ predefinedBlockDataBitsNetherrackGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.NETHERRACK.getBlockData())}; -+ predefinedBlockDataBitsEndStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.END_STONE.getBlockData())}; -+ } else { -+ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); -+ List predefinedBlockDataList = new LinkedList(); -+ -+ for (String id : paperWorldConfig.hiddenBlocks) { -+ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); -+ -+ if (block != null && !block.isTileEntity()) { -+ toObfuscate.add(id); -+ predefinedBlockDataList.add(block.getBlockData()); -+ } -+ } -+ -+ // The doc of the LinkedHashSet(Collection c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation -+ Set predefinedBlockDataSet = new LinkedHashSet(); -+ // Therefore addAll(Collection c) is used, which guarantees this order in the doc -+ predefinedBlockDataSet.addAll(predefinedBlockDataList); -+ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataSet.toArray(new IBlockData[0]); -+ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataList.toArray(new IBlockData[0]); -+ predefinedBlockDataStone = null; -+ predefinedBlockDataNetherrack = null; -+ predefinedBlockDataEndStone = null; -+ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; -+ -+ for (int i = 0; i < predefinedBlockDataFull.length; i++) { -+ predefinedBlockDataBitsGlobal[i] = ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ -+ predefinedBlockDataBitsStoneGlobal = null; -+ predefinedBlockDataBitsNetherrackGlobal = null; -+ predefinedBlockDataBitsEndStoneGlobal = null; -+ } -+ -+ for (String id : toObfuscate) { -+ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); -+ -+ // Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void -+ if (block != null && !block.getBlockData().isAir()) { -+ // Replace all block states of a specified block -+ // No OBFHELPER for nms.BlockStateList#a() due to too many decompile errors -+ // The OBFHELPER should be getBlockDataList() -+ for (IBlockData blockData : block.getStates().a()) { -+ obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)] = true; -+ } -+ } -+ } -+ -+ ChunkEmpty emptyChunk = new ChunkEmpty(world, new ChunkCoordIntPair(0, 0)); -+ BlockPosition zeroPos = new BlockPosition(0, 0, 0); -+ -+ for (int i = 0; i < solidGlobal.length; i++) { -+ IBlockData blockData = ChunkSection.GLOBAL_PALETTE.getObject(i); -+ -+ if (blockData != null) { -+ solidGlobal[i] = blockData.isOccluding(emptyChunk, zeroPos) -+ && blockData.getBlock() != Blocks.SPAWNER && blockData.getBlock() != Blocks.BARRIER && blockData.getBlock() != Blocks.SHULKER_BOX && blockData.getBlock() != Blocks.SLIME_BLOCK || paperWorldConfig.lavaObscures && blockData == Blocks.LAVA.getBlockData(); -+ // Comparing blockData == Blocks.LAVA.getBlockData() instead of blockData.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used -+ // shulker box checks TE. -+ } -+ } -+ -+ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; -+ } -+ -+ private int getPredefinedBlockDataFullLength() { -+ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length; -+ } -+ -+ @Override -+ public IBlockData[] getPredefinedBlockData(World world, IChunkAccess chunk, ChunkSection chunkSection, boolean initializeBlocks) { -+ // Return the block data which should be added to the data palettes so that they can be used for the obfuscation -+ if (chunkSection.getYPosition() >> 4 <= maxChunkSectionIndex) { -+ switch (engineMode) { -+ case HIDE: -+ switch (world.getWorld().getEnvironment()) { -+ case NETHER: -+ return predefinedBlockDataNetherrack; -+ case THE_END: -+ return predefinedBlockDataEndStone; -+ default: -+ return predefinedBlockDataStone; -+ } -+ default: -+ return predefinedBlockData; -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public boolean shouldModify(EntityPlayer entityPlayer, Chunk chunk, int chunkSectionSelector) { -+ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); -+ } -+ -+ @Override -+ public ChunkPacketInfoAntiXray getChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ // Return a new instance to collect data and objects in the right state while creating the chunk packet for thread safe access later -+ // Note: As of 1.14 this has to be moved later due to the chunk system. -+ ChunkPacketInfoAntiXray chunkPacketInfoAntiXray = new ChunkPacketInfoAntiXray(packetPlayOutMapChunk, chunk, chunkSectionSelector, this); -+ return chunkPacketInfoAntiXray; -+ } -+ -+ @Override -+ public void modifyBlocks(PacketPlayOutMapChunk packetPlayOutMapChunk, ChunkPacketInfo chunkPacketInfo) { -+ if (chunkPacketInfo == null) { -+ packetPlayOutMapChunk.setReady(true); -+ return; -+ } -+ -+ if (!Bukkit.isPrimaryThread()) { -+ // plugins? -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ this.modifyBlocks(packetPlayOutMapChunk, chunkPacketInfo); -+ }); -+ return; -+ } -+ -+ Chunk chunk = chunkPacketInfo.getChunk(); -+ int x = chunk.getPos().x; -+ int z = chunk.getPos().z; -+ WorldServer world = (WorldServer)chunk.world; -+ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( -+ (Chunk) world.getChunkIfLoadedImmediately(x - 1, z), -+ (Chunk) world.getChunkIfLoadedImmediately(x + 1, z), -+ (Chunk) world.getChunkIfLoadedImmediately(x, z - 1), -+ (Chunk) world.getChunkIfLoadedImmediately(x, z + 1)); -+ -+ executor.execute((ChunkPacketInfoAntiXray) chunkPacketInfo); -+ } -+ -+ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) -+ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here -+ private final ThreadLocal predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]); -+ private static final ThreadLocal solid = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); -+ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); -+ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate -+ private static final ThreadLocal current = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal next = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ private static final ThreadLocal nextNext = ThreadLocal.withInitial(() -> new boolean[16][16]); -+ -+ public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) { -+ int[] predefinedBlockDataBits = this.predefinedBlockDataBits.get(); -+ boolean[] solid = this.solid.get(); -+ boolean[] obfuscate = this.obfuscate.get(); -+ boolean[][] current = this.current.get(); -+ boolean[][] next = this.next.get(); -+ boolean[][] nextNext = this.nextNext.get(); -+ // dataBitsReader, dataBitsWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it -+ DataBitsReader dataBitsReader = new DataBitsReader(); -+ DataBitsWriter dataBitsWriter = new DataBitsWriter(); -+ ChunkSection[] nearbyChunkSections = new ChunkSection[4]; -+ boolean[] solidTemp = null; -+ boolean[] obfuscateTemp = null; -+ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData()); -+ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData()); -+ int numberOfBlocks = predefinedBlockDataBits.length; -+ // Keep the lambda expressions as simple as possible. They are used very frequently. -+ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() { -+ private int state; -+ -+ { -+ while ((state = ThreadLocalRandom.current().nextInt()) == 0); -+ } -+ -+ @Override -+ public int getAsInt() { -+ // https://en.wikipedia.org/wiki/Xorshift -+ state ^= state << 13; -+ state ^= state >>> 17; -+ state ^= state << 5; -+ // https://www.pcg-random.org/posts/bounded-rands.html -+ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32); -+ } -+ }; -+ -+ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) { -+ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) { -+ int[] predefinedBlockDataBitsTemp; -+ -+ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == ChunkSection.GLOBAL_PALETTE) { -+ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; -+ } else { -+ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead -+ IBlockData[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex); -+ predefinedBlockDataBitsTemp = predefinedBlockDataBits; -+ -+ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { -+ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]); -+ } -+ } -+ -+ dataBitsWriter.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ -+ // Check if the chunk section below was not obfuscated -+ if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex - 1) == null) { -+ // If so, initialize some stuff -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex), obfuscate, obfuscateGlobal); -+ // Read the blocks of the upper layer of the chunk section below if it exists -+ ChunkSection belowChunkSection = null; -+ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == Chunk.EMPTY_CHUNK_SECTION; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ current[z][x] = true; -+ next[z][x] = skipFirstLayer || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(belowChunkSection.getType(x, 15, z))]; -+ } -+ } -+ -+ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section -+ dataBitsWriter.setBitsPerObject(0); -+ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex)); -+ nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; -+ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? Chunk.EMPTY_CHUNK_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex]; -+ -+ // Obfuscate all layers of the current chunk section except the upper one -+ for (int y = 0; y < 15; y++) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ // Check if the chunk section above doesn't need obfuscation -+ if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex + 1) == null) { -+ // If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists -+ ChunkSection aboveChunkSection; -+ -+ if (chunkSectionIndex != 15 && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != Chunk.EMPTY_CHUNK_SECTION) { -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ -+ for (int z = 0; z < 16; z++) { -+ for (int x = 0; x < 16; x++) { -+ if (!solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(aboveChunkSection.getType(x, 0, z))]) { -+ current[z][x] = true; -+ } -+ } -+ } -+ -+ // There is nothing to read anymore -+ dataBitsReader.setBitsPerObject(0); -+ solid[0] = true; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ } else { -+ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section -+ dataBitsReader.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex + 1)); -+ dataBitsReader.setIndex(chunkPacketInfoAntiXray.getDataBitsIndex(chunkSectionIndex + 1)); -+ solidTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), solid, solidGlobal); -+ obfuscateTemp = readDataPalette(chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal); -+ boolean[][] temp = current; -+ current = next; -+ next = nextNext; -+ nextNext = temp; -+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random); -+ } -+ -+ dataBitsWriter.finish(); -+ } -+ } -+ -+ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true); -+ } -+ -+ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, ChunkSection[] nearbyChunkSections, IntSupplier random) { -+ // First block of first line -+ int dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][1] = true; -+ next[1][0] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(0, y, 15))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 0))] || current[0][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][0] = true; -+ } -+ -+ // First line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][x - 1] = true; -+ next[0][x + 1] = true; -+ next[1][x] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(x, y, 15))] || current[0][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][x] = true; -+ } -+ } -+ -+ // Last block of first line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[0][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[0][14] = true; -+ next[1][15] = true; -+ } else { -+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(15, y, 15))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 0))] || current[0][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[0][15] = true; -+ } -+ -+ // All inner lines -+ for (int z = 1; z < 15; z++) { -+ // First block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][1] = true; -+ next[z - 1][0] = true; -+ next[z + 1][0] = true; -+ } else { -+ if (nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, z))] || current[z][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][0] = true; -+ } -+ -+ // All inner blocks -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][x - 1] = true; -+ next[z][x + 1] = true; -+ next[z - 1][x] = true; -+ next[z + 1][x] = true; -+ } else { -+ if (current[z][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][x] = true; -+ } -+ } -+ -+ // Last block -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[z][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[z][14] = true; -+ next[z - 1][15] = true; -+ next[z + 1][15] = true; -+ } else { -+ if (nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, z))] || current[z][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[z][15] = true; -+ } -+ } -+ -+ // First block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][0] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][1] = true; -+ next[14][0] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(0, y, 0))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 15))] || current[15][0]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][0] = true; -+ } -+ -+ // Last line -+ for (int x = 1; x < 15; x++) { -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][x] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][x - 1] = true; -+ next[15][x + 1] = true; -+ next[14][x] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(x, y, 0))] || current[15][x]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][x] = true; -+ } -+ } -+ -+ // Last block of last line -+ dataBits = dataBitsReader.read(); -+ -+ if (nextNext[15][15] = !solid[dataBits]) { -+ dataBitsWriter.skip(); -+ next[15][14] = true; -+ next[14][15] = true; -+ } else { -+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(15, y, 0))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 15))] || current[15][15]) { -+ dataBitsWriter.skip(); -+ } else { -+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); -+ } -+ } -+ -+ if (!obfuscate[dataBits]) { -+ next[15][15] = true; -+ } -+ } -+ -+ private boolean[] readDataPalette(DataPalette dataPalette, boolean[] temp, boolean[] global) { -+ if (dataPalette == ChunkSection.GLOBAL_PALETTE) { -+ return global; -+ } -+ -+ IBlockData blockData; -+ -+ for (int i = 0; (blockData = dataPalette.getObject(i)) != null; i++) { -+ temp[i] = global[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]; -+ } -+ -+ return temp; -+ } -+ -+ @Override -+ public void onBlockChange(World world, BlockPosition blockPosition, IBlockData newBlockData, IBlockData oldBlockData, int flag) { -+ if (oldBlockData != null && solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(oldBlockData)] && !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(world, blockPosition); -+ } -+ } -+ -+ @Override -+ public void onPlayerLeftClickBlock(PlayerInteractManager playerInteractManager, BlockPosition blockPosition, EnumDirection enumDirection) { -+ if (blockPosition.getY() <= maxBlockYUpdatePosition) { -+ updateNearbyBlocks(playerInteractManager.world, blockPosition); -+ } -+ } -+ -+ private void updateNearbyBlocks(World world, BlockPosition blockPosition) { -+ if (updateRadius >= 2) { -+ BlockPosition temp = blockPosition.west(); -+ updateBlock(world, temp); -+ updateBlock(world, temp.west()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.east()); -+ updateBlock(world, temp.east()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.down()); -+ updateBlock(world, temp.down()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.up()); -+ updateBlock(world, temp.up()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp.south()); -+ updateBlock(world, temp = blockPosition.north()); -+ updateBlock(world, temp.north()); -+ updateBlock(world, temp = blockPosition.south()); -+ updateBlock(world, temp.south()); -+ } else if (updateRadius == 1) { -+ updateBlock(world, blockPosition.west()); -+ updateBlock(world, blockPosition.east()); -+ updateBlock(world, blockPosition.down()); -+ updateBlock(world, blockPosition.up()); -+ updateBlock(world, blockPosition.north()); -+ updateBlock(world, blockPosition.south()); -+ } else { -+ // Do nothing if updateRadius <= 0 (test mode) -+ } -+ } -+ -+ private void updateBlock(World world, BlockPosition blockPosition) { -+ IBlockData blockData = world.getTypeIfLoaded(blockPosition); -+ -+ if (blockData != null && obfuscateGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(blockData)]) { -+ // world.notify(blockPosition, blockData, blockData, 3); -+ ((WorldServer)world).getChunkProvider().flagDirty(blockPosition); // We only need to re-send to client -+ } -+ } -+ -+ public enum EngineMode { -+ -+ HIDE(1, "hide ores"), -+ OBFUSCATE(2, "obfuscate"); -+ -+ private final int id; -+ private final String description; -+ -+ EngineMode(int id, String description) { -+ this.id = id; -+ this.description = description; -+ } -+ -+ public static EngineMode getById(int id) { -+ for (EngineMode engineMode : values()) { -+ if (engineMode.id == id) { -+ return engineMode; -+ } -+ } -+ -+ return null; -+ } -+ -+ public int getId() { -+ return id; -+ } -+ -+ public String getDescription() { -+ return description; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.world.level.chunk.Chunk; -+import net.minecraft.world.level.chunk.DataPalette; -+ -+public class ChunkPacketInfo { -+ -+ private final PacketPlayOutMapChunk packetPlayOutMapChunk; -+ private final Chunk chunk; -+ private final int chunkSectionSelector; -+ private byte[] data; -+ private final int[] bitsPerObject = new int[16]; -+ private final Object[] dataPalettes = new Object[16]; -+ private final int[] dataBitsIndexes = new int[16]; -+ private final Object[][] predefinedObjects = new Object[16][]; -+ -+ public ChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { -+ this.packetPlayOutMapChunk = packetPlayOutMapChunk; -+ this.chunk = chunk; -+ this.chunkSectionSelector = chunkSectionSelector; -+ } -+ -+ public PacketPlayOutMapChunk getPacketPlayOutMapChunk() { -+ return packetPlayOutMapChunk; -+ } -+ -+ public Chunk getChunk() { -+ return chunk; -+ } -+ -+ public int getChunkSectionSelector() { -+ return chunkSectionSelector; -+ } -+ -+ public byte[] getData() { -+ return data; -+ } -+ -+ public void setData(byte[] data) { -+ this.data = data; -+ } -+ -+ public int getBitsPerObject(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex]; -+ } -+ -+ public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { -+ this.bitsPerObject[chunkSectionIndex] = bitsPerObject; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public DataPalette getDataPalette(int chunkSectionIndex) { -+ return (DataPalette) dataPalettes[chunkSectionIndex]; -+ } -+ -+ public void setDataPalette(int chunkSectionIndex, DataPalette dataPalette) { -+ dataPalettes[chunkSectionIndex] = dataPalette; -+ } -+ -+ public int getDataBitsIndex(int chunkSectionIndex) { -+ return dataBitsIndexes[chunkSectionIndex]; -+ } -+ -+ public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { -+ dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public T[] getPredefinedObjects(int chunkSectionIndex) { -+ return (T[]) predefinedObjects[chunkSectionIndex]; -+ } -+ -+ public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { -+ this.predefinedObjects[chunkSectionIndex] = predefinedObjects; -+ } -+ -+ public boolean isWritten(int chunkSectionIndex) { -+ return bitsPerObject[chunkSectionIndex] != 0; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfoAntiXray.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.antixray; -+ -+import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; -+ -+public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { -+ -+ private Chunk[] nearbyChunks; -+ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; -+ -+ public ChunkPacketInfoAntiXray(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector, -+ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { -+ super(packetPlayOutMapChunk, chunk, chunkSectionSelector); -+ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; -+ } -+ -+ public Chunk[] getNearbyChunks() { -+ return nearbyChunks; -+ } -+ -+ public void setNearbyChunks(Chunk... nearbyChunks) { -+ this.nearbyChunks = nearbyChunks; -+ } -+ -+ @Override -+ public void run() { -+ chunkPacketBlockControllerAntiXray.obfuscate(this); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsReader { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private int mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ } -+ -+ public int read() { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ int value = (int) (current >>> bitInLongIndex) & mask; -+ bitInLongIndex += bitsPerObject; -+ return value; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.antixray; -+ -+public final class DataBitsWriter { -+ -+ private byte[] dataBits; -+ private int bitsPerObject; -+ private long mask; -+ private int longInDataBitsIndex; -+ private int bitInLongIndex; -+ private long current; -+ private boolean dirty; -+ -+ public void setDataBits(byte[] dataBits) { -+ this.dataBits = dataBits; -+ } -+ -+ public void setBitsPerObject(int bitsPerObject) { -+ this.bitsPerObject = bitsPerObject; -+ mask = (1 << bitsPerObject) - 1; -+ } -+ -+ public void setIndex(int index) { -+ this.longInDataBitsIndex = index; -+ bitInLongIndex = 0; -+ init(); -+ } -+ -+ private void init() { -+ if (dataBits.length > longInDataBitsIndex + 7) { -+ current = ((((long) dataBits[longInDataBitsIndex]) << 56) -+ | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) -+ | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) -+ | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) -+ | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) -+ | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) -+ | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) -+ | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); -+ } -+ -+ dirty = false; -+ } -+ -+ public void finish() { -+ if (dirty && dataBits.length > longInDataBitsIndex + 7) { -+ dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); -+ dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); -+ dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); -+ dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); -+ dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); -+ dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); -+ dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); -+ dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); -+ } -+ } -+ -+ public void write(int value) { -+ if (bitInLongIndex + bitsPerObject > 64) { -+ finish(); -+ bitInLongIndex = 0; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ -+ current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; -+ dirty = true; -+ bitInLongIndex += bitsPerObject; -+ } -+ -+ public void skip() { -+ bitInLongIndex += bitsPerObject; -+ -+ if (bitInLongIndex > 64) { -+ finish(); -+ bitInLongIndex = bitsPerObject; -+ longInDataBitsIndex += 8; -+ init(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -0,0 +0,0 @@ - package net.minecraft.network.protocol.game; - -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import com.google.common.collect.Lists; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntitySkull; -+import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.chunk.BiomeStorage; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkSection; -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - private List g; - private boolean h; - -- public PacketPlayOutMapChunk() {} -+ // Paper start - Async-Anti-Xray - Set the ready flag to true -+ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager -+ public PacketPlayOutMapChunk() { -+ this.ready = true; -+ } -+ // Paper end -+ - // Paper start - private final java.util.List extraPackets = new java.util.ArrayList<>(); - private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - return extraPackets; - } - // Paper end -- public PacketPlayOutMapChunk(Chunk chunk, int i) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public PacketPlayOutMapChunk(Chunk chunk, int i) { this(chunk, i, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public PacketPlayOutMapChunk(Chunk chunk, int i, boolean modifyBlocks) { -+ ChunkPacketInfo chunkPacketInfo = modifyBlocks ? chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i) : null; -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - - this.a = chunkcoordintpair.x; -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - } - - this.f = new byte[this.a(chunk, i)]; -- this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setData(this.getData()); -+ } -+ this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); -+ // Paper end - this.g = Lists.newArrayList(); - iterator = chunk.getTileEntities().entrySet().iterator(); - int totalTileEntities = 0; // Paper -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - this.g.add(nbttagcompound); - } - } -+ chunk.world.chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks -+ } - -+ // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag -+ @Override -+ public boolean isReady() { -+ return this.ready; -+ } -+ -+ public void setReady(boolean ready) { -+ this.ready = ready; - } -+ // Paper end - - @Override - public void a(PacketDataSerializer packetdataserializer) throws IOException { -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - return bytebuf; - } - -- public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER -- public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { return this.writeChunk(packetdataserializer, chunk, i, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector, ChunkPacketInfo chunkPacketInfo) { return this.a(packetDataSerializer, chunk, chunkSectionSelector, chunkPacketInfo); } // OBFHELPER -+ public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - int j = 0; - ChunkSection[] achunksection = chunk.getSections(); - int k = 0; -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - - if (chunksection != Chunk.a && (!this.f() || !chunksection.c()) && (i & 1 << k) != 0) { - j |= 1 << k; -- chunksection.b(packetdataserializer); -+ chunksection.writeChunkSection(packetdataserializer, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info - } - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - this.g(chunkcoordintpair); -- return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a)); -+ return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter - }, this.executor); - } - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { -- apacket[0] = new PacketPlayOutMapChunk(chunk, 65535); -+ apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass - apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - } - - } -+ -+ this.world.chunkPacketBlockController.onPlayerLeftClickBlock(this, blockposition, enumdirection); // Paper - Anti-Xray - } - - public void a(BlockPosition blockposition, PacketPlayInBlockDig.EnumPlayerDigType packetplayinblockdig_enumplayerdigtype, String s) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env); -+ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor - this.pvpMode = minecraftserver.getPVP(); - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level; - - import co.aikar.timings.Timing; - import co.aikar.timings.Timings; -+import com.destroystokyo.paper.antixray.ChunkPacketBlockController; // Paper - Anti-Xray -+import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray; // Paper - Anti-Xray - import com.destroystokyo.paper.event.server.ServerExceptionEvent; - import com.destroystokyo.paper.exception.ServerInternalException; - import com.google.common.base.MoreObjects; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ public final ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray - - public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPosition lastPhysicsProblem; // Spigot -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return typeKey; - } - -- protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { -+ protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper -+ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit end - - IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0); // CraftBukkit custom NO_PLACE flag -+ this.chunkPacketBlockController.onBlockChange(this, blockposition, iblockdata, iblockdata1, i); // Paper - Anti-Xray - - if (iblockdata1 == null) { - // CraftBukkit start - remove blockstate if failed (or the same) -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - return null; - } - -- chunksection = new ChunkSection(j >> 4 << 4); -+ chunksection = new ChunkSection(j >> 4 << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - this.sections[j >> 4] = chunksection; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -@@ -0,0 +0,0 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.data.worldgen.biome.BiomeRegistry; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -0,0 +0,0 @@ public class ChunkEmpty extends Chunk { - }); - - public ChunkEmpty(World world, ChunkCoordIntPair chunkcoordintpair) { -- super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); -+ super(world, chunkcoordintpair, new BiomeStorage(MinecraftServer.getServer().getCustomRegistry().b(IRegistry.ay), ChunkEmpty.b)); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry - } - - // Paper start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.chunk; - - import java.util.function.Predicate; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import javax.annotation.Nullable; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.network.PacketDataSerializer; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -@@ -0,0 +0,0 @@ public class ChunkSection { - private short e; - final DataPaletteBlock blockIds; // Paper - package-private - -- public ChunkSection(int i) { -- this(i, (short) 0, (short) 0, (short) 0); -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { -+ this(i, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); -+ // Paper end - } - -- public ChunkSection(int i, short short0, short short1, short short2) { -+ // Paper start - Anti-Xray - Add parameters -+ @Deprecated public ChunkSection(int i, short short0, short short1, short short2) { this(i, short0, short1, short2, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ChunkSection(int i, short short0, short short1, short short2, IChunkAccess chunk, World world, boolean initializeBlocks) { -+ // Paper end - this.yPos = i; - this.nonEmptyBlockCount = short0; - this.tickingBlockCount = short1; - this.e = short2; -- this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); -+ this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data - } - - public final IBlockData getType(int i, int j, int k) { // Paper -@@ -0,0 +0,0 @@ public class ChunkSection { - return this.blockIds; - } - -- public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public void b(PacketDataSerializer packetdataserializer) { -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public final void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public final void b(PacketDataSerializer packetdataserializer) { this.writeChunkSection(packetdataserializer, null); } // Notice for updates: Please make sure this method isn't used anywhere -+ public final void writeChunkSection(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo) { this.b(packetDataSerializer, chunkPacketInfo); } // OBFHELPER -+ public void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo) { -+ // Paper end - packetdataserializer.writeShort(this.nonEmptyBlockCount); -- this.blockIds.b(packetdataserializer); -+ this.blockIds.writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, this.yPos >> 4); // Paper - Anti-Xray - Add chunk packet info - } - - public int j() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.chunk; - - import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info - import java.util.Arrays; - import java.util.Objects; - import java.util.concurrent.locks.ReentrantLock; -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private final Function e; - private final Function f; - private final T g; -+ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects - protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER - private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER - private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - //this.j.unlock(); // Paper - disable this - } - -- public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { -+ // Paper start - Anti-Xray - Add predefined objects -+ @Deprecated public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { this(datapalette, registryblockid, function, function1, t0, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0, T[] predefinedObjects, boolean initialize) { -+ // Paper end - this.b = datapalette; - this.d = registryblockid; - this.e = function; - this.f = function1; - this.g = t0; -- this.b(4); -+ // Paper start - Anti-Xray - Add predefined objects -+ this.predefinedObjects = predefinedObjects; -+ -+ if (initialize) { -+ if (predefinedObjects == null) { -+ // Default -+ this.initialize(4); -+ } else { -+ // MathHelper.d() is trailingBits(roundCeilPow2(n)), alternatively; (int)ceil(log2(n)); however it's trash, use numberOfLeadingZeros instead -+ // Count the bits of the maximum array index to initialize a data palette with enough space from the beginning -+ // The length of the array is used because air is also added to the data palette from the beginning -+ // Start with at least 4 -+ int maxIndex = predefinedObjects.length >> 4; -+ int bitCount = (32 - Integer.numberOfLeadingZeros(Math.max(16, maxIndex) - 1)); -+ -+ // Initialize with at least 15 free indixes -+ this.initialize((1 << bitCount) - predefinedObjects.length < 16 ? bitCount + 1 : bitCount); -+ this.addPredefinedObjects(); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - Anti-Xray - Add predefined objects -+ private void addPredefinedObjects() { -+ if (this.predefinedObjects != null && this.getDataPalette() != this.getDataPaletteGlobal()) { -+ for (int i = 0; i < this.predefinedObjects.length; i++) { -+ this.getDataPalette().getOrCreateIdFor(this.predefinedObjects[i]); -+ } -+ } - } -+ // Paper end - - private static int b(int i, int j, int k) { - return j << 8 | k << 4 | i; -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - - int j; - -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - for (j = 0; j < databits.b(); ++j) { - T t1 = datapalette.a(databits.a(j)); - -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return t0 == null ? this.g : t0; - } - -- public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize -+ // Paper start - Anti-Xray - Add chunk packet info -+ @Deprecated public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // OBFHELPER // Notice for updates: Please make sure this method isn't used anywhere -+ @Deprecated public void b(PacketDataSerializer packetdataserializer) { this.writeDataPaletteBlock(packetdataserializer, null, 0); } // Notice for updates: Please make sure this method isn't used anywhere -+ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { this.b(packetDataSerializer, chunkPacketInfo, chunkSectionIndex); } // OBFHELPER -+ public synchronized void b(PacketDataSerializer packetdataserializer, ChunkPacketInfo chunkPacketInfo, int chunkSectionIndex) { // Paper - synchronize -+ // Paper end - this.a(); - packetdataserializer.writeByte(this.i); - this.h.b(packetdataserializer); -+ // Paper start - Anti-Xray - Add chunk packet info -+ if (chunkPacketInfo != null) { -+ chunkPacketInfo.setBitsPerObject(chunkSectionIndex, this.getBitsPerObject()); -+ chunkPacketInfo.setDataPalette(chunkSectionIndex, this.getDataPalette()); -+ chunkPacketInfo.setDataBitsIndex(chunkSectionIndex, packetdataserializer.writerIndex() + PacketDataSerializer.countBytes(this.getDataBits().getDataBits().length)); -+ chunkPacketInfo.setPredefinedObjects(chunkSectionIndex, this.predefinedObjects); -+ } -+ // Paper end - packetdataserializer.a(this.a.a()); - this.b(); - } - - public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize - this.a(); -- int i = Math.max(4, MathHelper.e(nbttaglist.size())); -+ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? -+ int i = Math.max(4, MathHelper.e(nbttaglist.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects - -- if (i != this.i) { -+ if (true || i != this.i) { // Paper - Anti-Xray - Not initialized yet - this.b(i); - } - - this.h.a(nbttaglist); -+ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects - int j = along.length * 64 / 4096; - - if (this.h == this.b) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -0,0 +0,0 @@ public class ProtoChunk implements IChunkAccess { - private long s; - private final Map t; - private volatile boolean u; -+ private final World world; // Paper - Anti-Xray - Add world - -- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, World world) { -+ // Paper end - this(chunkcoordintpair, chunkconverter, (ChunkSection[]) null, new ProtoChunkTickList<>((block) -> { - return block == null || block.getBlockData().isAir(); - }, chunkcoordintpair), new ProtoChunkTickList<>((fluidtype) -> { - return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, chunkcoordintpair)); -+ }, chunkcoordintpair), world); // Paper - Anti-Xray - Add world - } - -- public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { -+ // Paper start - Anti-Xray - Add world -+ @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1) { this(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -+ public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter, @Nullable ChunkSection[] achunksection, ProtoChunkTickList protochunkticklist, ProtoChunkTickList protochunkticklist1, World world) { -+ this.world = world; -+ // Paper end - this.f = Maps.newEnumMap(HeightMap.Type.class); - this.g = ChunkStatus.EMPTY; - this.h = Maps.newHashMap(); -@@ -0,0 +0,0 @@ public class ProtoChunk implements IChunkAccess { - - public ChunkSection a(int i) { - if (this.j[i] == Chunk.a) { -- this.j[i] = new ChunkSection(i << 4); -+ this.j[i] = new ChunkSection(i << 4, this, this.world, true); // Paper - Anti-Xray - Add parameters - } - - return this.j[i]; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -@@ -0,0 +0,0 @@ public class ProtoChunkExtension extends ProtoChunk { - private final Chunk a; - - public ProtoChunkExtension(Chunk chunk) { -- super(chunk.getPos(), ChunkConverter.a); -+ super(chunk.getPos(), ChunkConverter.a, chunk.world); // Paper - Anti-Xray - Add parameter - this.a = chunk; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - byte b0 = nbttagcompound2.getByte("Y"); - - if (nbttagcompound2.hasKeyOfType("Palette", 9) && nbttagcompound2.hasKeyOfType("BlockStates", 12)) { -- ChunkSection chunksection = new ChunkSection(b0 << 4); -+ ChunkSection chunksection = new ChunkSection(b0 << 4, null, worldserver, false); // Paper - Anti-Xray - Add parameters - - chunksection.getBlocks().a(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); - chunksection.recalcBlockCounts(); -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - // CraftBukkit end - }); - } else { -- ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1); -+ ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - - protochunk.a(biomestorage); - object = protochunk; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { - private final WorldServer worldServer; - private final int x; - private final int z; -- private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0).getBlocks(); -+ private static final DataPaletteBlock emptyBlockIDs = new ChunkSection(0, null, null, true).getBlocks(); // Paper - Anti-Xray - Add parameters - private static final byte[] emptyLight = new byte[2048]; - - public CraftChunk(net.minecraft.world.level.chunk.Chunk chunk) { -@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { - NBTTagCompound data = new NBTTagCompound(); - cs[i].getBlocks().a(data, "Palette", "BlockStates"); - -- DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); // TODO: snapshot whole ChunkSection -+ DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.world.level.block.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally - blockids.a(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); - - sectionBlockIDs[i] = blockids; -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -0,0 +0,0 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private final int maxHeight; - private final ChunkSection[] sections; - private Set tiles; -+ private World world; // Paper - Anti-Xray - Add world - - public CraftChunkData(World world) { - this(world.getMaxHeight()); -+ this.world = world; // Paper - Anti-Xray - Add world - } - - /* pp for tests */ CraftChunkData(int maxHeight) { -@@ -0,0 +0,0 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - private ChunkSection getChunkSection(int y, boolean create) { - ChunkSection section = sections[y >> 4]; - if (create && section == null) { -- sections[y >> 4] = section = new ChunkSection(y >> 4 << 4); -+ sections[y >> 4] = section = new ChunkSection(y >> 4 << 4, null, world instanceof org.bukkit.craftbukkit.CraftWorld ? ((org.bukkit.craftbukkit.CraftWorld) world).getHandle() : null, true); // Paper - Anti-Xray - Add parameters - } - return section; - } diff --git a/Spigot-Server-Patches/AnvilDamageEvent.patch b/Spigot-Server-Patches/AnvilDamageEvent.patch deleted file mode 100644 index 3e0d4b69e2..0000000000 --- a/Spigot-Server-Patches/AnvilDamageEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 20 Jul 2018 23:37:03 -0500 -Subject: [PATCH] AnvilDamageEvent - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerAnvil.java -@@ -0,0 +0,0 @@ public class ContainerAnvil extends ContainerAnvilAbstract { - - if (!entityhuman.abilities.canInstantlyBuild && iblockdata.a((Tag) TagsBlock.ANVIL) && entityhuman.getRandom().nextFloat() < 0.12F) { - IBlockData iblockdata1 = BlockAnvil.c(iblockdata); -- -+ // Paper start -+ com.destroystokyo.paper.event.block.AnvilDamagedEvent event = new com.destroystokyo.paper.event.block.AnvilDamagedEvent(getBukkitView(), iblockdata1 != null ? org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(iblockdata1) : null); -+ if (!event.callEvent()) { -+ return; -+ } else if (event.getDamageState() == com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.BROKEN) { -+ iblockdata1 = null; -+ } else { -+ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().set(BlockAnvil.FACING, iblockdata.get(BlockAnvil.FACING)); -+ } -+ // Paper end - if (iblockdata1 == null) { - world.a(blockposition, false); - world.triggerEffect(1029, blockposition, 0); diff --git a/Spigot-Server-Patches/Async-command-map-building.patch b/Spigot-Server-Patches/Async-command-map-building.patch deleted file mode 100644 index ba0645dcad..0000000000 --- a/Spigot-Server-Patches/Async-command-map-building.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Wed, 8 Apr 2020 02:42:14 -0500 -Subject: [PATCH] Async command map building - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -0,0 +0,0 @@ import net.minecraft.network.chat.ChatHoverable; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatMutableComponent; - import net.minecraft.network.protocol.game.PacketPlayOutCommands; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.commands.CommandAdvancement; - import net.minecraft.server.commands.CommandAttribute; - import net.minecraft.server.commands.CommandBan; -@@ -0,0 +0,0 @@ public class CommandDispatcher { - if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot - // CraftBukkit start - // Register Vanilla commands into builtRoot as before -+ // Paper start - Async command map building -+ java.util.concurrent.ForkJoinPool.commonPool().execute(() -> { -+ sendAsync(entityplayer); -+ }); -+ } -+ -+ private void sendAsync(EntityPlayer entityplayer) { -+ // Paper end - Async command map building - Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues - RootCommandNode vanillaRoot = new RootCommandNode(); - -@@ -0,0 +0,0 @@ public class CommandDispatcher { - for (CommandNode node : rootcommandnode.getChildren()) { - bukkit.add(node.getName()); - } -+ // Paper start - Async command map building -+ MinecraftServer.getServer().execute(() -> { -+ runSync(entityplayer, bukkit, rootcommandnode); -+ }); -+ } - -+ private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { -+ // Paper end - Async command map building - PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - diff --git a/Spigot-Server-Patches/AsyncTabCompleteEvent.patch b/Spigot-Server-Patches/AsyncTabCompleteEvent.patch deleted file mode 100644 index 17de52ce5d..0000000000 --- a/Spigot-Server-Patches/AsyncTabCompleteEvent.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Nov 2017 13:19:58 -0500 -Subject: [PATCH] AsyncTabCompleteEvent - -Let plugins be able to control tab completion of commands and chat async. - -This will be useful for frameworks like ACF so we can define async safe completion handlers, -and avoid going to main for tab completions. - -Especially useful if you need to query a database in order to obtain the results for tab -completion, such as offline players. - -Also adds isCommand and getLocation to the sync TabCompleteEvent - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInTabComplete packetplayintabcomplete) { -- PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); -+ // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start - if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { -- this.disconnect(new ChatMessage("disconnect.spam", new Object[0])); -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } - // CraftBukkit end -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - stringreader.skip(); - } - -- ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); -+ // Paper start - async tab completion -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ String buffer = packetplayintabcomplete.c(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getPlayer(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server -+ if (!event.isHandled()) { -+ if (!event.isCancelled()) { - -- this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -- }); -+ this.minecraftServer.scheduleOnMain(() -> { // Paper - This needs to be on main -+ ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); -+ -+ this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -+ if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -+ }); -+ }); -+ } -+ } else if (!completions.isEmpty()) { -+ com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packetplayintabcomplete.c(), stringreader.getTotalLength()); -+ -+ builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); -+ completions.forEach(builder::suggest); -+ player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); -+ } -+ // Paper end - async tab completion - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - offers = tabCompleteChat(player, message); - } - -- TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers); -+ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPosition(pos)) : null); // Paper - getPluginManager().callEvent(tabEvent); - - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - public void complete(LineReader reader, ParsedLine line, List candidates) { - final CraftServer server = this.server.server; - final String buffer = line.line(); -+ // Async Tab Complete -+ com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; -+ java.util.List completions = new java.util.ArrayList<>(); -+ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(server.getConsoleSender(), completions, -+ buffer, true, null); -+ event.callEvent(); -+ completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); -+ -+ if (event.isCancelled() || event.isHandled()) { -+ // Still fire sync event with the provided completions, if someone is listening -+ if (!event.isCancelled() && TabCompleteEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ List finalCompletions = completions; -+ Waitable> syncCompletions = new Waitable>() { -+ @Override -+ protected List evaluate() { -+ org.bukkit.event.server.TabCompleteEvent syncEvent = new org.bukkit.event.server.TabCompleteEvent(server.getConsoleSender(), buffer, finalCompletions); -+ return syncEvent.callEvent() ? syncEvent.getCompletions() : com.google.common.collect.ImmutableList.of(); -+ } -+ }; -+ server.getServer().processQueue.add(syncCompletions); -+ try { -+ completions = syncCompletions.get(); -+ } catch (InterruptedException | ExecutionException e1) { -+ e1.printStackTrace(); -+ } -+ } -+ -+ if (!completions.isEmpty()) { -+ candidates.addAll(completions.stream().map(Candidate::new).collect(java.util.stream.Collectors.toList())); -+ } -+ return; -+ } -+ - // Paper end - Waitable> waitable = new Waitable>() { - @Override diff --git a/Spigot-Server-Patches/Asynchronous-chunk-IO-and-loading.patch b/Spigot-Server-Patches/Asynchronous-chunk-IO-and-loading.patch deleted file mode 100644 index 06c10d22ec..0000000000 --- a/Spigot-Server-Patches/Asynchronous-chunk-IO-and-loading.patch +++ /dev/null @@ -1,4203 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 13 Jul 2019 09:23:10 -0700 -Subject: [PATCH] Asynchronous chunk IO and loading - -This patch re-adds a file IO thread as well as shoving de-serializing -chunk NBT data onto worker threads. This patch also will shove -chunk data serialization onto the same worker threads when the chunk -is unloaded - this cannot be done for regular saves since that's unsafe. - -The file IO Thread - -Unlike 1.13 and below, the file IO thread is prioritized - IO tasks can -be reoredered, however they are "stuck" to a world & coordinate. - -Scheduling IO tasks works as follows, given a world & coordinate - location: - -The IO thread has been designed to ensure that reads and writes appear to -occur synchronously for a given location, however the implementation also -has the unfortunate side-effect of making every write appear as if -they occur without failure. - -The IO thread has also been designed to accomodate Mojang's decision to -store chunk data and POI data separately. It can independently schedule -tasks for each. - -However threads can wait for writes to complete and check if: - - The write was overwriten by another scheduler - - The write failed (however it does not indicate whether it was overwritten by another scheduler) - -Scheduling reads: - - - If a write task is in progress, the task is not scheduled and returns the in-progress write data - This means that readers cannot modify the NBTTagCompound returned and must clone if it they wish to write - - If a write task is not in progress but a read task is in progress, then the read task is simply chained - This means that again, readers cannot modify the NBTTagCompound returned - -Scheduling writes: - - - If a read task is in progress, ignore the read task and schedule the write - We cannot complete the read task since we assume it wants old data - not current - - If a write task is pending, overwrite the write data - The file IO thread does correctly handle cases where the data is overwritten when it - is writing data (before completing a task it will check if the data was overwritten and - will retry). - -When the file IO thread executes a task for a location, the it will -execute the read task first (if it exists), then it will execute the -write task. This ensures that, even when scheduling at different -priorities, that reads/writes for a location act synchronously. - -The downside of the file IO thread is that write failure can only be -indicated to the scheduling thread if: - -- No other thread decides to schedule another write for the location -concurrently -- The scheduling thread blocks on the write to complete (however the -current implementation can be modified to indicate success -asynchronously) - -The file io thread can be modified easily to provide indications -of write failure and write overwriting if needed. - -The upside of the file IO thread is that if a write failures, then -chunk data is not lost until server restart. This leaves more room -for spurious failure. - -Finally, the io thread will indicate to the console when reads -or writes fail - with relevant detail. - -Asynchronous chunk data serialization for unloading chunks - -When chunks unload they make a call to PlayerChunkMap#saveChunk(IChunkAccess). -Even if I make the IO asynchronous for this call, the data serialization -still hits pretty hard. And given that now the chunk system will -aggressively unload chunks more often (queued immediately at -ticket level 45 or higher), unloads occur more often, and -combined with our changes to the unload queue to make it -significantly more aggresive - chunk unloads can hit pretty hard. -Especially players running around with elytras and fireworks. - -For serializing chunk data off main, there are some tasks which cannot be -done asynchronously. Lighting data must be saved beforehand as well as -potentially some tick lists. These are completed before scheduling the -asynchronous save. - -However serializing chunk data off of the main thread is still risky. -Even though this patch schedules the save to occur after ALL references -of the chunk are removed from the world, plugins can still technically -access entities inside the chunks. For this, if the serialization task -fails for any reason, it will be re-scheduled to be serialized on the -main thread - with the hopes that the reason it failed was due to a plugin -and not an error with the save code itself. Like vanilla code - if the -serialization fails, the chunk data is lost. - -Asynchronous chunk io/loading - -Mojang's current implementation for loading chunk data off disk is -to return a CompletableFuture that will be completed by scheduling a -task to be executed on the world's chunk queue (which is only drained -on the main thread). This task will read the IO off disk and it will -apply data conversions & deserialization synchronously. Obviously -all 3 of these operations are expensive however all can be completed -asynchronously instead. - -The solution this patch uses is as follows: - -0. If an asynchronous chunk save is in progress (see above), wait -for that task to complete. It will use the serialized NBTTagCompound -created by the task. If the task fails to complete, then we would continue -with step 1. If it does not, we skip step 1. (Note: We actually load -POI data no matter what in this case). -1. Schedule an IO task to read chunk & poi data off disk. -2. The IO task will schedule a chunk load task. -3. The chunk load task executes on the async chunk loader threads -and will apply datafixers & de-serialize the chunk into a ProtoChunk -or ProtoChunkExtension. -4. The in progress chunk is then passed on to the world's chunk queue -to complete the ComletableFuture and execute any of the synchronous -tasks required to be executed by the chunk load task (i.e lighting -and some poi tasks). - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +0,0 @@ public class WorldTimingsHandler { - - public final Timing miscMobSpawning; - -+ public final Timing poiUnload; -+ public final Timing chunkUnload; -+ public final Timing poiSaveDataSerialization; -+ public final Timing chunkSave; -+ public final Timing chunkSaveOverwriteCheck; -+ public final Timing chunkSaveDataSerialization; -+ public final Timing chunkSaveIOWait; -+ public final Timing chunkUnloadPrepareSave; -+ public final Timing chunkUnloadPOISerialization; -+ public final Timing chunkUnloadDataSave; -+ - public WorldTimingsHandler(World server) { - String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; - -@@ -0,0 +0,0 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ -+ poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); -+ chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -+ poiSaveDataSerialization = Timings.ofSafe(name + "Chunk save - POI Data serialization"); -+ chunkSave = Timings.ofSafe(name + "Chunk save - Chunk"); -+ chunkSaveOverwriteCheck = Timings.ofSafe(name + "Chunk save - Chunk Overwrite Check"); -+ chunkSaveDataSerialization = Timings.ofSafe(name + "Chunk save - Chunk Data serialization"); -+ chunkSaveIOWait = Timings.ofSafe(name + "Chunk save - Chunk IO Wait"); -+ chunkUnloadPrepareSave = Timings.ofSafe(name + "Chunk unload - Async Save Prepare"); -+ chunkUnloadPOISerialization = Timings.ofSafe(name + "Chunk unload - POI Data Serialization"); -+ chunkUnloadDataSave = Timings.ofSafe(name + "Chunk unload - Data Serialization"); - } - - public static Timing getTickList(WorldServer worldserver, String timingsType) { -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -0,0 +0,0 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); - - public PaperCommand(String name) { - super(name); -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - case "debug": - doDebug(sender, args); - break; -+ case "dumpwaiting": -+ ChunkTaskManager.dumpAllChunkLoadInfo(); -+ break; - case "chunkinfo": - doChunkInfo(sender, args); - break; -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper; - -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; - import com.google.common.base.Strings; - import com.google.common.base.Throwables; - -@@ -0,0 +0,0 @@ public class PaperConfig { - maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } -+ -+ public static boolean asyncChunks = false; -+ private static void asyncChunks() { -+ ConfigurationSection section; -+ if (version < 15) { -+ section = config.createSection("settings.async-chunks"); -+ section.set("threads", -1); -+ } else { -+ section = config.getConfigurationSection("settings.async-chunks"); -+ if (section == null) { -+ section = config.createSection("settings.async-chunks"); -+ } -+ } -+ // Clean up old configs -+ if (section.contains("load-threads")) { -+ if (!section.contains("threads")) { -+ section.set("threads", section.get("load-threads")); -+ } -+ section.set("load-threads", null); -+ } -+ section.set("generation", null); -+ section.set("enabled", null); -+ section.set("thread-per-world-generation", null); -+ -+ int threads = getInt("settings.async-chunks.threads", -1); -+ int cpus = Runtime.getRuntime().availableProcessors(); -+ if (threads <= 0) { -+ threads = (int) Math.min(Integer.getInteger("paper.maxChunkThreads", 8), Math.max(1, cpus - 1)); -+ } -+ if (cpus == 1 && !Boolean.getBoolean("Paper.allowAsyncChunksSingleCore")) { -+ asyncChunks = false; -+ } else { -+ asyncChunks = true; -+ } -+ -+ // Let Shared Host set some limits -+ String sharedHostThreads = System.getenv("PAPER_ASYNC_CHUNKS_SHARED_HOST_THREADS"); -+ if (sharedHostThreads != null) { -+ try { -+ threads = Math.max(1, Math.min(threads, Integer.parseInt(sharedHostThreads))); -+ } catch (NumberFormatException ignored) {} -+ } -+ -+ if (!asyncChunks) { -+ log("Async Chunks: Disabled - Chunks will be managed synchronously, and will cause tremendous lag."); -+ } else { -+ ChunkTaskManager.initGlobalLoadThreads(threads); -+ log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/io/IOUtil.java b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/IOUtil.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io; -+ -+import org.bukkit.Bukkit; -+ -+public final class IOUtil { -+ -+ /* Copied from concrete or concurrentutil */ -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getRegionCoordinate(final int chunkCoordinate) { -+ return chunkCoordinate >> 5; -+ } -+ -+ public static int getChunkInRegion(final int chunkCoordinate) { -+ return chunkCoordinate & 31; -+ } -+ -+ public static String genericToString(final Object object) { -+ return object == null ? "null" : object.getClass().getName() + ":" + object.toString(); -+ } -+ -+ public static T notNull(final T obj) { -+ if (obj == null) { -+ throw new NullPointerException(); -+ } -+ return obj; -+ } -+ -+ public static T notNull(final T obj, final String msgIfNull) { -+ if (obj == null) { -+ throw new NullPointerException(msgIfNull); -+ } -+ return obj; -+ } -+ -+ public static void arrayBounds(final int off, final int len, final int arrayLength, final String msgPrefix) { -+ if (off < 0 || len < 0 || (arrayLength - off) < len) { -+ throw new ArrayIndexOutOfBoundsException(msgPrefix + ": off: " + off + ", len: " + len + ", array length: " + arrayLength); -+ } -+ } -+ -+ public static int getPriorityForCurrentThread() { -+ return Bukkit.isPrimaryThread() ? PrioritizedTaskQueue.HIGHEST_PRIORITY : PrioritizedTaskQueue.NORMAL_PRIORITY; -+ } -+ -+ @SuppressWarnings("unchecked") -+ public static void rethrow(final Throwable throwable) throws T { -+ throw (T)throwable; -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PaperFileIOThread.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.RegionFile; -+import org.apache.logging.log4j.Logger; -+ -+import java.io.IOException; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.function.Consumer; -+import java.util.function.Function; -+ -+/** -+ * Prioritized singleton thread responsible for all chunk IO that occurs in a minecraft server. -+ * -+ *

-+ * Singleton access: {@link Holder#INSTANCE} -+ *

-+ * -+ *

-+ * All functions provided are MT-Safe, however certain ordering constraints are (but not enforced): -+ *

  • -+ * Chunk saves may not occur for unloaded chunks. -+ *
  • -+ *
  • -+ * Tasks must be scheduled on the main thread. -+ *
  • -+ *

    -+ * -+ * @see Holder#INSTANCE -+ * @see #scheduleSave(WorldServer, int, int, NBTTagCompound, NBTTagCompound, int) -+ * @see #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean) -+ */ -+public final class PaperFileIOThread extends QueueExecutorThread { -+ -+ public static final Logger LOGGER = MinecraftServer.LOGGER; -+ public static final NBTTagCompound FAILURE_VALUE = new NBTTagCompound(); -+ -+ public static final class Holder { -+ -+ public static final PaperFileIOThread INSTANCE = new PaperFileIOThread(); -+ -+ static { -+ INSTANCE.start(); -+ } -+ } -+ -+ private final AtomicLong writeCounter = new AtomicLong(); -+ -+ private PaperFileIOThread() { -+ super(new PrioritizedTaskQueue<>(), (int)(1.0e6)); // 1.0ms spinwait time -+ this.setName("Paper RegionFile IO Thread"); -+ this.setPriority(Thread.NORM_PRIORITY - 1); // we keep priority close to normal because threads can wait on us -+ this.setUncaughtExceptionHandler((final Thread unused, final Throwable thr) -> { -+ LOGGER.fatal("Uncaught exception thrown from IO thread, report this!", thr); -+ }); -+ } -+ -+ /* run() is implemented by superclass */ -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures. When writes fail the data is kept so future reads will actually -+ * read the failed write data. This should hopefully act as a way to prevent data loss for spurious fails for writing data. -+ * -+ */ -+ -+ /** -+ * Attempts to bump the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to try to bump to -+ */ -+ public void bumpPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.raisePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.raisePriority(priority); -+ } -+ } -+ -+ public NBTTagCompound getPendingWrite(final WorldServer world, final int chunkX, final int chunkZ, final boolean poiData) { -+ final ChunkDataController taskController = poiData ? world.poiDataController : world.chunkDataController; -+ -+ final ChunkDataTask dataTask = taskController.tasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ -+ if (dataTask == null) { -+ return null; -+ } -+ -+ final ChunkDataController.InProgressWrite write = dataTask.inProgressWrite; -+ -+ if (write == null) { -+ return null; -+ } -+ -+ return write.data; -+ } -+ -+ /** -+ * Sets the priority of all IO tasks for the given chunk coordinates. This has no effect if no tasks are queued. -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level to set to -+ */ -+ public void setPriority(final WorldServer world, final int chunkX, final int chunkZ, final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final Long key = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ final ChunkDataTask poiTask = world.poiDataController.tasks.get(key); -+ final ChunkDataTask chunkTask = world.chunkDataController.tasks.get(key); -+ -+ if (poiTask != null) { -+ poiTask.updatePriority(priority); -+ } -+ if (chunkTask != null) { -+ chunkTask.updatePriority(priority); -+ } -+ } -+ -+ /** -+ * Schedules the chunk data to be written asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * This function presumes a chunk load for the coordinates is not called during this function (anytime after is OK). This means -+ * saves must be scheduled before a chunk is unloaded. -+ *
  • -+ *
  • -+ * Writes may be called concurrently, although only the "later" write will go through. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param poiData Chunk point of interest data. If {@code null}, then no poi data is saved. -+ * @param chunkData Chunk data. If {@code null}, then no chunk data is saved. -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @throws IllegalArgumentException If both {@code poiData} and {@code chunkData} are {@code null}. -+ * @throws IllegalStateException If the file io thread has shutdown. -+ */ -+ public void scheduleSave(final WorldServer world, final int chunkX, final int chunkZ, -+ final NBTTagCompound poiData, final NBTTagCompound chunkData, -+ final int priority) throws IllegalArgumentException { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ final long writeCounter = this.writeCounter.getAndIncrement(); -+ -+ if (poiData != null) { -+ this.scheduleWrite(world.poiDataController, world, chunkX, chunkZ, poiData, priority, writeCounter); -+ } -+ if (chunkData != null) { -+ this.scheduleWrite(world.chunkDataController, world, chunkX, chunkZ, chunkData, priority, writeCounter); -+ } -+ } -+ -+ private void scheduleWrite(final ChunkDataController dataController, final WorldServer world, -+ final int chunkX, final int chunkZ, final NBTTagCompound data, final int priority, final long writeCounter) { -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask taskRunning) -> { -+ if (taskRunning == null) { -+ // no task is scheduled -+ -+ // create task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ newTask.inProgressWrite.writeCounter = writeCounter; -+ newTask.inProgressWrite.data = data; -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule -+ return newTask; -+ } -+ -+ taskRunning.raisePriority(priority); -+ -+ if (taskRunning.inProgressWrite == null) { -+ taskRunning.inProgressWrite = new ChunkDataController.InProgressWrite(); -+ } -+ -+ boolean reschedule = taskRunning.inProgressWrite.writeCounter == -1L; -+ -+ // synchronize for readers -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (taskRunning) { -+ taskRunning.inProgressWrite.data = data; -+ taskRunning.inProgressWrite.writeCounter = writeCounter; -+ } -+ -+ if (reschedule) { -+ // We need to reschedule this task since the previous one is not currently scheduled since it failed -+ taskRunning.reschedule(priority); -+ } -+ -+ return taskRunning; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * a {@link CompletableFuture} which is potentially completed ASYNCHRONOUSLY ON THE FILE IO THREAD when the load task -+ * has completed. -+ *

    -+ * Note that if the chunk fails to load the returned future is completed with {@code null}. -+ *

    -+ */ -+ public CompletableFuture loadChunkDataAsyncFuture(final WorldServer world, final int chunkX, final int chunkZ, -+ final int priority, final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ final CompletableFuture future = new CompletableFuture<>(); -+ this.loadChunkDataAsync(world, chunkX, chunkZ, priority, future::complete, readPoiData, readChunkData, intendingToBlock); -+ return future; -+ } -+ -+ /** -+ * Schedules a load to be executed asynchronously. -+ *

    -+ * Impl notes: -+ *

    -+ *
  • -+ * If a chunk fails to load, the {@code onComplete} parameter is completed with {@code null}. -+ *
  • -+ *
  • -+ * It is possible for the {@code onComplete} parameter to be given {@link ChunkData} containing data -+ * this call did not request. -+ *
  • -+ *
  • -+ * The {@code onComplete} parameter may be completed during the execution of this function synchronously or it may -+ * be completed asynchronously on this file io thread. Interacting with the file IO thread in the completion of -+ * data is undefined behaviour, and can cause deadlock. -+ *
  • -+ * @param world Chunk's world -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority level for this task. See {@link PrioritizedTaskQueue} -+ * @param onComplete Consumer to execute once this task has completed -+ * @param readPoiData Whether to read point of interest data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @param readChunkData Whether to read chunk data. If {@code false}, the {@code NBTTagCompound} will be {@code null}. -+ * @return The {@link PrioritizedTaskQueue.PrioritizedTask} associated with this task. Note that this task does not support -+ * cancellation. -+ */ -+ public void loadChunkDataAsync(final WorldServer world, final int chunkX, final int chunkZ, -+ final int priority, final Consumer onComplete, -+ final boolean readPoiData, final boolean readChunkData, -+ final boolean intendingToBlock) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority: " + priority); -+ } -+ -+ if (!(readPoiData | readChunkData)) { -+ throw new IllegalArgumentException("Must read chunk data or poi data"); -+ } -+ -+ final ChunkData complete = new ChunkData(); -+ final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; -+ -+ if (readPoiData) { -+ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final NBTTagCompound poiData) -> { -+ complete.poiData = poiData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[0] = false; // 0 -> poi data -+ finished = !requireCompletion[1]; // 1 -> chunk data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ if (readChunkData) { -+ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final NBTTagCompound chunkData) -> { -+ complete.chunkData = chunkData; -+ -+ final boolean finished; -+ -+ // avoid a race condition where the file io thread completes and we complete synchronously -+ // Note: Synchronization can be elided if both of the accesses are volatile -+ synchronized (requireCompletion) { -+ requireCompletion[1] = false; // 1 -> chunk data -+ finished = !requireCompletion[0]; // 0 -> poi data -+ } -+ -+ if (finished) { -+ onComplete.accept(complete); -+ } -+ }, priority, intendingToBlock); -+ } -+ -+ } -+ -+ // Note: the onComplete may be called asynchronously or synchronously here. -+ private void scheduleRead(final ChunkDataController dataController, final WorldServer world, -+ final int chunkX, final int chunkZ, final Consumer onComplete, final int priority, -+ final boolean intendingToBlock) { -+ -+ Function tryLoadFunction = (final RegionFile file) -> { -+ if (file == null) { -+ return Boolean.TRUE; -+ } -+ return Boolean.valueOf(file.chunkExists(new ChunkCoordIntPair(chunkX, chunkZ))); -+ }; -+ -+ dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { -+ if (running == null) { -+ // not scheduled -+ -+ final Boolean shouldSchedule = intendingToBlock ? dataController.computeForRegionFile(chunkX, chunkZ, tryLoadFunction) : -+ dataController.computeForRegionFileIfLoaded(chunkX, chunkZ, tryLoadFunction); -+ -+ if (shouldSchedule == Boolean.FALSE) { -+ // not on disk -+ onComplete.accept(null); -+ return null; -+ } -+ -+ // set up task -+ final ChunkDataTask newTask = new ChunkDataTask(priority, world, chunkX, chunkZ, dataController); -+ newTask.inProgressRead = new ChunkDataController.InProgressRead(); -+ newTask.inProgressRead.readFuture.thenAccept(onComplete); -+ -+ PaperFileIOThread.this.queueTask(newTask); // schedule task -+ return newTask; -+ } -+ -+ running.raisePriority(priority); -+ -+ if (running.inProgressWrite == null) { -+ // chain to the read future -+ running.inProgressRead.readFuture.thenAccept(onComplete); -+ return running; -+ } -+ -+ // at this stage we have to use the in progress write's data to avoid an order issue -+ // we don't synchronize since all writes to data occur in the compute() call -+ onComplete.accept(running.inProgressWrite.data); -+ return running; -+ }); -+ } -+ -+ /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns -+ * the {@link ChunkData} associated with the specified chunk when the task is complete. -+ * @return The chunk data, or {@code null} if the chunk failed to load. -+ */ -+ public ChunkData loadChunkData(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final boolean readPoiData, final boolean readChunkData) { -+ return this.loadChunkDataAsyncFuture(world, chunkX, chunkZ, priority, readPoiData, readChunkData, true).join(); -+ } -+ -+ /** -+ * Schedules the given task at the specified priority to be executed on the IO thread. -+ *

    -+ * Internal api. Do not use. -+ *

    -+ */ -+ public void runTask(final int priority, final Runnable runnable) { -+ this.queueTask(new GeneralTask(priority, runnable)); -+ } -+ -+ static final class GeneralTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ private final Runnable run; -+ -+ public GeneralTask(final int priority, final Runnable run) { -+ super(priority); -+ this.run = IOUtil.notNull(run, "Task may not be null"); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.run.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Failed to execute general task on IO thread " + IOUtil.genericToString(this.run), throwable); -+ } -+ } -+ } -+ -+ public static final class ChunkData { -+ -+ public NBTTagCompound poiData; -+ public NBTTagCompound chunkData; -+ -+ public ChunkData() {} -+ -+ public ChunkData(final NBTTagCompound poiData, final NBTTagCompound chunkData) { -+ this.poiData = poiData; -+ this.chunkData = chunkData; -+ } -+ } -+ -+ public static abstract class ChunkDataController { -+ -+ // ConcurrentHashMap synchronizes per chain, so reduce the chance of task's hashes colliding. -+ public final ConcurrentHashMap tasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ public abstract void writeData(final int x, final int z, final NBTTagCompound compound) throws IOException; -+ public abstract NBTTagCompound readData(final int x, final int z) throws IOException; -+ -+ public abstract T computeForRegionFile(final int chunkX, final int chunkZ, final Function function); -+ public abstract T computeForRegionFileIfLoaded(final int chunkX, final int chunkZ, final Function function); -+ -+ public static final class InProgressWrite { -+ public long writeCounter; -+ public NBTTagCompound data; -+ } -+ -+ public static final class InProgressRead { -+ public final CompletableFuture readFuture = new CompletableFuture<>(); -+ } -+ } -+ -+ public static final class ChunkDataTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public ChunkDataController.InProgressWrite inProgressWrite; -+ public ChunkDataController.InProgressRead inProgressRead; -+ -+ private final WorldServer world; -+ private final int x; -+ private final int z; -+ private final ChunkDataController taskController; -+ -+ public ChunkDataTask(final int priority, final WorldServer world, final int x, final int z, final ChunkDataController taskController) { -+ super(priority); -+ this.world = world; -+ this.x = x; -+ this.z = z; -+ this.taskController = taskController; -+ } -+ -+ @Override -+ public String toString() { -+ return "Task for world: '" + this.world.getWorld().getName() + "' at " + this.x + "," + this.z + -+ " poi: " + (this.taskController == this.world.poiDataController) + ", hash: " + this.hashCode(); -+ } -+ -+ /* -+ * -+ * IO thread will perform reads before writes -+ * -+ * How reads/writes are scheduled: -+ * -+ * If read in progress while scheduling write, ignore read and schedule write -+ * If read in progress while scheduling read (no write in progress), chain the read task -+ * -+ * -+ * If write in progress while scheduling read, use the pending write data and ret immediately -+ * If write in progress while scheduling write (ignore read in progress), overwrite the write in progress data -+ * -+ * This allows the reads and writes to act as if they occur synchronously to the thread scheduling them, however -+ * it fails to properly propagate write failures -+ * -+ */ -+ -+ void reschedule(final int priority) { -+ // priority is checked before this stage // TODO what -+ this.queue.lazySet(null); -+ this.priority.lazySet(priority); -+ PaperFileIOThread.Holder.INSTANCE.queueTask(this); -+ } -+ -+ @Override -+ public void run() { -+ ChunkDataController.InProgressRead read = this.inProgressRead; -+ if (read != null) { -+ NBTTagCompound compound = PaperFileIOThread.FAILURE_VALUE; -+ try { -+ compound = this.taskController.readData(this.x, this.z); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to read chunk data for task: " + this.toString(), thr); -+ // fall through to complete with null data -+ } -+ read.readFuture.complete(compound); -+ } -+ -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(this.x, this.z)); -+ -+ ChunkDataController.InProgressWrite write = this.inProgressWrite; -+ -+ if (write == null) { -+ // IntelliJ warns this is invalid, however it does not consider that writes to the task map & the inProgress field can occur concurrently. -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ return valueInMap.inProgressWrite == null ? null : valueInMap; -+ }); -+ -+ if (inMap == null) { -+ return; // set the task value to null, indicating we're done -+ } -+ -+ // not null, which means there was a concurrent write -+ write = this.inProgressWrite; -+ } -+ -+ // check if another process is writing -+ /*try { TODO: Can we restore this? -+ ((WorldServer)this.world).checkSession(); -+ } catch (final Exception ex) { -+ LOGGER.fatal("Couldn't save chunk; already in use by another instance of Minecraft?", ex); -+ // we don't need to set the write counter to -1 as we know at this stage there's no point in re-scheduling -+ // writes since they'll fail anyways. -+ return; -+ } -+*/ -+ for (;;) { -+ final long writeCounter; -+ final NBTTagCompound data; -+ -+ //noinspection SynchronizationOnLocalVariableOrMethodParameter -+ synchronized (write) { -+ writeCounter = write.writeCounter; -+ data = write.data; -+ } -+ -+ boolean failedWrite = false; -+ -+ try { -+ this.taskController.writeData(this.x, this.z, data); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ LOGGER.fatal("Failed to write chunk data for task: " + this.toString(), thr); -+ failedWrite = true; -+ } -+ -+ boolean finalFailWrite = failedWrite; -+ -+ ChunkDataTask inMap = this.taskController.tasks.compute(chunkKey, (final Long keyInMap, final ChunkDataTask valueInMap) -> { -+ if (valueInMap == null) { -+ throw new IllegalStateException("Write completed concurrently, expected this task: " + ChunkDataTask.this.toString() + ", report this!"); -+ } -+ if (valueInMap != ChunkDataTask.this) { -+ throw new IllegalStateException("Chunk task mismatch, expected this task: " + ChunkDataTask.this.toString() + ", got: " + valueInMap.toString() + ", report this!"); -+ } -+ if (valueInMap.inProgressWrite.writeCounter == writeCounter) { -+ if (finalFailWrite) { -+ valueInMap.inProgressWrite.writeCounter = -1L; -+ } -+ -+ return null; -+ } -+ return valueInMap; -+ // Hack end -+ }); -+ -+ if (inMap == null) { -+ // write counter matched, so we wrote the most up-to-date pending data, we're done here -+ // or we failed to write and successfully set the write counter to -1 -+ return; // we're done here -+ } -+ -+ // fetch & write new data -+ continue; -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/PrioritizedTaskQueue.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicReference; -+ -+public class PrioritizedTaskQueue { -+ -+ // lower numbers are a higher priority (except < 0) -+ // higher priorities are always executed before lower priorities -+ -+ /** -+ * Priority value indicating the task has completed or is being completed. -+ */ -+ public static final int COMPLETING_PRIORITY = -1; -+ -+ /** -+ * Highest priority, should only be used for main thread tasks or tasks that are blocking the main thread. -+ */ -+ public static final int HIGHEST_PRIORITY = 0; -+ -+ /** -+ * Should be only used in an IO task so that chunk loads do not wait on other IO tasks. -+ * This only exists because IO tasks are scheduled before chunk load tasks to decrease IO waiting times. -+ */ -+ public static final int HIGHER_PRIORITY = 1; -+ -+ /** -+ * Should be used for scheduling chunk loads/generation that would increase response times to users. -+ */ -+ public static final int HIGH_PRIORITY = 2; -+ -+ /** -+ * Default priority. -+ */ -+ public static final int NORMAL_PRIORITY = 3; -+ -+ /** -+ * Use for tasks not at all critical and can potentially be delayed. -+ */ -+ public static final int LOW_PRIORITY = 4; -+ -+ /** -+ * Use for tasks that should "eventually" execute. -+ */ -+ public static final int LOWEST_PRIORITY = 5; -+ -+ private static final int TOTAL_PRIORITIES = 6; -+ -+ final ConcurrentLinkedQueue[] queues = (ConcurrentLinkedQueue[])new ConcurrentLinkedQueue[TOTAL_PRIORITIES]; -+ -+ private final AtomicBoolean shutdown = new AtomicBoolean(); -+ -+ { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ this.queues[i] = new ConcurrentLinkedQueue<>(); -+ } -+ } -+ -+ /** -+ * Returns whether the specified priority is valid -+ */ -+ public static boolean validPriority(final int priority) { -+ return priority >= 0 && priority < TOTAL_PRIORITIES; -+ } -+ -+ /** -+ * Queues a task. -+ * @throws IllegalStateException If the task has already been queued. Use {@link PrioritizedTask#raisePriority(int)} to -+ * raise a task's priority. -+ * This can also be thrown if the queue has shutdown. -+ */ -+ public void add(final T task) throws IllegalStateException { -+ int priority = task.getPriority(); -+ if (priority != COMPLETING_PRIORITY) { -+ task.setQueue(this); -+ this.queues[priority].add(task); -+ } -+ if (this.shutdown.get()) { -+ // note: we're not actually sure at this point if our task will go through -+ throw new IllegalStateException("Queue has shutdown, refusing to execute task " + IOUtil.genericToString(task)); -+ } -+ } -+ -+ /** -+ * Polls the highest priority task currently available. {@code null} if none. -+ */ -+ public T poll() { -+ T task; -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ while ((task = queue.poll()) != null) { -+ final int prevPriority = task.tryComplete(i); -+ if (prevPriority != COMPLETING_PRIORITY && prevPriority <= i) { -+ // if the prev priority was greater-than or equal to our current priority -+ return task; -+ } -+ } -+ } -+ -+ return null; -+ } -+ -+ /** -+ * Returns whether this queue may have tasks queued. -+ *

    -+ * This operation is not atomic, but is MT-Safe. -+ *

    -+ * @return {@code true} if tasks may be queued, {@code false} otherwise -+ */ -+ public boolean hasTasks() { -+ for (int i = 0; i < TOTAL_PRIORITIES; ++i) { -+ final ConcurrentLinkedQueue queue = this.queues[i]; -+ -+ if (queue.peek() != null) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ /** -+ * Prevent further additions to this queue. Attempts to add after this call has completed (potentially during) will -+ * result in {@link IllegalStateException} being thrown. -+ *

    -+ * This operation is atomic with respect to other shutdown calls -+ *

    -+ *

    -+ * After this call has completed, regardless of return value, this queue will be shutdown. -+ *

    -+ * @return {@code true} if the queue was shutdown, {@code false} if it has shut down already -+ */ -+ public boolean shutdown() { -+ return this.shutdown.getAndSet(false); -+ } -+ -+ public abstract static class PrioritizedTask { -+ -+ protected final AtomicReference queue = new AtomicReference<>(); -+ -+ protected final AtomicInteger priority; -+ -+ protected PrioritizedTask() { -+ this(PrioritizedTaskQueue.NORMAL_PRIORITY); -+ } -+ -+ protected PrioritizedTask(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority " + priority); -+ } -+ this.priority = new AtomicInteger(priority); -+ } -+ -+ /** -+ * Returns the current priority. Note that {@link PrioritizedTaskQueue#COMPLETING_PRIORITY} will be returned -+ * if this task is completing or has completed. -+ */ -+ public final int getPriority() { -+ return this.priority.get(); -+ } -+ -+ /** -+ * Returns whether this task is scheduled to execute, or has been already executed. -+ */ -+ public boolean isScheduled() { -+ return this.queue.get() != null; -+ } -+ -+ final int tryComplete(final int minPriority) { -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return COMPLETING_PRIORITY; -+ } -+ if (curr > minPriority) { -+ // curr is lower priority -+ return curr; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, COMPLETING_PRIORITY))) { -+ return curr; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Forces this task to be completed. -+ * @return {@code true} if the task was cancelled, {@code false} if the task has already completed or is being completed. -+ */ -+ public boolean cancel() { -+ return this.exchangePriorityVolatile(PrioritizedTaskQueue.COMPLETING_PRIORITY) != PrioritizedTaskQueue.COMPLETING_PRIORITY; -+ } -+ -+ /** -+ * Attempts to raise the priority to the priority level specified. -+ * @param priority Priority specified -+ * @return {@code true} if successful, {@code false} otherwise. -+ */ -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (priority >= curr) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ /** -+ * Attempts to set this task's priority level to the level specified. -+ * @param priority Specified priority level. -+ * @return {@code true} if successful, {@code false} if this task is completing or has completed. -+ */ -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalArgumentException("Invalid priority"); -+ } -+ -+ for (int curr = this.getPriorityVolatile();;) { -+ if (curr == COMPLETING_PRIORITY) { -+ return false; -+ } -+ if (curr == priority) { -+ return true; -+ } -+ -+ if (curr == (curr = this.compareAndExchangePriorityVolatile(curr, priority))) { -+ PrioritizedTaskQueue queue = this.queue.get(); -+ if (queue != null) { -+ //noinspection unchecked -+ queue.queues[priority].add(this); // silently fail on shutdown -+ } -+ return true; -+ } -+ continue; -+ } -+ } -+ -+ void setQueue(final PrioritizedTaskQueue queue) { -+ this.queue.set(queue); -+ } -+ -+ /* priority */ -+ -+ protected final int getPriorityVolatile() { -+ return this.priority.get(); -+ } -+ -+ protected final int compareAndExchangePriorityVolatile(final int expect, final int update) { -+ if (this.priority.compareAndSet(expect, update)) { -+ return expect; -+ } -+ return this.priority.get(); -+ } -+ -+ protected final int exchangePriorityVolatile(final int value) { -+ return this.priority.getAndSet(value); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/QueueExecutorThread.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io; -+ -+import net.minecraft.server.MinecraftServer; -+import org.apache.logging.log4j.Logger; -+ -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.concurrent.locks.LockSupport; -+ -+public class QueueExecutorThread extends Thread { -+ -+ private static final Logger LOGGER = MinecraftServer.LOGGER; -+ -+ protected final PrioritizedTaskQueue queue; -+ protected final long spinWaitTime; -+ -+ protected volatile boolean closed; -+ -+ protected final AtomicBoolean parked = new AtomicBoolean(); -+ -+ protected volatile ConcurrentLinkedQueue flushQueue = new ConcurrentLinkedQueue<>(); -+ protected volatile long flushCycles; -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue) { -+ this(queue, (int)(1.e6)); // 1.0ms -+ } -+ -+ public QueueExecutorThread(final PrioritizedTaskQueue queue, final long spinWaitTime) { // in ms -+ this.queue = queue; -+ this.spinWaitTime = spinWaitTime; -+ } -+ -+ @Override -+ public void run() { -+ final long spinWaitTime = this.spinWaitTime; -+ main_loop: -+ for (;;) { -+ this.pollTasks(true); -+ -+ // spinwait -+ -+ final long start = System.nanoTime(); -+ -+ for (;;) { -+ // If we are interrpted for any reason, park() will always return immediately. Clear so that we don't needlessly use cpu in such an event. -+ Thread.interrupted(); -+ LockSupport.parkNanos("Spinwaiting on tasks", 1000L); // 1us -+ -+ if (this.pollTasks(true)) { -+ // restart loop, found tasks -+ continue main_loop; -+ } -+ -+ if (this.handleClose()) { -+ return; // we're done -+ } -+ -+ if ((System.nanoTime() - start) >= spinWaitTime) { -+ break; -+ } -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ this.parked.set(true); -+ -+ // We need to parse here to avoid a race condition where a thread queues a task before we set parked to true -+ // (i.e it will not notify us) -+ if (this.pollTasks(true)) { -+ this.parked.set(false); -+ continue; -+ } -+ -+ if (this.handleClose()) { -+ return; -+ } -+ -+ // we don't need to check parked before sleeping, but we do need to check parked in a do-while loop -+ // LockSupport.park() can fail for any reason -+ do { -+ Thread.interrupted(); -+ LockSupport.park("Waiting on tasks"); -+ } while (this.parked.get()); -+ } -+ } -+ -+ protected boolean handleClose() { -+ if (this.closed) { -+ this.pollTasks(true); // this ensures we've emptied the queue -+ this.handleFlushThreads(true); -+ return true; -+ } -+ return false; -+ } -+ -+ protected boolean pollTasks(boolean flushTasks) { -+ Runnable task; -+ boolean ret = false; -+ -+ while ((task = this.queue.poll()) != null) { -+ ret = true; -+ try { -+ task.run(); -+ } catch (final Throwable throwable) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ LOGGER.fatal("Exception thrown from prioritized runnable task in thread '" + this.getName() + "': " + IOUtil.genericToString(task), throwable); -+ } -+ } -+ -+ if (flushTasks) { -+ this.handleFlushThreads(false); -+ } -+ -+ return ret; -+ } -+ -+ protected void handleFlushThreads(final boolean shutdown) { -+ Thread parking; -+ ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ do { -+ ++flushCycles; // may be plain read opaque write -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } while (this.pollTasks(false)); -+ -+ if (shutdown) { -+ this.flushQueue = null; -+ -+ // defend against a race condition where a flush thread double-checks right before we set to null -+ while ((parking = flushQueue.poll()) != null) { -+ LockSupport.unpark(parking); -+ } -+ } -+ } -+ -+ /** -+ * Notify's this thread that a task has been added to its queue -+ * @return {@code true} if this thread was waiting for tasks, {@code false} if it is executing tasks -+ */ -+ public boolean notifyTasks() { -+ if (this.parked.get() && this.parked.getAndSet(false)) { -+ LockSupport.unpark(this); -+ return true; -+ } -+ return false; -+ } -+ -+ protected void queueTask(final T task) { -+ this.queue.add(task); -+ this.notifyTasks(); -+ } -+ -+ /** -+ * Waits until this thread's queue is empty. -+ * -+ * @throws IllegalStateException If the current thread is {@code this} thread. -+ */ -+ public void flush() { -+ final Thread currentThread = Thread.currentThread(); -+ -+ if (currentThread == this) { -+ // avoid deadlock -+ throw new IllegalStateException("Cannot flush the queue executor thread while on the queue executor thread"); -+ } -+ -+ // order is important -+ -+ int successes = 0; -+ long lastCycle = -1L; -+ -+ do { -+ final ConcurrentLinkedQueue flushQueue = this.flushQueue; -+ if (flushQueue == null) { -+ return; -+ } -+ -+ flushQueue.add(currentThread); -+ -+ // double check flush queue -+ if (this.flushQueue == null) { -+ return; -+ } -+ -+ final long currentCycle = this.flushCycles; // may be opaque read -+ -+ if (currentCycle == lastCycle) { -+ Thread.yield(); -+ continue; -+ } -+ -+ // force response -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ LockSupport.park("flushing queue executor thread"); -+ -+ // returns whether there are tasks queued, does not return whether there are tasks executing -+ // this is why we cycle twice twice through flush (we know a pollTask call is made after a flush cycle) -+ // we really only need to guarantee that the tasks this thread has queued has gone through, and can leave -+ // tasks queued concurrently that are unsychronized with this thread as undefined behavior -+ if (this.queue.hasTasks()) { -+ successes = 0; -+ } else { -+ ++successes; -+ } -+ -+ } while (successes != 2); -+ -+ } -+ -+ /** -+ * Closes this queue executor's queue and optionally waits for it to empty. -+ *

    -+ * If wait is {@code true}, then the queue will be empty by the time this call completes. -+ *

    -+ *

    -+ * This function is MT-Safe. -+ *

    -+ * @param wait If this call is to wait until the queue is empty -+ * @param killQueue Whether to shutdown this thread's queue -+ * @return whether this thread shut down the queue -+ */ -+ public boolean close(final boolean wait, final boolean killQueue) { -+ boolean ret = !killQueue ? false : this.queue.shutdown(); -+ this.closed = true; -+ -+ // force thread to respond to the shutdown -+ this.parked.set(false); -+ LockSupport.unpark(this); -+ -+ if (wait) { -+ this.flush(); -+ } -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkLoadTask.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+ -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+ -+public final class ChunkLoadTask extends ChunkTask { -+ -+ public boolean cancelled; -+ -+ Consumer onComplete; -+ public PaperFileIOThread.ChunkData chunkData; -+ -+ private boolean hasCompleted; -+ -+ public ChunkLoadTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, -+ final Consumer onComplete) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.onComplete = onComplete; -+ } -+ -+ private static final ArrayDeque EMPTY_QUEUE = new ArrayDeque<>(); -+ -+ private static ChunkRegionLoader.InProgressChunkHolder createEmptyHolder() { -+ return new ChunkRegionLoader.InProgressChunkHolder(null, EMPTY_QUEUE); -+ } -+ -+ @Override -+ public void run() { -+ try { -+ this.executeTask(); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Failed to execute chunk load task: " + this.toString(), ex); -+ if (!this.hasCompleted) { -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ } -+ } -+ -+ private boolean checkCancelled() { -+ if (this.cancelled) { -+ // IntelliJ does not understand writes may occur to cancelled concurrently. -+ return this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ return valueInMap; -+ }) == null; -+ } -+ return false; -+ } -+ -+ public void executeTask() { -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ // either executed synchronously or asynchronously -+ final PaperFileIOThread.ChunkData chunkData = this.chunkData; -+ -+ if (chunkData.poiData == PaperFileIOThread.FAILURE_VALUE || chunkData.chunkData == PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.LOGGER.error("Could not load chunk for task: " + this.toString() + ", file IO thread has dumped the relevant exception above"); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ if (chunkData.chunkData == null) { -+ // not on disk -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(this.chunkX, this.chunkZ); -+ -+ final PlayerChunkMap chunkManager = this.world.getChunkProvider().playerChunkMap; -+ -+ try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { -+ final ChunkRegionLoader.InProgressChunkHolder chunkHolder; -+ -+ // apply fixes -+ -+ try { -+ chunkData.chunkData = chunkManager.getChunkData(this.world.getTypeKey(), -+ chunkManager.getWorldPersistentDataSupplier(), chunkData.chunkData, chunkPos, this.world); // clone data for safety, file IO thread does not clone -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not apply datafixers for chunk task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ } -+ -+ if (this.checkCancelled()) { -+ return; -+ } -+ -+ try { -+ this.world.getChunkProvider().playerChunkMap.updateChunkStatusOnDisk(chunkPos, chunkData.chunkData); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.warn("Failed to update chunk status cache for task: " + this.toString(), ex); -+ // non-fatal, continue -+ } -+ -+ try { -+ chunkHolder = ChunkRegionLoader.loadChunk(this.world, -+ chunkManager.definedStructureManager, chunkManager.getVillagePlace(), chunkPos, -+ chunkData.chunkData, true); -+ } catch (final Throwable ex) { -+ PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); -+ this.complete(ChunkLoadTask.createEmptyHolder()); -+ return; -+ } -+ -+ this.complete(chunkHolder); -+ } -+ } -+ -+ private void complete(final ChunkRegionLoader.InProgressChunkHolder holder) { -+ this.hasCompleted = true; -+ holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; -+ -+ this.taskManager.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != ChunkLoadTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", current: " + ChunkLoadTask.this); -+ } -+ if (valueInMap.cancelled) { -+ return null; -+ } -+ try { -+ ChunkLoadTask.this.onComplete.accept(holder); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkSaveTask.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import co.aikar.timings.Timing; -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+ -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.atomic.AtomicInteger; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+ -+public final class ChunkSaveTask extends ChunkTask { -+ -+ public final ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ public final IChunkAccess chunk; -+ public final CompletableFuture onComplete = new CompletableFuture<>(); -+ -+ private final AtomicInteger attemptedPriority; -+ -+ public ChunkSaveTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager, final ChunkRegionLoader.AsyncSaveData asyncSaveData, -+ final IChunkAccess chunk) { -+ super(world, chunkX, chunkZ, priority, taskManager); -+ this.chunk = chunk; -+ this.asyncSaveData = asyncSaveData; -+ this.attemptedPriority = new AtomicInteger(priority); -+ } -+ -+ @Override -+ public void run() { -+ // can be executed asynchronously or synchronously -+ final NBTTagCompound compound; -+ -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { -+ compound = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ } catch (final Throwable ex) { -+ // has a plugin modified something it should not have and made us CME? -+ PaperFileIOThread.LOGGER.error("Failed to serialize unloading chunk data for task: " + this.toString() + ", falling back to a synchronous execution", ex); -+ -+ // Note: We add to the server thread queue here since this is what the server will drain tasks from -+ // when waiting for chunks -+ ChunkTaskManager.queueChunkWaitTask(() -> { -+ try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { -+ NBTTagCompound data = PaperFileIOThread.FAILURE_VALUE; -+ -+ try { -+ data = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); -+ PaperFileIOThread.LOGGER.info("Successfully serialized chunk data for task: " + this.toString() + " synchronously"); -+ } catch (final Throwable ex1) { -+ PaperFileIOThread.LOGGER.fatal("Failed to synchronously serialize unloading chunk data for task: " + this.toString() + "! Chunk data will be lost", ex1); -+ } -+ -+ ChunkSaveTask.this.complete(data); -+ } -+ }); -+ -+ return; // the main thread will now complete the data -+ } -+ -+ this.complete(compound); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ -+ // we know priority is valid here -+ for (int curr = this.attemptedPriority.get();;) { -+ if (curr <= priority) { -+ break; // curr is higher/same priority -+ } -+ if (this.attemptedPriority.compareAndSet(curr, priority)) { -+ break; -+ } -+ curr = this.attemptedPriority.get(); -+ } -+ -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ if (!PrioritizedTaskQueue.validPriority(priority)) { -+ throw new IllegalStateException("Invalid priority: " + priority); -+ } -+ this.attemptedPriority.set(priority); -+ return super.updatePriority(priority); -+ } -+ -+ private void complete(final NBTTagCompound compound) { -+ try { -+ this.onComplete.complete(compound); -+ } catch (final Throwable thr) { -+ PaperFileIOThread.LOGGER.error("Failed to complete chunk data for task: " + this.toString(), thr); -+ } -+ if (compound != PaperFileIOThread.FAILURE_VALUE) { -+ PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, this.chunkX, this.chunkZ, null, compound, this.attemptedPriority.get()); -+ } -+ this.taskManager.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(this.chunkX, this.chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != ChunkSaveTask.this) { -+ throw new IllegalStateException("Expected this task to be scheduled, but another was! Other: " + valueInMap + ", this: " + ChunkSaveTask.this); -+ } -+ return null; -+ }); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTask.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import net.minecraft.server.level.WorldServer; -+ -+abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { -+ -+ public final WorldServer world; -+ public final int chunkX; -+ public final int chunkZ; -+ public final ChunkTaskManager taskManager; -+ -+ public ChunkTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, -+ final ChunkTaskManager taskManager) { -+ super(priority); -+ this.world = world; -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.taskManager = taskManager; -+ } -+ -+ @Override -+ public String toString() { -+ return "Chunk task: class:" + this.getClass().getName() + ", for world '" + this.world.getWorld().getName() + -+ "', (" + this.chunkX + "," + this.chunkZ + "), hashcode:" + this.hashCode() + ", priority: " + this.getPriority(); -+ } -+ -+ @Override -+ public boolean raisePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.bumpPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.raisePriority(priority); -+ } -+ -+ @Override -+ public boolean updatePriority(final int priority) { -+ PaperFileIOThread.Holder.INSTANCE.setPriority(this.world, this.chunkX, this.chunkZ, priority); -+ return super.updatePriority(priority); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io.chunk; -+ -+import com.destroystokyo.paper.io.PaperFileIOThread; -+import com.destroystokyo.paper.io.IOUtil; -+import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import com.destroystokyo.paper.io.QueueExecutorThread; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.util.thread.IAsyncTaskHandler; -+import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; -+import org.apache.commons.lang.StringUtils; -+import org.apache.logging.log4j.Level; -+import org.bukkit.Bukkit; -+import org.spigotmc.AsyncCatcher; -+ -+import java.util.ArrayDeque; -+import java.util.HashSet; -+import java.util.Set; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentLinkedQueue; -+import java.util.function.Consumer; -+ -+public final class ChunkTaskManager { -+ -+ private final QueueExecutorThread[] workers; -+ private final WorldServer world; -+ -+ private final PrioritizedTaskQueue queue; -+ private final boolean perWorldQueue; -+ -+ final ConcurrentHashMap chunkLoadTasks = new ConcurrentHashMap<>(64, 0.5f); -+ final ConcurrentHashMap chunkSaveTasks = new ConcurrentHashMap<>(64, 0.5f); -+ -+ private final PrioritizedTaskQueue chunkTasks = new PrioritizedTaskQueue<>(); // used if async chunks are disabled in config -+ -+ protected static QueueExecutorThread[] globalWorkers; -+ protected static QueueExecutorThread globalUrgentWorker; -+ protected static PrioritizedTaskQueue globalQueue; -+ protected static PrioritizedTaskQueue globalUrgentQueue; -+ -+ protected static final ConcurrentLinkedQueue CHUNK_WAIT_QUEUE = new ConcurrentLinkedQueue<>(); -+ -+ public static final ArrayDeque WAITING_CHUNKS = new ArrayDeque<>(); // stack -+ -+ private static final class ChunkInfo { -+ -+ public final int chunkX; -+ public final int chunkZ; -+ public final WorldServer world; -+ -+ public ChunkInfo(final int chunkX, final int chunkZ, final WorldServer world) { -+ this.chunkX = chunkX; -+ this.chunkZ = chunkZ; -+ this.world = world; -+ } -+ -+ @Override -+ public String toString() { -+ return "[( " + this.chunkX + "," + this.chunkZ + ") in '" + this.world.getWorld().getName() + "']"; -+ } -+ } -+ -+ public static void pushChunkWait(final WorldServer world, final int chunkX, final int chunkZ) { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); -+ } -+ } -+ -+ public static void popChunkWait() { -+ synchronized (WAITING_CHUNKS) { -+ WAITING_CHUNKS.pop(); -+ } -+ } -+ -+ private static ChunkInfo[] getChunkInfos() { -+ ChunkInfo[] chunks; -+ synchronized (WAITING_CHUNKS) { -+ chunks = WAITING_CHUNKS.toArray(new ChunkInfo[0]); -+ } -+ return chunks; -+ } -+ -+ public static void dumpAllChunkLoadInfo() { -+ ChunkInfo[] chunks = getChunkInfos(); -+ if (chunks.length > 0) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Chunk wait task info below: "); -+ -+ for (final ChunkInfo chunkInfo : chunks) { -+ final long key = IOUtil.getCoordinateKey(chunkInfo.chunkX, chunkInfo.chunkZ); -+ final ChunkLoadTask loadTask = chunkInfo.world.asyncChunkTaskManager.chunkLoadTasks.get(key); -+ final ChunkSaveTask saveTask = chunkInfo.world.asyncChunkTaskManager.chunkSaveTasks.get(key); -+ -+ PaperFileIOThread.LOGGER.log(Level.ERROR, chunkInfo.chunkX + "," + chunkInfo.chunkZ + " in '" + chunkInfo.world.getWorld().getName() + ":"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Load Task - " + (loadTask == null ? "none" : loadTask.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, "Save Task - " + (saveTask == null ? "none" : saveTask.toString())); -+ // log current status of chunk to indicate whether we're waiting on generation or loading -+ PlayerChunk chunkHolder = chunkInfo.world.getChunkProvider().playerChunkMap.getVisibleChunk(key); -+ -+ dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); -+ } -+ } -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ } -+ -+ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { -+ if (seenChunks.contains(chunkHolder)) { -+ return; -+ } -+ if (indent > maxDepth) { -+ return; -+ } -+ seenChunks.add(chunkHolder); -+ String indentStr = StringUtils.repeat(" ", indent); -+ if (chunkHolder == null) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); -+ } else { -+ IChunkAccess chunk = chunkHolder.getAvailableChunkNow(); -+ ChunkStatus holderStatus = chunkHolder.getChunkHolderStatus(); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - non-null"); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ } -+ } -+ -+ public static void initGlobalLoadThreads(int threads) { -+ if (threads <= 0 || globalWorkers != null) { -+ return; -+ } -+ -+ globalWorkers = new QueueExecutorThread[threads]; -+ globalQueue = new PrioritizedTaskQueue<>(); -+ globalUrgentQueue = new PrioritizedTaskQueue<>(); -+ -+ for (int i = 0; i < threads; ++i) { -+ globalWorkers[i] = new QueueExecutorThread<>(globalQueue, (long)0.10e6); //0.1ms -+ globalWorkers[i].setName("Paper Async Chunk Task Thread #" + i); -+ globalWorkers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ globalWorkers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalWorkers[i].start(); -+ } -+ -+ globalUrgentWorker = new QueueExecutorThread<>(globalUrgentQueue, (long)0.10e6); //0.1ms -+ globalUrgentWorker.setName("Paper Async Chunk Urgent Task Thread"); -+ globalUrgentWorker.setPriority(Thread.NORM_PRIORITY+1); -+ globalUrgentWorker.setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ globalUrgentWorker.start(); -+ } -+ -+ /** -+ * Creates this chunk task manager to operate off the specified number of threads. If the specified number of threads is -+ * less-than or equal to 0, then this chunk task manager will operate off of the world's chunk task queue. -+ * @param world Specified world. -+ * @param threads Specified number of threads. -+ * @see ChunkProviderServer#serverThreadQueue -+ */ -+ public ChunkTaskManager(final WorldServer world, final int threads) { -+ this.world = world; -+ this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; -+ this.queue = new PrioritizedTaskQueue<>(); -+ this.perWorldQueue = true; -+ -+ for (int i = 0; i < threads; ++i) { -+ this.workers[i] = new QueueExecutorThread<>(this.queue, (long)0.10e6); //0.1ms -+ this.workers[i].setName("Async chunk loader thread #" + i + " for world: " + world.getWorld().getName()); -+ this.workers[i].setPriority(Thread.NORM_PRIORITY - 1); -+ this.workers[i].setUncaughtExceptionHandler((final Thread thread, final Throwable throwable) -> { -+ PaperFileIOThread.LOGGER.fatal("Thread '" + thread.getName() + "' threw an uncaught exception!", throwable); -+ }); -+ -+ this.workers[i].start(); -+ } -+ } -+ -+ /** -+ * Creates the chunk task manager to work from the global workers. When {@link #close(boolean)} is invoked, -+ * the global queue is not shutdown. If the global workers is configured to be disabled or use 0 threads, then -+ * this chunk task manager will operate off of the world's chunk task queue. -+ * @param world The world that this task manager is responsible for -+ * @see ChunkProviderServer#serverThreadQueue -+ */ -+ public ChunkTaskManager(final WorldServer world) { -+ this.world = world; -+ this.workers = globalWorkers; -+ this.queue = globalQueue; -+ this.perWorldQueue = false; -+ } -+ -+ public boolean pollNextChunkTask() { -+ final ChunkTask task = this.chunkTasks.poll(); -+ -+ if (task != null) { -+ task.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Polls and runs the next available chunk wait queue task. This is to be used when the server is waiting on a chunk queue. -+ * (per-world can cause issues if all the worker threads are blocked waiting for a response from the main thread) -+ */ -+ public static boolean pollChunkWaitQueue() { -+ final Runnable run = CHUNK_WAIT_QUEUE.poll(); -+ if (run != null) { -+ run.run(); -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Queues a chunk wait task. Note that this will execute out of order with respect to tasks scheduled on a world's -+ * chunk task queue, since this is the global chunk wait queue. -+ */ -+ public static void queueChunkWaitTask(final Runnable runnable) { -+ CHUNK_WAIT_QUEUE.add(runnable); -+ } -+ -+ private static void drainChunkWaitQueue() { -+ Runnable run; -+ while ((run = CHUNK_WAIT_QUEUE.poll()) != null) { -+ run.run(); -+ } -+ } -+ -+ /** -+ * The exact same as {@link #scheduleChunkLoad(int, int, int, Consumer, boolean)}, except that the chunk data is provided as -+ * the {@code data} parameter. -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock, final CompletableFuture dataFuture) { -+ final WorldServer world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ dataFuture.thenAccept((final NBTTagCompound data) -> { -+ final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ if (!failed) { -+ chunkData.chunkData = data; -+ } -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, failed, intendingToBlock); // read data off disk if the future fails -+ }); -+ -+ return ret; -+ }); -+ } -+ -+ public void cancelChunkLoad(final int chunkX, final int chunkZ) { -+ this.chunkLoadTasks.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap == null) { -+ return null; -+ } -+ -+ if (valueInMap.cancelled) { -+ PaperFileIOThread.LOGGER.warn("Task " + valueInMap.toString() + " is already cancelled!"); -+ } -+ valueInMap.cancelled = true; -+ if (valueInMap.cancel()) { -+ return null; -+ } -+ -+ return valueInMap; -+ }); -+ } -+ -+ /** -+ * Schedules an asynchronous chunk load for the specified coordinates. The onComplete parameter may be invoked asynchronously -+ * on a worker thread or on the world's chunk executor queue. As such the code that is executed for the parameter should be -+ * carefully chosen. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param onComplete The consumer to invoke with the {@link ChunkRegionLoader.InProgressChunkHolder} object once this task is complete -+ * @param intendingToBlock Whether the caller is intending to block on this task completing (this is a performance tune, and has no adverse side-effects) -+ * @return The {@link ChunkLoadTask} associated with -+ */ -+ public ChunkLoadTask scheduleChunkLoad(final int chunkX, final int chunkZ, final int priority, -+ final Consumer onComplete, -+ final boolean intendingToBlock) { -+ final WorldServer world = this.world; -+ -+ return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { -+ if (valueInMap != null) { -+ if (!valueInMap.cancelled) { -+ throw new IllegalStateException("Double scheduling chunk load for task: " + valueInMap.toString()); -+ } -+ valueInMap.cancelled = false; -+ valueInMap.onComplete = onComplete; -+ return valueInMap; -+ } -+ -+ final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); -+ -+ PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { -+ ret.chunkData = chunkData; -+ ChunkTaskManager.this.internalSchedule(ret); // only schedule to the worker threads here -+ }, true, true, intendingToBlock); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Schedules an async save for the specified chunk. The chunk, at the beginning of this call, must be completely unloaded -+ * from the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @param priority Priority for this task -+ * @param asyncSaveData Async save data. See {@link ChunkRegionLoader#getAsyncSaveData(WorldServer, IChunkAccess)} -+ * @param chunk Chunk to save -+ * @return The {@link ChunkSaveTask} associated with the save task. -+ */ -+ public ChunkSaveTask scheduleChunkSave(final int chunkX, final int chunkZ, final int priority, -+ final ChunkRegionLoader.AsyncSaveData asyncSaveData, -+ final IChunkAccess chunk) { -+ AsyncCatcher.catchOp("chunk save schedule"); -+ -+ final WorldServer world = this.world; -+ -+ return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { -+ if (valueInMap != null) { -+ throw new IllegalStateException("Double scheduling chunk save for task: " + valueInMap.toString()); -+ } -+ -+ final ChunkSaveTask ret = new ChunkSaveTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, asyncSaveData, chunk); -+ -+ ChunkTaskManager.this.internalSchedule(ret); -+ -+ return ret; -+ }); -+ } -+ -+ /** -+ * Returns a completable future which will be completed with the un-copied chunk data for an in progress async save. -+ * Returns {@code null} if no save is in progress. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ */ -+ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.onComplete; -+ } -+ -+ /** -+ * Returns the chunk object being used to serialize data async for an unloaded chunk. Note that modifying this chunk -+ * is not safe to do as another thread is handling its save. The chunk is also not loaded into the world. -+ * @param chunkX Chunk's x coordinate -+ * @param chunkZ Chunk's z coordinate -+ * @return Chunk object for an in-progress async save, or {@code null} if no save is in progress -+ */ -+ public IChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { -+ final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); -+ if (chunkSaveTask == null) { -+ return null; -+ } -+ return chunkSaveTask.chunk; -+ } -+ -+ public void flush() { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks here -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ drainChunkWaitQueue(); -+ -+ if (this.workers == null) { -+ if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); -+ } else { -+ CompletableFuture wait = new CompletableFuture<>(); -+ MinecraftServer.getServer().scheduleOnMain(() -> { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); -+ }); -+ wait.join(); -+ } -+ } else { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.flush(); -+ } -+ } -+ if (globalUrgentWorker != null) globalUrgentWorker.flush(); -+ -+ // flush again since tasks we execute async saves -+ drainChunkWaitQueue(); -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ } -+ -+ public void close(final boolean wait) { -+ // flush here since we schedule tasks on the IO thread that can schedule tasks to this task manager -+ // we do this regardless of the wait param since after we invoke close no tasks can be queued -+ PaperFileIOThread.Holder.INSTANCE.flush(); -+ -+ if (this.workers == null) { -+ if (wait) { -+ this.flush(); -+ } -+ return; -+ } -+ -+ if (this.workers != globalWorkers) { -+ for (final QueueExecutorThread worker : this.workers) { -+ worker.close(false, this.perWorldQueue); -+ } -+ } -+ -+ if (wait) { -+ this.flush(); -+ } -+ } -+ -+ public void raisePriority(final int chunkX, final int chunkZ, final int priority) { -+ final Long chunkKey = Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)); -+ -+ ChunkTask chunkSaveTask = this.chunkSaveTasks.get(chunkKey); -+ if (chunkSaveTask != null) { -+ // don't bump save into urgent queue -+ raiseTaskPriority(chunkSaveTask, priority != PrioritizedTaskQueue.HIGHEST_PRIORITY ? priority : PrioritizedTaskQueue.HIGH_PRIORITY); -+ } -+ -+ ChunkLoadTask chunkLoadTask = this.chunkLoadTasks.get(chunkKey); -+ if (chunkLoadTask != null) { -+ raiseTaskPriority(chunkLoadTask, priority); -+ } -+ } -+ -+ private void raiseTaskPriority(ChunkTask task, int priority) { -+ final boolean raised = task.raisePriority(priority); -+ if (task.isScheduled() && raised && this.workers != null) { -+ // only notify if we're in queue to be executed -+ if (priority == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ // was in another queue but became urgent later, add to urgent queue and the previous -+ // queue will just have to ignore this task if it has already been started. -+ // Ultimately, we now have 2 potential queues that can pull it out whoever gets it first -+ // but the urgent queue has dedicated thread(s) so it's likely to win.... -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.internalScheduleNotify(); -+ } -+ } -+ } -+ -+ protected void internalSchedule(final ChunkTask task) { -+ if (this.workers == null) { -+ this.chunkTasks.add(task); -+ return; -+ } -+ -+ // It's important we order the task to be executed before notifying. Avoid a race condition where the worker thread -+ // wakes up and goes to sleep before we actually schedule (or it's just about to sleep) -+ if (task.getPriority() == PrioritizedTaskQueue.HIGHEST_PRIORITY) { -+ globalUrgentQueue.add(task); -+ this.internalScheduleNotifyUrgent(); -+ } else { -+ this.queue.add(task); -+ this.internalScheduleNotify(); -+ } -+ -+ } -+ -+ protected void internalScheduleNotify() { -+ if (this.workers == null) { -+ return; -+ } -+ for (final QueueExecutorThread worker : this.workers) { -+ if (worker.notifyTasks()) { -+ // break here since we only want to wake up one worker for scheduling one task -+ break; -+ } -+ } -+ } -+ -+ -+ protected void internalScheduleNotifyUrgent() { -+ if (globalUrgentWorker == null) { -+ return; -+ } -+ globalUrgentWorker.notifyTasks(); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java -@@ -0,0 +0,0 @@ public class PacketPlayInTabComplete implements Packet { - @Override - public void a(PacketDataSerializer packetdataserializer) throws IOException { - this.a = packetdataserializer.i(); -- this.b = packetdataserializer.e(32500); -+ this.b = packetdataserializer.e(2048); - } - - @Override -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ public final class MCUtil { - out.print(fileData); - } - } -+ -+ public static int getTicketLevelFor(ChunkStatus status) { -+ // TODO make sure the constant `33` is correct on future updates. See getChunkAt(int, int, ChunkStatus, boolean) -+ return 33 + ChunkStatus.getTicketLevelOffset(status); -+ } - } -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ import net.minecraft.server.players.UserCache; - import net.minecraft.util.MathHelper; - import net.minecraft.util.datafix.DataConverterRegistry; - import net.minecraft.util.worldupdate.WorldUpgrader; -+import net.minecraft.world.entity.npc.VillagerTrades; - import net.minecraft.world.level.DataPackConfiguration; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; -@@ -0,0 +0,0 @@ public class Main { - - convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object); - */ -+ Class.forName(VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async - final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.a((thread) -> { - DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataConverterRegistry.a(), minecraftsessionservice, gameprofilerepository, usercache, WorldLoadListenerLogger::new); - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { -+ if (Thread.currentThread() != this.serverThread) { -+ CompletableFuture> future = new CompletableFuture>(); -+ this.serverThreadQueue.execute(() -> { -+ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { -+ if (ex != null) { -+ future.completeExceptionally(ex); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.asyncChunks) { -+ world.getWorld().loadChunk(x, z, gen); -+ Chunk chunk = getChunkAtIfLoadedMainThread(x, z); -+ return CompletableFuture.completedFuture(chunk != null ? Either.left(chunk) : PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ -+ long k = ChunkCoordIntPair.pair(x, z); -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ -+ IChunkAccess ichunkaccess; -+ -+ // try cache -+ for (int l = 0; l < 4; ++l) { -+ if (k == this.cachePos[l] && ChunkStatus.FULL == this.cacheStatus[l]) { -+ ichunkaccess = this.cacheChunk[l]; -+ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime -+ -+ // move to first in cache -+ -+ for (int i1 = 3; i1 > 0; --i1) { -+ this.cachePos[i1] = this.cachePos[i1 - 1]; -+ this.cacheStatus[i1] = this.cacheStatus[i1 - 1]; -+ this.cacheChunk[i1] = this.cacheChunk[i1 - 1]; -+ } -+ -+ this.cachePos[0] = k; -+ this.cacheStatus[0] = ChunkStatus.FULL; -+ this.cacheChunk[0] = ichunkaccess; -+ -+ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); -+ } -+ } -+ } -+ -+ if (gen) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ IChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions -+ if (current != null) { -+ if (!(current instanceof ProtoChunkExtension) && !(current instanceof Chunk)) { -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ // we know the chunk is at full status here (either in read-only mode or the real thing) -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); -+ -+ if (status != null && status != ChunkStatus.FULL) { -+ // does not exist on disk -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ -+ if (status == ChunkStatus.FULL) { -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ } -+ -+ // status is null here -+ -+ // here we don't know what status it is and we're not supposed to generate -+ // so we asynchronously load empty status -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, isUrgent).thenCompose((either) -> { -+ IChunkAccess chunk = either.left().orElse(null); -+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof Chunk)) { -+ // the chunk on disk was not a full status chunk -+ return CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK_ACCESS); -+ } -+ ; // bring to full status if required -+ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); -+ }); -+ } -+ -+ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, boolean isUrgent) { -+ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); -+ } -+ -+ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, ChunkStatus status, boolean isUrgent) { -+ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); -+ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); -+ int ticketLevel = MCUtil.getTicketLevelFor(status); -+ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ -+ return future.thenComposeAsync((Either either) -> { -+ // either left -> success -+ // either right -> failure -+ -+ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier); -+ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading -+ -+ Optional failure = either.right(); -+ -+ if (failure.isPresent()) { -+ // failure -+ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString()); -+ } -+ -+ return CompletableFuture.completedFuture(either); -+ }, this.serverThreadQueue); -+ } -+ -+ public void addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { -+ this.chunkMapDistance.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } -+ -+ public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { -+ this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); -+ } - // Paper end - - @Nullable - @Override - public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ final int x = i; final int z = j; // Paper - conflict on variable change - if (Thread.currentThread() != this.serverThread) { - return (IChunkAccess) CompletableFuture.supplyAsync(() -> { - return this.getChunkAt(i, j, chunkstatus, flag); -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } - - gameprofilerfiller.c("getChunkCacheMiss"); -- CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); -+ CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag, true); // Paper - - if (!completablefuture.isDone()) { // Paper -+ // Paper start - async chunk io/loading -+ this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); -+ // Paper end - this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.world.timings.syncChunkLoad.stopTiming(); // Paper - } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } - - private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ // Paper start - add isUrgent - old sig left in place for dirty nms plugins -+ return getChunkFutureMainThread(i, j, chunkstatus, flag, false); -+ } -+ private CompletableFuture> getChunkFutureMainThread(int i, int j, ChunkStatus chunkstatus, boolean flag, boolean isUrgent) { -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j); - long k = chunkcoordintpair.pair(); - int l = 33 + ChunkStatus.a(chunkstatus); -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - protected boolean executeNext() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task - try { -+ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask(); // Paper - if (ChunkProviderServer.this.tickDistanceManager()) { - return true; - } else { - ChunkProviderServer.this.lightEngine.queueUpdate(); -- return super.executeNext(); -+ return super.executeNext() || execChunkTask; // Paper - } - } finally { - playerChunkMap.callbackExecutor.run(); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - return null; - } -+ -+ public ChunkStatus getChunkHolderStatus() { -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture> future = this.getStatusFutureUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return curr; -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -@@ -0,0 +0,0 @@ public class PlayerChunk { - ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel); - ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel); - boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET; -- boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; -+ boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; // Paper - diff on change: (flag1 = new ticket level is in loadable range) - PlayerChunk.State playerchunk_state = getChunkState(this.oldTicketLevel); - PlayerChunk.State playerchunk_state1 = getChunkState(this.ticketLevel); - // CraftBukkit start -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - }); - -+ // Paper start -+ if (!flag1) { -+ playerchunkmap.world.asyncChunkTaskManager.cancelChunkLoad(this.location.x, this.location.z); -+ } -+ // Paper end -+ - for (int i = flag1 ? chunkstatus1.c() + 1 : 0; i <= chunkstatus.c(); ++i) { - completablefuture = (CompletableFuture) this.statusFutures.get(i); - if (completablefuture != null) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.ProtoChunkExtension; - import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; - import net.minecraft.world.level.chunk.storage.IChunkLoader; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; - import net.minecraft.world.level.storage.Convertable; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; - public final ChunkGenerator chunkGenerator; -- private final Supplier l; -+ private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER - private final VillagePlace m; - public final LongSet unloadQueue; - private boolean updatingChunksModified; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final WorldLoadListener worldLoadListener; - public final PlayerChunkMap.a chunkDistanceManager; - private final AtomicInteger u; -- private final DefinedStructureManager definedStructureManager; -+ public final DefinedStructureManager definedStructureManager; // Paper - private -> public - private final File w; - private final PlayerMap playerMap; - public final Int2ObjectMap trackedEntities; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); - this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); - this.l = supplier; -- this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag); -+ this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); - } - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - @Nullable -- protected PlayerChunk getUpdatingChunk(long i) { -+ public PlayerChunk getUpdatingChunk(long i) { // Paper - return (PlayerChunk) this.updatingChunks.get(i); - } - - @Nullable -- protected PlayerChunk getVisibleChunk(long i) { -+ public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public - return (PlayerChunk) this.visibleChunks.get(i); - } - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public void close() throws IOException { - try { - this.p.close(); -+ this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.m.close(); - } finally { - super.close(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.b(() -> { - return true; - }); -- this.i(); -+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour -+// this.i(); // Paper - nuke IOWorker - PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); - } else { - this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot -+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more - - protected void unloadChunks(BooleanSupplier booleansupplier) { - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - -+ try (Timing ignored = this.world.timings.poiUnload.startTiming()) { // Paper - gameprofilerfiller.enter("poi"); - this.m.a(booleansupplier); -+ } // Paper - gameprofilerfiller.exitEnter("chunk_unload"); - if (!this.world.isSavingDisabled()) { -+ try (Timing ignored = this.world.timings.chunkUnload.startTiming()) { // Paper - this.b(booleansupplier); -+ }// Paper - } - - gameprofilerfiller.exit(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (playerchunk != null) { - this.pendingUnload.put(j, playerchunk); - this.updatingChunksModified = true; -+ this.a(j, playerchunk); // Paper - Move up - don't leak chunks - // Spigot start - if (!booleansupplier.getAsBoolean() && this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { - break; - } - // Spigot end -- this.a(j, playerchunk); -+ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb - } - } - activityAccountant.endActivity(); // Spigot -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ // Paper start - async chunk save for unload -+ // Note: This is very unsafe to call if the chunk is still in use. -+ // This is also modeled after PlayerChunkMap#saveChunk(IChunkAccess, boolean), with the intentional difference being -+ // serializing the chunk is left to a worker thread. -+ private void asyncSave(IChunkAccess chunk) { -+ ChunkCoordIntPair chunkPos = chunk.getPos(); -+ NBTTagCompound poiData; -+ try (Timing ignored = this.world.timings.chunkUnloadPOISerialization.startTiming()) { -+ poiData = this.getVillagePlace().getData(chunk.getPos()); -+ } -+ -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, -+ poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ -+ if (!chunk.isNeedsSaving()) { -+ return; -+ } -+ -+ ChunkStatus chunkstatus = chunk.getChunkStatus(); -+ -+ // Copied from PlayerChunkMap#saveChunk(IChunkAccess, boolean) -+ if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper -+ // Paper start - Optimize save by using status cache -+ try { -+ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkPos); -+ if (statusOnDisk != null && statusOnDisk.getType() == ChunkStatus.Type.LEVELCHUNK) { -+ // Paper end -+ return; -+ } -+ -+ if (chunkstatus == ChunkStatus.EMPTY && chunk.h().values().stream().noneMatch(StructureStart::e)) { -+ return; -+ } -+ } catch (IOException ex) { -+ ex.printStackTrace(); -+ return; -+ } -+ } -+ } -+ -+ ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ try (Timing ignored = this.world.timings.chunkUnloadPrepareSave.startTiming()) { -+ asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); -+ } -+ -+ this.world.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, -+ asyncSaveData, chunk); -+ -+ chunk.setLastSaved(this.world.getTime()); -+ chunk.setNeedsSaving(false); -+ } -+ // Paper end -+ - private void a(long i, PlayerChunk playerchunk) { - CompletableFuture completablefuture = playerchunk.getChunkSave(); - Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ((Chunk) ichunkaccess).setLoaded(false); - } - -- this.saveChunk(ichunkaccess); -+ //this.saveChunk(ichunkaccess);// Paper - delay - if (this.loadedChunks.remove(i) && ichunkaccess instanceof Chunk) { - Chunk chunk = (Chunk) ichunkaccess; - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - this.autoSaveQueue.remove(playerchunk); // Paper - -+ try { -+ this.asyncSave(ichunkaccess); // Paper - async chunk saving -+ } catch (Throwable ex) { -+ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); -+ this.saveChunk(ichunkaccess); -+ } -+ - this.lightEngine.a(ichunkaccess.getPos()); - this.lightEngine.queueUpdate(); - this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - Async chunk io -+ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { - try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper - this.world.getMethodProfiler().c("chunkLoad"); -- NBTTagCompound nbttagcompound; // Paper -- try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -- nbttagcompound = this.readChunkData(chunkcoordintpair); -- } // Paper end -+ // Paper start -+ if (ioThrowable != null) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); -+ } - -- if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings -- boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); -+ this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData); -+ chunkHolder.tasks.forEach(Runnable::run); -+ // Paper end - -- if (flag) { -- ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.m, chunkcoordintpair, nbttagcompound); -+ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async -+ -+ if (true) { -+ ProtoChunk protochunk = chunkHolder.protoChunk; - - protochunk.setLastSaved(this.world.getTime()); - this.a(chunkcoordintpair, protochunk.getChunkStatus().getType()); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - this.g(chunkcoordintpair); - return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter -- }, this.executor); -+ // Paper start - Async chunk io -+ }; -+ CompletableFuture> ret = new CompletableFuture<>(); -+ -+ Consumer chunkHolderConsumer = (ChunkRegionLoader.InProgressChunkHolder holder) -> { -+ // Go into the chunk load queue and not server task queue so we can be popped out even faster. -+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.queueChunkWaitTask(() -> { -+ try { -+ ret.complete(syncLoadComplete.apply(holder, null)); -+ } catch (Exception e) { -+ ret.completeExceptionally(e); -+ } -+ }); -+ }; -+ -+ CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); -+ if (chunkSaveFuture != null) { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ } else { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ } -+ return ret; -+ // Paper end - } - - private void g(ChunkCoordIntPair chunkcoordintpair) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - public boolean saveChunk(IChunkAccess ichunkaccess) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) { // Paper - this.m.a(ichunkaccess.getPos()); - if (!ichunkaccess.isNeedsSaving()) { - return false; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkStatus chunkstatus = ichunkaccess.getChunkStatus(); - - if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper - if (this.h(chunkcoordintpair)) { - return false; - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (chunkstatus == ChunkStatus.EMPTY && ichunkaccess.h().values().stream().noneMatch(StructureStart::e)) { - return false; - } -+ } // Paper - } - - this.world.getMethodProfiler().c("chunkSave"); -- NBTTagCompound nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); -+ NBTTagCompound nbttagcompound; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper -+ nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); -+ } // Paper -+ - -- this.a(chunkcoordintpair, nbttagcompound); -+ // Paper start - async chunk io -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkcoordintpair.x, chunkcoordintpair.z, -+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); -+ // Paper end - async chunk io - this.a(chunkcoordintpair, chunkstatus.getType()); - return true; - } catch (Exception exception) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return false; - } - } -+ } // Paper - } - - private boolean h(ChunkCoordIntPair chunkcoordintpair) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -+ // Paper start - Asynchronous chunk io -+ @Nullable -+ @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ false, true, true).join().chunkData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { -+ if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.world, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - @Nullable - public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public - NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - // Paper start - chunk status cache "api" - public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ synchronized (this) { // Paper -+ RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos); - - return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } // Paper - } - - public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ // Paper start - async chunk save for unload -+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getChunkStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false); - -- if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -- return null; -+ if (inProgressWrite != null) { -+ return ChunkRegionLoader.getStatus(inProgressWrite); - } -+ // Paper end -+ synchronized (this) { // Paper - async io -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -+ return null; -+ } - -- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - -- if (status != null) { -- return status; -+ if (status != null) { -+ return status; -+ } -+ // Paper start - async io - } - -- this.readChunkData(chunkPos); -+ NBTTagCompound compound = this.readChunkData(chunkPos); - -- return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ return ChunkRegionLoader.getStatus(compound); -+ // Paper end - } - - public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { -- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ synchronized (this) { -+ RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false); - -- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ } - } - - public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - -+ -+ // Paper start - async io -+ // this function will not load chunk data off disk to check for status -+ // ret null for unknown, empty for empty status on disk or absent from disk -+ public ChunkStatus getStatusOnDiskNoLoad(int x, int z) { -+ // Paper start - async chunk save for unload -+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(x, z); -+ if (unloadingChunk != null) { -+ return unloadingChunk.getChunkStatus(); -+ } -+ // Paper end -+ // Paper start - async io -+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .getPendingWrite(this.world, x, z, false); -+ -+ if (inProgressWrite != null) { -+ return ChunkRegionLoader.getStatus(inProgressWrite); -+ } -+ // Paper end -+ // variant of PlayerChunkMap#getChunkStatusOnDisk that does not load data off disk, but loads the region file -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ synchronized (world.getChunkProvider().playerChunkMap) { -+ RegionFile file; -+ try { -+ file = world.getChunkProvider().playerChunkMap.regionFileCache.getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return !file.chunkExists(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z); -+ } -+ } -+ - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ public VillagePlace getVillagePlace() { return this.h(); } // Paper - OBFHELPER - protected VillagePlace h() { - return this.m; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -0,0 +0,0 @@ public class TicketType { - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper -+ public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ import net.minecraft.core.IRegistry; - import net.minecraft.core.IRegistryCustom; - import net.minecraft.core.SectionPosition; - import net.minecraft.core.particles.ParticleParam; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkSection; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.dimension.DimensionManager; - import net.minecraft.world.level.dimension.end.EnderDragonBattle; - import net.minecraft.world.level.levelgen.HeightMap; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return this.chunkProvider.getChunkAt(x, z, false); - } - -+ // Paper start - Asynchronous IO -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { -+ WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().write(new ChunkCoordIntPair(x, z), compound); -+ } -+ -+ @Override -+ public NBTTagCompound readData(int x, int z) throws java.io.IOException { -+ return WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().read(new ChunkCoordIntPair(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { -+ RegionFile file; -+ -+ try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { -+ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ -+ public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController chunkDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { -+ @Override -+ public void writeData(int x, int z, NBTTagCompound compound) throws java.io.IOException { -+ WorldServer.this.getChunkProvider().playerChunkMap.write(new ChunkCoordIntPair(x, z), compound); -+ } -+ -+ @Override -+ public NBTTagCompound readData(int x, int z) throws java.io.IOException { -+ return WorldServer.this.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)); -+ } -+ -+ @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { -+ RegionFile file; -+ -+ try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); -+ } catch (java.io.IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ return function.apply(file); -+ } -+ } -+ -+ @Override -+ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { -+ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); -+ return function.apply(file); -+ } -+ } -+ }; -+ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.dragonBattle = null; - } - this.getServer().addWorld(this.getWorld()); // CraftBukkit -+ -+ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper - } - - // CraftBukkit start -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { -- getChunkProvider().getChunkAtMainThread(pair.x, pair.z); -+ getChunkProvider().getChunkAtAsynchronously(pair.x, pair.z, true, false).exceptionally((ex) -> { -+ ex.printStackTrace(); -+ return null; -+ }); - }); - } - public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } -+ // Paper start -+ String str = packetplayintabcomplete.c(); int index = -1; -+ if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ // Paper end - // CraftBukkit end - StringReader stringreader = new StringReader(packetplayintabcomplete.c()); - -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -0,0 +0,0 @@ public abstract class IAsyncTaskHandler implements Mailbox public - while (this.executeNext()) { - ; - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -0,0 +0,0 @@ import java.util.stream.Stream; - import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.level.LightEngineGraphSection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.IWorldReader; -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - private final VillagePlace.a a = new VillagePlace.a(); - private final LongSet b = new LongOpenHashSet(); - -+ private final WorldServer world; // Paper -+ - public VillagePlace(File file, DataFixer datafixer, boolean flag) { -+ // Paper start - add world parameter -+ this(file, datafixer, flag, null); -+ } -+ public VillagePlace(File file, DataFixer datafixer, boolean flag, WorldServer world) { - super(file, VillagePlaceSection::a, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK, flag); -+ this.world = world; -+ // Paper end - add world parameter - } - - public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) { -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - - @Override - public void a(BooleanSupplier booleansupplier) { -- super.a(booleansupplier); -+ // Paper start - async chunk io -+ if (this.world == null) { -+ super.a(booleansupplier); -+ } else { -+ //super.a(booleansupplier); // re-implement below -+ while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) { -+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r(); -+ -+ NBTTagCompound data; -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { -+ data = this.getData(chunkcoordintpair); -+ } -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, -+ chunkcoordintpair.x, chunkcoordintpair.z, data, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); -+ } -+ } -+ // Paper end - this.a.a(); - } - -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - } - } - -+ // Paper start - Asynchronous chunk io -+ @javax.annotation.Nullable -+ @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ NBTTagCompound ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE -+ .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), -+ true, false, true).join().poiData; -+ -+ if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { -+ throw new java.io.IOException("See logs for further detail"); -+ } -+ return ret; -+ } -+ return super.read(chunkcoordintpair); -+ } -+ -+ @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws java.io.IOException { -+ if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave( -+ this.world, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound, null, -+ com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); -+ return; -+ } -+ super.write(chunkcoordintpair, nbttagcompound); -+ } -+ // Paper end -+ - public static enum Occupancy { - - HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> { -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - - public class NextTickListEntry { - -- private static long d; -+ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading - private final T e; - public final BlockPosition a; - public final long b; -@@ -0,0 +0,0 @@ public class NextTickListEntry { - } - - public NextTickListEntry(BlockPosition blockposition, T t0, long i, TickListPriority ticklistpriority) { -- this.f = (long) (NextTickListEntry.d++); -+ this.f = (long) (NextTickListEntry.COUNTER.getAndIncrement()); // Paper - async chunk loading - this.a = blockposition.immutableCopy(); - this.e = t0; - this.b = i; -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -0,0 +0,0 @@ public class ChunkStatus { - return ChunkStatus.q.size(); - } - -+ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.a(status); } // Paper - OBFHELPER - public static int a(ChunkStatus chunkstatus) { - return ChunkStatus.r.getInt(chunkstatus.c()); - } -@@ -0,0 +0,0 @@ public class ChunkStatus { - this.t = chunkstatus == null ? 0 : chunkstatus.c() + 1; - } - -+ public final int getStatusIndex() { return c(); } // Paper - OBFHELPER - public int c() { - return this.t; - } -@@ -0,0 +0,0 @@ public class ChunkStatus { - return this.s; - } - -- public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER -+ public final ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER - public ChunkStatus e() { - return this.u; - } -@@ -0,0 +0,0 @@ public class ChunkStatus { - return this.w.doWork(this, worldserver, definedstructuremanager, lightenginethreaded, function, ichunkaccess); - } - -+ public final int getNeighborRadius() { return this.f(); } // Paper - OBFHELPER - public int f() { - return this.x; - } -@@ -0,0 +0,0 @@ public class ChunkStatus { - return this.z; - } - -+ public final boolean isAtLeastStatus(ChunkStatus chunkstatus) { return b(chunkstatus); } // Paper - OBFHELPER - public boolean b(ChunkStatus chunkstatus) { - return this.c() >= chunkstatus.c(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -0,0 +0,0 @@ public class NibbleArray { - return this.a; - } - -+ public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER - public NibbleArray b() { - return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.shorts.ShortList; - import it.unimi.dsi.fastutil.shorts.ShortListIterator; -+import java.util.ArrayDeque; // Paper - import java.util.Arrays; - import java.util.BitSet; - import java.util.EnumSet; -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start -+ public static final class InProgressChunkHolder { -+ -+ public final ProtoChunk protoChunk; -+ public final ArrayDeque tasks; -+ -+ public NBTTagCompound poiData; -+ -+ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { -+ this.protoChunk = protoChunk; -+ this.tasks = tasks; -+ } -+ } -+ - public static ProtoChunk loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -+ InProgressChunkHolder holder = loadChunk(worldserver, definedstructuremanager, villageplace, chunkcoordintpair, nbttagcompound, true); -+ holder.tasks.forEach(Runnable::run); -+ return holder.protoChunk; -+ } -+ -+ public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { -+ ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); -+ // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - LightEngine lightengine = chunkproviderserver.getLightEngine(); - - if (flag) { -- lightengine.b(chunkcoordintpair, true); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ lightengine.b(chunkcoordintpair, true); -+ }); // Paper - delay this task since we're executing off-main - } - - for (int i = 0; i < nbttaglist.size(); ++i) { -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - achunksection[b0] = chunksection; - } - -- villageplace.a(chunkcoordintpair, chunksection); -+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ villageplace.a(chunkcoordintpair, chunksection); -+ }); // Paper - delay this task since we're executing off-main - } - - if (flag) { - if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) { -- lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("BlockLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), blockLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - - if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) { -- lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("SkyLight")), true); -+ // Paper start - delay this task since we're executing off-main -+ NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); -+ tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true); -+ }); -+ // Paper end - delay this task since we're executing off-main - } - } - } -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - } - - if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { -- return new ProtoChunkExtension((Chunk) object); -+ return new InProgressChunkHolder(new ProtoChunkExtension((Chunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading - } else { - ProtoChunk protochunk1 = (ProtoChunk) object; - -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - protochunk1.a(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); - } - -- return protochunk1; -+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading -+ } -+ } -+ -+ // Paper start - async chunk save for unload -+ public static final class AsyncSaveData { -+ public final NibbleArray[] blockLight; // null or size of 17 (for indices -1 through 15) -+ public final NibbleArray[] skyLight; -+ -+ public final NBTTagList blockTickList; // non-null if we had to go to the server's tick list -+ public final NBTTagList fluidTickList; // non-null if we had to go to the server's tick list -+ -+ public final long worldTime; -+ -+ public AsyncSaveData(NibbleArray[] blockLight, NibbleArray[] skyLight, NBTTagList blockTickList, NBTTagList fluidTickList, -+ long worldTime) { -+ this.blockLight = blockLight; -+ this.skyLight = skyLight; -+ this.blockTickList = blockTickList; -+ this.fluidTickList = fluidTickList; -+ this.worldTime = worldTime; - } - } - -+ // must be called sync -+ public static AsyncSaveData getAsyncSaveData(WorldServer world, IChunkAccess chunk) { -+ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); -+ ChunkCoordIntPair chunkPos = chunk.getPos(); -+ -+ LightEngineThreaded lightenginethreaded = world.getChunkProvider().getLightEngine(); -+ -+ NibbleArray[] blockLight = new NibbleArray[17 - (-1)]; -+ NibbleArray[] skyLight = new NibbleArray[17 - (-1)]; -+ -+ for (int i = -1; i < 17; ++i) { -+ NibbleArray blockArray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkPos, i)); -+ NibbleArray skyArray = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkPos, i)); -+ -+ // copy data for safety -+ if (blockArray != null) { -+ blockArray = blockArray.copy(); -+ } -+ if (skyArray != null) { -+ skyArray = skyArray.copy(); -+ } -+ -+ // apply offset of 1 for -1 starting index -+ blockLight[i + 1] = blockArray; -+ skyLight[i + 1] = skyArray; -+ } -+ -+ TickList blockTickList = chunk.n(); -+ -+ NBTTagList blockTickListSerialized; -+ if (blockTickList instanceof ProtoChunkTickList || blockTickList instanceof TickListChunk) { -+ blockTickListSerialized = null; -+ } else { -+ blockTickListSerialized = world.getBlockTickList().a(chunkPos); -+ } -+ -+ TickList fluidTickList = chunk.o(); -+ -+ NBTTagList fluidTickListSerialized; -+ if (fluidTickList instanceof ProtoChunkTickList || fluidTickList instanceof TickListChunk) { -+ fluidTickListSerialized = null; -+ } else { -+ fluidTickListSerialized = world.getFluidTickList().a(chunkPos); -+ } -+ -+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getTime()); -+ } -+ - public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) { -+ return saveChunk(worldserver, ichunkaccess, null); -+ } -+ public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { -+ // Paper end - ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); - NBTTagCompound nbttagcompound = new NBTTagCompound(); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - nbttagcompound.set("Level", nbttagcompound1); - nbttagcompound1.setInt("xPos", chunkcoordintpair.x); - nbttagcompound1.setInt("zPos", chunkcoordintpair.z); -- nbttagcompound1.setLong("LastUpdate", worldserver.getTime()); -+ nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading - nbttagcompound1.setLong("InhabitedTime", ichunkaccess.getInhabitedTime()); - nbttagcompound1.setString("Status", ichunkaccess.getChunkStatus().d()); - ChunkConverter chunkconverter = ichunkaccess.p(); -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - - NBTTagCompound nbttagcompound2; - -- for (int i = -1; i < 17; ++i) { -+ for (int i = -1; i < 17; ++i) { // Paper - conflict on loop parameter change - int finalI = i; // CraftBukkit - decompile errors - ChunkSection chunksection = (ChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { - return chunksection1 != null && chunksection1.getYPosition() >> 4 == finalI; // CraftBukkit - decompile errors - }).findFirst().orElse(Chunk.a); -- NibbleArray nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); -- NibbleArray nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); -- -+ // Paper start - async chunk save for unload -+ NibbleArray nibblearray; // block light -+ NibbleArray nibblearray1; // sky light -+ if (asyncsavedata == null) { -+ nibblearray = lightenginethreaded.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) -+ nibblearray1 = lightenginethreaded.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, i)); // Paper - diff on method change (see getAsyncSaveData) -+ } else { -+ nibblearray = asyncsavedata.blockLight[i + 1]; // +1 to offset the -1 starting index -+ nibblearray1 = asyncsavedata.skyLight[i + 1]; // +1 to offset the -1 starting index -+ } -+ // Paper end - if (chunksection != Chunk.a || nibblearray != null || nibblearray1 != null) { - nbttagcompound2 = new NBTTagCompound(); - nbttagcompound2.setByte("Y", (byte) (i & 255)); -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - Entity entity = (Entity) iterator1.next(); - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); - // Paper start -- if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { - toUpdate.add(entity); - continue; - } -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - } - - nbttagcompound1.set("Entities", nbttaglist2); -- TickList ticklist = ichunkaccess.n(); -+ TickList ticklist = ichunkaccess.n(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist instanceof ProtoChunkTickList) { - nbttagcompound1.set("ToBeTicked", ((ProtoChunkTickList) ticklist).b()); - } else if (ticklist instanceof TickListChunk) { - nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).b()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.set("TileTicks", asyncsavedata.blockTickList); -+ // Paper end - } else { -- nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); -+ nbttagcompound1.set("TileTicks", worldserver.getBlockTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - -- TickList ticklist1 = ichunkaccess.o(); -+ TickList ticklist1 = ichunkaccess.o(); // Paper - diff on method change (see getAsyncSaveData) - - if (ticklist1 instanceof ProtoChunkTickList) { - nbttagcompound1.set("LiquidsToBeTicked", ((ProtoChunkTickList) ticklist1).b()); - } else if (ticklist1 instanceof TickListChunk) { - nbttagcompound1.set("LiquidTicks", ((TickListChunk) ticklist1).b()); -+ // Paper start - async chunk save for unload -+ } else if (asyncsavedata != null) { -+ nbttagcompound1.set("LiquidTicks", asyncsavedata.fluidTickList); -+ // Paper end - } else { -- nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); -+ nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) - } - - nbttagcompound1.set("PostProcessing", a(ichunkaccess.l())); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.chunk.storage; - import com.mojang.datafixers.DataFixer; - import java.io.File; - import java.io.IOException; -+// Paper start -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.CompletionException; -+// Paper end - import java.util.function.Supplier; - import javax.annotation.Nullable; - import net.minecraft.SharedConstants; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.dimension.DimensionManager; - - public class IChunkLoader implements AutoCloseable { - -- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER -+ // Paper - OBFHELPER - nuke IOWorker - protected final DataFixer b; - @Nullable -- private PersistentStructureLegacy c; -+ private volatile PersistentStructureLegacy c; // Paper - async chunk loading -+ -+ private final Object persistentDataLock = new Object(); // Paper -+ public final RegionFileCache regionFileCache; - - public IChunkLoader(File file, DataFixer datafixer, boolean flag) { -+ this.regionFileCache = new RegionFileCache(file, flag); // Paper - nuke IOWorker - this.b = datafixer; -- this.a = new IOWorker(file, flag, "chunk"); -+ // Paper - nuke IOWorker - } - - // CraftBukkit start - private boolean check(ChunkProviderServer cps, int x, int z) throws IOException { - ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); - if (cps != null) { -- com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); -- if (cps.isLoaded(x, z)) { -+ //com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); // Paper - this function is now MT-Safe -+ if (cps.getChunkAtIfCachedImmediately(x, z) != null) { // Paper - isLoaded is a ticket level check, not a chunk loaded check! - return true; - } - } - -- NBTTagCompound nbt = read(pos); -- if (nbt != null) { -- NBTTagCompound level = nbt.getCompound("Level"); -- if (level.getBoolean("TerrainPopulated")) { -- return true; -- } -+ -+ // Paper start - prioritize -+ NBTTagCompound nbt = cps == null ? read(pos) : -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((WorldServer)cps.getWorld(), x, z, -+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; -+ // Paper end -+ if (nbt != null) { -+ NBTTagCompound level = nbt.getCompound("Level"); -+ if (level.getBoolean("TerrainPopulated")) { -+ return true; -+ } - - ChunkStatus status = ChunkStatus.a(level.getString("Status")); - if (status != null && status.b(ChunkStatus.FEATURES)) { -@@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable { - if (i < 1493) { - nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493); - if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - if (this.c == null) { - this.c = PersistentStructureLegacy.a(resourcekey, (WorldPersistentData) supplier.get()); - } - - nbttagcompound = this.c.a(nbttagcompound); -+ } // Paper - Async chunk loading - } - } - -@@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable { - - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { -- return this.a.a(chunkcoordintpair); -+ return this.regionFileCache.read(chunkcoordintpair); - } - -- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -- this.a.a(chunkcoordintpair, nbttagcompound); -+ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.c != null) { -+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading - this.c.a(chunkcoordintpair.pair()); -+ } // Paper - Async chunk loading} - } -- -- } -- -- public void i() { -- this.a.a().join(); - } - - public void close() throws IOException { -- this.a.close(); -+ this.regionFileCache.close(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - protected final RegionFileBitSet freeSectors; - public final File file; // Paper - -+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper -+ - // Paper start - Cache chunk status - private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; - -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - return (i + 4096 - 1) / 4096; - } - -- public boolean b(ChunkCoordIntPair chunkcoordintpair) { -+ public synchronized boolean b(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronized - int i = this.getOffset(chunkcoordintpair); - - if (i == 0) { -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - } - - public void close() throws IOException { -+ // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.lock(); -+ synchronized (this) { -+ try { -+ // Paper end - this.closed = true; // Paper - try { - this.d(); -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - this.dataFile.close(); - } - } -+ } finally { // Paper start - Prevent regionfiles from being closed during use -+ this.fileLock.unlock(); -+ } -+ } // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; - --public final class RegionFileCache implements AutoCloseable { -+public class RegionFileCache implements AutoCloseable { // Paper - no final - - public final Long2ObjectLinkedOpenHashMap cache = new Long2ObjectLinkedOpenHashMap(); - private final File b; -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - - - // Paper start -- public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { -+ public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io - return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); - } - - // Paper end -- public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public -+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize -+ // Paper start - add lock parameter -+ return this.getFile(chunkcoordintpair, existingOnly, false); -+ } -+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { -+ // Paper end - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); - - if (regionfile != null) { -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile.fileLock.lock(); -+ } -+ // Paper end - return regionfile; - } else { - if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - RegionFile regionfile1 = new RegionFile(file, this.b, this.c); - - this.cache.putAndMoveToFirst(i, regionfile1); -+ // Paper start -+ if (lock) { -+ // must be in this synchronized block -+ regionfile1.fileLock.lock(); -+ } -+ // Paper end - return regionfile1; - } - } -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { - // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing -- RegionFile regionfile = this.getFile(chunkcoordintpair, true); -+ RegionFile regionfile = this.getFile(chunkcoordintpair, true, true); // Paper - if (regionfile == null) { - return null; - } - // CraftBukkit end -+ try { // Paper - DataInputStream datainputstream = regionfile.a(chunkcoordintpair); - // Paper start - if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - } - - return nbttagcompound; -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - - protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { -- RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit -+ RegionFile regionfile = this.getFile(chunkcoordintpair, false, true); // CraftBukkit // Paper -+ try { // Paper - int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); - Throwable throwable = null; -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - MinecraftServer.LOGGER.error("Failed to save chunk", laste); - } - // Paper end -+ } finally { // Paper start -+ regionfile.fileLock.unlock(); -+ } // Paper end - } - -- public void close() throws IOException { -+ public synchronized void close() throws IOException { // Paper -> synchronized - ExceptionSuppressor exceptionsuppressor = new ExceptionSuppressor<>(); - ObjectIterator objectiterator = this.cache.values().iterator(); - -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - } - - } -+ -+ // CraftBukkit start -+ public synchronized boolean chunkExists(ChunkCoordIntPair pos) throws IOException { // Paper - synchronize -+ RegionFile regionfile = getFile(pos, true); -+ -+ return regionfile != null ? regionfile.chunkExists(pos) : false; -+ } -+ // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileSection.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.World; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - --public class RegionFileSection implements AutoCloseable { -+public class RegionFileSection extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker - - private static final Logger LOGGER = LogManager.getLogger(); -- private final IOWorker b; -+ // Paper - nuke IOWorker - private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); -- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); -+ public final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> public - private final Function> e; - private final Function f; - private final DataFixer g; - private final DataFixTypes h; - - public RegionFileSection(File file, Function> function, Function function1, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) { -+ super(file, flag); // Paper - nuke IOWorker - this.e = function; - this.f = function1; - this.g = datafixer; - this.h = datafixtypes; -- this.b = new IOWorker(file, flag, file.getName()); -+ //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker - } - - protected void a(BooleanSupplier booleansupplier) { - while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) { -- ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); -+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); // Paper - conflict here to avoid obfhelpers - - this.d(chunkcoordintpair); - } -@@ -0,0 +0,0 @@ public class RegionFileSection implements AutoCloseable { - } - - private void b(ChunkCoordIntPair chunkcoordintpair) { -- this.a(chunkcoordintpair, DynamicOpsNBT.a, this.c(chunkcoordintpair)); -+ // Paper start - load data in function -+ this.loadInData(chunkcoordintpair, this.c(chunkcoordintpair)); -+ } -+ public void loadInData(ChunkCoordIntPair chunkPos, NBTTagCompound compound) { -+ this.a(chunkPos, DynamicOpsNBT.a, compound); -+ // Paper end - } - - @Nullable - private NBTTagCompound c(ChunkCoordIntPair chunkcoordintpair) { - try { -- return this.b.a(chunkcoordintpair); -+ return this.read(chunkcoordintpair); // Paper - nuke IOWorker - } catch (IOException ioexception) { - RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception); - return null; -@@ -0,0 +0,0 @@ public class RegionFileSection implements AutoCloseable { - } - - private void d(ChunkCoordIntPair chunkcoordintpair) { -- Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); -+ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); // Paper - conflict here to avoid adding obfhelpers :) - NBTBase nbtbase = (NBTBase) dynamic.getValue(); - - if (nbtbase instanceof NBTTagCompound) { -- this.b.a(chunkcoordintpair, (NBTTagCompound) nbtbase); -+ try { this.write(chunkcoordintpair, (NBTTagCompound) nbtbase); } catch (IOException ioexception) { RegionFileSection.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async - } else { - RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); - } - - } - -+ // Paper start - internal get data function, copied from above -+ private NBTTagCompound getDataInternal(ChunkCoordIntPair chunkcoordintpair) { -+ Dynamic dynamic = this.a(chunkcoordintpair, DynamicOpsNBT.a); -+ NBTBase nbtbase = (NBTBase) dynamic.getValue(); -+ -+ if (nbtbase instanceof NBTTagCompound) { -+ return (NBTTagCompound)nbtbase; -+ } else { -+ RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); -+ } -+ return null; -+ } -+ // Paper end -+ - private Dynamic a(ChunkCoordIntPair chunkcoordintpair, DynamicOps dynamicops) { - Map map = Maps.newHashMap(); - -@@ -0,0 +0,0 @@ public class RegionFileSection implements AutoCloseable { - public void a(ChunkCoordIntPair chunkcoordintpair) { - if (!this.d.isEmpty()) { - for (int i = 0; i < 16; ++i) { -- long j = SectionPosition.a(chunkcoordintpair, i).s(); -+ long j = SectionPosition.a(chunkcoordintpair, i).s(); // Paper - conflict here to avoid obfhelpers - -- if (this.d.contains(j)) { -+ if (this.d.contains(j)) { // Paper - conflict here to avoid obfhelpers - this.d(chunkcoordintpair); - return; - } -@@ -0,0 +0,0 @@ public class RegionFileSection implements AutoCloseable { - - } - -- public void close() throws IOException { -- this.b.close(); -+// Paper start - nuke IOWorker -+// public void close() throws IOException { -+// this.b.close(); -+// } -+// Paper end -+ -+ // Paper start - get data function -+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) { -+ // Note: Copied from above -+ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) -+ if (!this.d.isEmpty()) { -+ for (int i = 0; i < 16; ++i) { -+ long j = SectionPosition.a(chunkcoordintpair, i).s(); -+ -+ if (this.d.contains(j)) { -+ return this.getDataInternal(chunkcoordintpair); -+ } -+ } -+ } -+ return null; - } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - return true; - } - -- net.minecraft.world.level.chunk.storage.RegionFile file; -- try { -- file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -- } catch (IOException ex) { -- throw new RuntimeException(ex); -- } -+ ChunkStatus status = world.getChunkProvider().playerChunkMap.getStatusOnDiskNoLoad(x, z); // Paper - async io - move to own method - -- ChunkStatus status = file.getStatusIfCached(x, z); -- if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ // Paper start - async io -+ if (status == ChunkStatus.EMPTY) { -+ // does not exist on disk - return false; - } - -+ if (status == null) { // at this stage we don't know what it is on disk - IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); - if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { - return false; - } -+ } else if (status != ChunkStatus.FULL) { -+ return false; // not full status on disk -+ } -+ // Paper end - - // fall through to load - // we do this so we do not re-read the chunk data on disk -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - public DragonBattle getEnderDragonBattle() { - return (getHandle().getDragonBattle() == null) ? null : new CraftDragonBattle(getHandle().getDragonBattle()); - } -+ // Paper start -+ @Override -+ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { -+ if (Bukkit.isPrimaryThread()) { -+ net.minecraft.world.level.chunk.Chunk immediate = this.world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z); -+ if (immediate != null) { -+ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); -+ } -+ } else { -+ CompletableFuture future = new CompletableFuture(); -+ world.getMinecraftServer().execute(() -> { -+ getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { -+ if (err != null) { -+ future.completeExceptionally(err); -+ } else { -+ future.complete(chunk); -+ } -+ }); -+ }); -+ return future; -+ } -+ -+ return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { -+ net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); -+ return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -+ }, net.minecraft.server.MinecraftServer.getServer()); -+ } -+ // Paper end - - // Spigot start - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.TicketType; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityAreaEffectCloud; -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.vehicle.EntityMinecartHopper; - import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; - import net.minecraft.world.entity.vehicle.EntityMinecartRideable; - import net.minecraft.world.entity.vehicle.EntityMinecartTNT; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.phys.AxisAlignedBB; - import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - entity.setHeadRotation(yaw); - } - -+ @Override// Paper start -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { -+ PlayerChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().playerChunkMap; -+ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture<>(); -+ -+ loc.getWorld().getChunkAtAsyncUrgently(loc).thenCompose(chunk -> { -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(chunk.getX(), chunk.getZ()); -+ ((CraftWorld) loc.getWorld()).getHandle().getChunkProvider().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pair.pair()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); -+ } -+ }).thenAccept((chunk) -> future.complete(teleport(loc, cause))).exceptionally(ex -> { -+ future.completeExceptionally(ex); -+ return null; -+ }); -+ return future; -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location) { - return teleport(location, TeleportCause.PLUGIN); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -0,0 +0,0 @@ import java.lang.management.ThreadInfo; - import java.util.logging.Level; - import java.util.logging.Logger; - import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.io.chunk.ChunkTaskManager; // Paper - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper -+ ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Spigot-Server-Patches/Attributes-API-for-item-defaults.patch b/Spigot-Server-Patches/Attributes-API-for-item-defaults.patch deleted file mode 100644 index 00023654b1..0000000000 --- a/Spigot-Server-Patches/Attributes-API-for-item-defaults.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 8 May 2021 15:01:54 -0700 -Subject: [PATCH] Attributes API for item defaults - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -0,0 +0,0 @@ public class Item implements IMaterial { - return false; - } - -+ public Multimap getAttributesForSlot(EnumItemSlot enumItemSlot) { return a(enumItemSlot); } // Paper - OBFHELPER - public Multimap a(EnumItemSlot enumitemslot) { - return ImmutableMultimap.of(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); - } - -+ @Override -+ public com.google.common.collect.Multimap getItemAttributes(org.bukkit.Material material, org.bukkit.inventory.EquipmentSlot equipmentSlot) { -+ Item item = this.getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item and therefore does not have attributes"); -+ } -+ com.google.common.collect.ImmutableMultimap.Builder attributeMapBuilder = com.google.common.collect.ImmutableMultimap.builder(); -+ item.getAttributesForSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { -+ attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.IRegistry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); -+ }); -+ return attributeMapBuilder.build(); -+ } -+ - @Override - public int getProtocolVersion() { - return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); diff --git a/Spigot-Server-Patches/Auto-fix-bad-Y-levels-on-player-login.patch b/Spigot-Server-Patches/Auto-fix-bad-Y-levels-on-player-login.patch deleted file mode 100644 index 62d47a55dc..0000000000 --- a/Spigot-Server-Patches/Auto-fix-bad-Y-levels-on-player-login.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 23:48:39 -0400 -Subject: [PATCH] Auto fix bad Y levels on player login - -Bring down to a saner Y level if super high, as this can cause the server to crash - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - @Override - public void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); -+ if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world - if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { - if (this.getMinecraftServer().getForceGamemode()) { - this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET); diff --git a/Spigot-Server-Patches/Avoid-NPE-in-PathfinderGoalTempt.patch b/Spigot-Server-Patches/Avoid-NPE-in-PathfinderGoalTempt.patch deleted file mode 100644 index 0d3b2428af..0000000000 --- a/Spigot-Server-Patches/Avoid-NPE-in-PathfinderGoalTempt.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 29 Nov 2017 22:18:54 -0500 -Subject: [PATCH] Avoid NPE in PathfinderGoalTempt - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTempt.java -@@ -0,0 +0,0 @@ public class PathfinderGoalTempt extends PathfinderGoal { - } - this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle(); - } -- return tempt; -+ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled - // CraftBukkit end - } - } diff --git a/Spigot-Server-Patches/Avoid-blocking-on-Network-Manager-creation.patch b/Spigot-Server-Patches/Avoid-blocking-on-Network-Manager-creation.patch deleted file mode 100644 index 4f9163776d..0000000000 --- a/Spigot-Server-Patches/Avoid-blocking-on-Network-Manager-creation.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 23:19:16 -0400 -Subject: [PATCH] Avoid blocking on Network Manager creation - -Per Paper issue 294 - -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -0,0 +0,0 @@ public class ServerConnection { - public volatile boolean c; - private final List listeningChannels = Collections.synchronizedList(Lists.newArrayList()); - private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); -+ // Paper start - prevent blocking on adding a new network manager while the server is ticking -+ private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private void addPending() { -+ NetworkManager manager = null; -+ while ((manager = pending.poll()) != null) { -+ connectedChannels.add(manager); -+ } -+ } -+ // Paper end - - public ServerConnection(MinecraftServer minecraftserver) { - this.e = minecraftserver; -@@ -0,0 +0,0 @@ public class ServerConnection { - int j = ServerConnection.this.e.k(); - Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); - -- ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ //ServerConnection.this.connectedChannels.add((NetworkManager) object); // CraftBukkit - decompile error -+ pending.add((NetworkManager) object); // Paper - channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); - } -@@ -0,0 +0,0 @@ public class ServerConnection { - - synchronized (this.connectedChannels) { - // Spigot Start -+ this.addPending(); // Paper - // This prevents players from 'gaming' the server, and strategically relogging to increase their position in the tick order - if ( org.spigotmc.SpigotConfig.playerShuffle > 0 && MinecraftServer.currentTick % org.spigotmc.SpigotConfig.playerShuffle == 0 ) - { diff --git a/Spigot-Server-Patches/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch b/Spigot-Server-Patches/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch deleted file mode 100644 index 9db6147e86..0000000000 --- a/Spigot-Server-Patches/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Toon Schoenmakers -Date: Fri, 23 Oct 2020 15:01:44 +0200 -Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing - loot - -This can realistically only happen if there's custom loot active on fishing -which can return 0 items. This would disconnect the player who's fishing. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile { - - while (iterator.hasNext()) { - ItemStack itemstack1 = (ItemStack) iterator.next(); -- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); -+ // Paper start, new EntityItem would throw if for whatever reason (mostly shitty datapacks) the itemstack1 turns out to be empty -+ // if the item stack is empty we instead just have our entityitem as null -+ EntityItem entityitem = null; -+ if (!itemstack1.isEmpty()) { -+ entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); -+ } -+ // Paper end - // CraftBukkit start -- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); -+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null - playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); - this.world.getServer().getPluginManager().callEvent(playerFishEvent); - -@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile { - double d2 = entityhuman.locZ() - this.locZ(); - double d3 = 0.1D; - -- entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -- this.world.addEntity(entityitem); -+ // Paper start, entity item can be null, so we need to check against this -+ if (entityitem != null) { -+ entityitem.setMot(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); -+ this.world.addEntity(entityitem); -+ } -+ // Paper end - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { - entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper diff --git a/Spigot-Server-Patches/Avoid-hopper-searches-if-there-are-no-items.patch b/Spigot-Server-Patches/Avoid-hopper-searches-if-there-are-no-items.patch deleted file mode 100644 index 0b28542830..0000000000 --- a/Spigot-Server-Patches/Avoid-hopper-searches-if-there-are-no-items.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CullanP -Date: Thu, 3 Mar 2016 02:13:38 -0600 -Subject: [PATCH] Avoid hopper searches if there are no items - -Hoppers searching for items and minecarts is the most expensive part of hopper ticking. -We keep track of the number of minecarts and items in a chunk. -If there are no items in the chunk, we skip searching for items. -If there are no minecarts in the chunk, we skip searching for them. - -Usually hoppers aren't near items, so we can skip most item searches. -And since minecart hoppers are used _very_ rarely near we can avoid alot of searching there. - -Combined, this adds up a lot. - -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -0,0 +0,0 @@ public final class IEntitySelector { - public static final Predicate c = (entity) -> { - return entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); - }; -+ public static final Predicate isInventory() { return d; } // Paper - OBFHELPER - public static final Predicate d = (entity) -> { - return entity instanceof IInventory && entity.isAlive(); - }; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.IInventory; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.IEntitySelector; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.TickList; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - return removed; - } - } -+ // Track the number of minecarts and items -+ // Keep this synced with entitySlices.add() and entitySlices.remove() -+ private final int[] itemCounts = new int[16]; -+ private final int[] inventoryEntityCounts = new int[16]; - // Paper end - - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ // Paper start -+ if (entity instanceof EntityItem) { -+ itemCounts[k]++; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[k]++; -+ } -+ // Paper end - entity.entitySlice = this.entitySlices[k]; // Paper - this.markDirty(); // Paper - } -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - if (!this.entitySlices[i].remove(entity)) { - return; - } -+ if (entity instanceof EntityItem) { -+ itemCounts[i]--; -+ } else if (entity instanceof IInventory) { -+ inventoryEntityCounts[i]--; -+ } - entityCounts.decrement(entity.getMinecraftKeyString()); - this.markDirty(); // Paper - // Paper end -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - for (int k = i; k <= j; ++k) { - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error - if (entity.shouldBeRemoved) continue; // Paper -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - i = MathHelper.clamp(i, 0, this.entitySlices.length - 1); - j = MathHelper.clamp(j, 0, this.entitySlices.length - 1); - -+ // Paper start -+ int[] counts; -+ if (EntityItem.class.isAssignableFrom(oclass)) { -+ counts = itemCounts; -+ } else if (IInventory.class.isAssignableFrom(oclass)) { -+ counts = inventoryEntityCounts; -+ } else { -+ counts = null; -+ } -+ // Paper end - for (int k = i; k <= j; ++k) { -+ if (counts != null && counts[k] <= 0) continue; // Paper - Don't check a chunk if it doesn't have the type we are looking for - Iterator iterator = this.entitySlices[k].iterator(); // Spigot - -+ // Paper start - Don't search for inventories if we have none, and that is all we want -+ /* -+ * We check if they want inventories by seeing if it is the static `IEntitySelector.d` -+ * -+ * Make sure the inventory selector stays in sync. -+ * It should be the one that checks `var1 instanceof IInventory && var1.isAlive()` -+ */ -+ if (predicate == IEntitySelector.isInventory() && inventoryEntityCounts[k] <= 0) continue; -+ // Paper end - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error - if (t0.shouldBeRemoved) continue; // Paper diff --git a/Spigot-Server-Patches/Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/Spigot-Server-Patches/Avoid-item-merge-if-stack-size-above-max-stack-size.patch deleted file mode 100644 index 8ee1a77385..0000000000 --- a/Spigot-Server-Patches/Avoid-item-merge-if-stack-size-above-max-stack-size.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 16 Jul 2018 12:42:20 +0200 -Subject: [PATCH] Avoid item merge if stack size above max stack size - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - - private void mergeNearby() { - if (this.z()) { -+ // Paper start - avoid item merge if stack size above max stack size -+ ItemStack stack = getItemStack(); -+ if (stack.getCount() >= stack.getMaxStackSize()) return; -+ // Paper end - // Spigot start - double radius = world.spigotConfig.itemMerge; - List list = this.world.a(EntityItem.class, this.getBoundingBox().grow(radius, radius, radius), (entityitem) -> { diff --git a/Spigot-Server-Patches/Basic-PlayerProfile-API.patch b/Spigot-Server-Patches/Basic-PlayerProfile-API.patch deleted file mode 100644 index f1242a28df..0000000000 --- a/Spigot-Server-Patches/Basic-PlayerProfile-API.patch +++ /dev/null @@ -1,575 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 15 Jan 2018 22:11:48 -0500 -Subject: [PATCH] Basic PlayerProfile API - -Establishes base extension of profile systems for future edits too - -diff --git a/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/CraftPlayerProfile.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.destroystokyo.paper.PaperConfig; -+import com.google.common.base.Charsets; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.properties.Property; -+import com.mojang.authlib.properties.PropertyMap; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.players.UserCache; -+import org.apache.commons.lang3.Validate; -+import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.spigotmc.SpigotConfig; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.AbstractSet; -+import java.util.Collection; -+import java.util.Iterator; -+import java.util.Objects; -+import java.util.Set; -+import java.util.UUID; -+ -+public class CraftPlayerProfile implements PlayerProfile { -+ -+ private GameProfile profile; -+ private final PropertySet properties = new PropertySet(); -+ -+ public CraftPlayerProfile(CraftPlayer player) { -+ this.profile = player.getHandle().getProfile(); -+ } -+ -+ public CraftPlayerProfile(UUID id, String name) { -+ this.profile = new GameProfile(id, name); -+ } -+ -+ public CraftPlayerProfile(GameProfile profile) { -+ Validate.notNull(profile, "GameProfile cannot be null!"); -+ this.profile = profile; -+ } -+ -+ @Override -+ public boolean hasProperty(String property) { -+ return profile.getProperties().containsKey(property); -+ } -+ -+ @Override -+ public void setProperty(ProfileProperty property) { -+ String name = property.getName(); -+ PropertyMap properties = profile.getProperties(); -+ properties.removeAll(name); -+ properties.put(name, new Property(name, property.getValue(), property.getSignature())); -+ } -+ -+ public GameProfile getGameProfile() { -+ return profile; -+ } -+ -+ @Nullable -+ @Override -+ public UUID getId() { -+ return profile.getId(); -+ } -+ -+ @Override -+ public UUID setId(@Nullable UUID uuid) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(uuid, prev.getName()); -+ copyProfileProperties(prev, this.profile); -+ return prev.getId(); -+ } -+ -+ @Nullable -+ @Override -+ public String getName() { -+ return profile.getName(); -+ } -+ -+ @Override -+ public String setName(@Nullable String name) { -+ GameProfile prev = this.profile; -+ this.profile = new GameProfile(prev.getId(), name); -+ copyProfileProperties(prev, this.profile); -+ return prev.getName(); -+ } -+ -+ @Nonnull -+ @Override -+ public Set getProperties() { -+ return properties; -+ } -+ -+ @Override -+ public void setProperties(Collection properties) { -+ properties.forEach(this::setProperty); -+ } -+ -+ @Override -+ public void clearProperties() { -+ profile.getProperties().clear(); -+ } -+ -+ @Override -+ public boolean removeProperty(String property) { -+ return !profile.getProperties().removeAll(property).isEmpty(); -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ CraftPlayerProfile that = (CraftPlayerProfile) o; -+ return Objects.equals(profile, that.profile); -+ } -+ -+ @Override -+ public int hashCode() { -+ return profile.hashCode(); -+ } -+ -+ @Override -+ public String toString() { -+ return profile.toString(); -+ } -+ -+ @Override -+ public CraftPlayerProfile clone() { -+ CraftPlayerProfile clone = new CraftPlayerProfile(this.getId(), this.getName()); -+ clone.setProperties(getProperties()); -+ return clone; -+ } -+ -+ @Override -+ public boolean isComplete() { -+ return profile.isComplete(); -+ } -+ -+ @Override -+ public boolean completeFromCache() { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return completeFromCache(false, PaperConfig.isProxyOnlineMode()); -+ } -+ -+ public boolean completeFromCache(boolean onlineMode) { -+ return completeFromCache(false, onlineMode); -+ } -+ -+ public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ String name = profile.getName(); -+ UserCache userCache = server.getUserCache(); -+ if (profile.getId() == null) { -+ final GameProfile profile; -+ if (onlineMode) { -+ profile = lookupUUID ? userCache.getProfile(name) : userCache.getProfileIfCached(name); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ if (profile != null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } -+ } -+ -+ if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { -+ GameProfile profile = userCache.getProfile(this.profile.getId()); -+ if (profile != null) { -+ if (this.profile.getName() == null) { -+ // if old has it, assume its newer, so overwrite, else use cached if it was set and ours wasn't -+ copyProfileProperties(this.profile, profile); -+ this.profile = profile; -+ } else { -+ copyProfileProperties(profile, this.profile); -+ } -+ } -+ } -+ return this.profile.isComplete(); -+ } -+ -+ public boolean complete(boolean textures) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ return complete(textures, PaperConfig.isProxyOnlineMode()); -+ } -+ public boolean complete(boolean textures, boolean onlineMode) { -+ MinecraftServer server = MinecraftServer.getServer(); -+ -+ boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); -+ if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { -+ GameProfile result = server.getMinecraftSessionService().fillProfileProperties(profile, true); -+ if (result != null) { -+ copyProfileProperties(result, this.profile, true); -+ } -+ if (this.profile.isComplete()) { -+ server.getUserCache().saveProfile(this.profile); -+ } -+ } -+ return profile.isComplete() && (!onlineMode || !textures || hasTextures()); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target) { -+ copyProfileProperties(source, target, false); -+ } -+ -+ private static void copyProfileProperties(GameProfile source, GameProfile target, boolean clearTarget) { -+ PropertyMap sourceProperties = source.getProperties(); -+ PropertyMap targetProperties = target.getProperties(); -+ if (clearTarget) targetProperties.clear(); -+ if (sourceProperties.isEmpty()) { -+ return; -+ } -+ -+ for (Property property : sourceProperties.values()) { -+ targetProperties.removeAll(property.getName()); -+ targetProperties.put(property.getName(), property); -+ } -+ } -+ -+ private static ProfileProperty toBukkit(Property property) { -+ return new ProfileProperty(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static PlayerProfile asBukkitCopy(GameProfile gameProfile) { -+ CraftPlayerProfile profile = new CraftPlayerProfile(gameProfile.getId(), gameProfile.getName()); -+ copyProfileProperties(gameProfile, profile.profile); -+ return profile; -+ } -+ -+ public static PlayerProfile asBukkitMirror(GameProfile profile) { -+ return new CraftPlayerProfile(profile); -+ } -+ -+ public static Property asAuthlib(ProfileProperty property) { -+ return new Property(property.getName(), property.getValue(), property.getSignature()); -+ } -+ -+ public static GameProfile asAuthlibCopy(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return asAuthlib(craft.clone()); -+ } -+ -+ public static GameProfile asAuthlib(PlayerProfile profile) { -+ CraftPlayerProfile craft = ((CraftPlayerProfile) profile); -+ return craft.getGameProfile(); -+ } -+ -+ private class PropertySet extends AbstractSet { -+ -+ @Override -+ @Nonnull -+ public Iterator iterator() { -+ return new ProfilePropertyIterator(profile.getProperties().values().iterator()); -+ } -+ -+ @Override -+ public int size() { -+ return profile.getProperties().size(); -+ } -+ -+ @Override -+ public boolean add(ProfileProperty property) { -+ setProperty(property); -+ return true; -+ } -+ -+ @Override -+ public boolean addAll(Collection c) { -+ //noinspection unchecked -+ setProperties((Collection) c); -+ return true; -+ } -+ -+ @Override -+ public boolean contains(Object o) { -+ return o instanceof ProfileProperty && profile.getProperties().containsKey(((ProfileProperty) o).getName()); -+ } -+ -+ private class ProfilePropertyIterator implements Iterator { -+ private final Iterator iterator; -+ -+ ProfilePropertyIterator(Iterator iterator) { -+ this.iterator = iterator; -+ } -+ -+ @Override -+ public boolean hasNext() { -+ return iterator.hasNext(); -+ } -+ -+ @Override -+ public ProfileProperty next() { -+ return toBukkit(iterator.next()); -+ } -+ -+ @Override -+ public void remove() { -+ iterator.remove(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.*; -+import com.mojang.authlib.minecraft.MinecraftSessionService; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; -+ -+import java.net.Proxy; -+ -+public class PaperAuthenticationService extends YggdrasilAuthenticationService { -+ private final Environment environment; -+ public PaperAuthenticationService(Proxy proxy) { -+ super(proxy); -+ this.environment = (Environment)EnvironmentParser.getEnvironmentFromProperties().orElse(YggdrasilEnvironment.PROD);; -+ } -+ -+ @Override -+ public UserAuthentication createUserAuthentication(Agent agent) { -+ return new PaperUserAuthentication(this, agent); -+ } -+ -+ @Override -+ public MinecraftSessionService createMinecraftSessionService() { -+ return new PaperMinecraftSessionService(this, this.environment); -+ } -+ -+ @Override -+ public GameProfileRepository createProfileRepository() { -+ return new PaperGameProfileRepository(this, this.environment); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.ProfileLookupCallback; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; -+ -+public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { -+ public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -+ super.findProfilesByNames(names, agent, callback); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; -+import com.mojang.authlib.minecraft.MinecraftProfileTexture; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; -+ -+import java.util.Map; -+ -+public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionService { -+ protected PaperMinecraftSessionService(YggdrasilAuthenticationService authenticationService, Environment environment) { -+ super(authenticationService, environment); -+ } -+ -+ @Override -+ public Map getTextures(GameProfile profile, boolean requireSecure) { -+ return super.getTextures(profile, requireSecure); -+ } -+ -+ @Override -+ public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -+ return super.fillProfileProperties(profile, requireSecure); -+ } -+ -+ @Override -+ protected GameProfile fillGameProfile(GameProfile profile, boolean requireSecure) { -+ return super.fillGameProfile(profile, requireSecure); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperUserAuthentication.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.profile; -+ -+import com.mojang.authlib.Agent; -+import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -+import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; -+import java.util.UUID; -+ -+public class PaperUserAuthentication extends YggdrasilUserAuthentication { -+ public PaperUserAuthentication(YggdrasilAuthenticationService authenticationService, Agent agent) { -+ super(authenticationService, UUID.randomUUID().toString(), agent); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ - package net.minecraft.server; - - import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPosition; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.level.World; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.mojang.authlib.GameProfile; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -0,0 +0,0 @@ public final class MCUtil { - return run.get(); - } - -+ public static PlayerProfile toBukkit(GameProfile profile) { -+ return CraftPlayerProfile.asBukkitMirror(profile); -+ } -+ - /** - * Calculates distance between 2 entities - * @param e1 -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ public class Main { - } - - File file = (File) optionset.valueOf("universe"); // CraftBukkit -- YggdrasilAuthenticationService yggdrasilauthenticationservice = new YggdrasilAuthenticationService(Proxy.NO_PROXY); -+ YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); - UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -0,0 +0,0 @@ public class UserCache { - - private static final Logger LOGGER = LogManager.getLogger(); - private static boolean b; -- private final Map c = Maps.newConcurrentMap(); -+ private final Map c = Maps.newConcurrentMap();private final Map nameCache = c; // Paper - OBFHELPER // Paper - private final Map d = Maps.newConcurrentMap(); - private final GameProfileRepository e; - private final Gson f = (new GsonBuilder()).create(); -@@ -0,0 +0,0 @@ public class UserCache { - return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper - } - -+ public void saveProfile(GameProfile gameprofile) { a(gameprofile); } // Paper - OBFHELPER - public synchronized void a(GameProfile gameprofile) { // Paper - synchronize - Calendar calendar = Calendar.getInstance(); - -@@ -0,0 +0,0 @@ public class UserCache { - return gameprofile; - } - -+ // Paper start -+ @Nullable public GameProfile getProfileIfCached(String name) { -+ UserCache.UserCacheEntry entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); -+ return entry == null ? null : entry.getProfile(); -+ } -+ // Paper end -+ - @Nullable - public GameProfile getProfile(UUID uuid) { - UserCache.UserCacheEntry usercache_usercacheentry = (UserCache.UserCacheEntry) this.d.get(uuid); -@@ -0,0 +0,0 @@ public class UserCache { - - static class UserCacheEntry { - -- private final GameProfile a; -+ private final GameProfile a;public GameProfile getProfile() { return a; } // Paper - OBFHELPER - private final Date b; - private volatile long c; - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - -+import javax.annotation.Nullable; // Paper -+import javax.annotation.Nonnull; // Paper -+ - public final class CraftServer implements Server { - private final String serverName = "Paper"; // Paper - private final String serverVersion; -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - public boolean suggestPlayerNamesWhenNullTabCompletions() { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { -+ return createProfile(uuid, null); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull String name) { -+ return createProfile(null, name); -+ } -+ -+ @Override -+ public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nullable UUID uuid, @Nullable String name) { -+ Player player = uuid != null ? Bukkit.getPlayer(uuid) : (name != null ? Bukkit.getPlayerExact(name) : null); -+ if (player != null) { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile((CraftPlayer)player); -+ } -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - } - - private void setProfile(GameProfile profile) { -+ // Paper start -+ if (profile != null) { -+ com.destroystokyo.paper.profile.CraftPlayerProfile paperProfile = new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); -+ paperProfile.completeFromCache(false, true); -+ profile = paperProfile.getGameProfile(); -+ } -+ // Paper end - this.profile = profile; - this.serializedProfile = (profile == null) ? null : GameProfileSerializer.serialize(new NBTTagCompound(), profile); - } diff --git a/Spigot-Server-Patches/Be-a-bit-more-informative-in-maxHealth-exception.patch b/Spigot-Server-Patches/Be-a-bit-more-informative-in-maxHealth-exception.patch deleted file mode 100644 index 9ad4d1b879..0000000000 --- a/Spigot-Server-Patches/Be-a-bit-more-informative-in-maxHealth-exception.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Thu, 3 Mar 2016 02:18:39 -0600 -Subject: [PATCH] Be a bit more informative in maxHealth exception - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setHealth(double health) { - health = (float) health; - if ((health < 0) || (health > getMaxHealth())) { -- throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + "(" + health + ")"); -+ // Paper - Be more informative -+ throw new IllegalArgumentException("Health must be between 0 and " + getMaxHealth() + ", but was " + health -+ + ". (attribute base value: " + this.getHandle().getAttributeInstance(GenericAttributes.MAX_HEALTH).getBaseValue() -+ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); - } - - getHandle().setHealth((float) health); diff --git a/Spigot-Server-Patches/Beacon-API-custom-effect-ranges.patch b/Spigot-Server-Patches/Beacon-API-custom-effect-ranges.patch deleted file mode 100644 index 1b0ffdf1cf..0000000000 --- a/Spigot-Server-Patches/Beacon-API-custom-effect-ranges.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 24 Jun 2020 12:39:08 -0600 -Subject: [PATCH] Beacon API - custom effect ranges - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - return (hasSecondaryEffect()) ? CraftPotionUtil.toBukkit(new MobEffect(this.secondaryEffect, getLevel(), getAmplification(), true, true)) : null; - } - // CraftBukkit end -+ // Paper start - add field/methods for custom range -+ private final String PAPER_RANGE_TAG = "Paper.Range"; -+ private double effectRange = -1; -+ -+ public double getEffectRange() { -+ if (this.effectRange < 0) { -+ return this.levels * 10 + 10; -+ } else { -+ return effectRange; -+ } -+ } -+ -+ public void setEffectRange(double range) { -+ this.effectRange = range; -+ } -+ -+ public void resetEffectRange() { -+ this.effectRange = -1; -+ } -+ // Paper end - - public TileEntityBeacon() { - super(TileEntityTypes.BEACON); -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - - public List getHumansInRange() { - { -- double d0 = (double) (this.levels * 10 + 10); -+ // Paper - custom beacon ranges -+ double d0 = this.getEffectRange(); - - AxisAlignedBB axisalignedbb = (new AxisAlignedBB(this.position)).g(d0).b(0.0D, (double) this.world.getBuildHeight(), 0.0D); - List list = this.world.a(EntityHuman.class, axisalignedbb); -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - this.secondaryEffect = MobEffectList.fromId(nbttagcompound.getInt("Secondary")); - this.levels = nbttagcompound.getInt("Levels"); // SPIGOT-5053, use where available - // CraftBukkit end -+ // Paper -+ this.effectRange = nbttagcompound.hasKeyOfType(PAPER_RANGE_TAG, 6) ? nbttagcompound.getDouble(PAPER_RANGE_TAG) : -1; -+ - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { - this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); - } -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - if (this.customName != null) { - nbttagcompound.setString("CustomName", IChatBaseComponent.ChatSerializer.a(this.customName)); - } -+ // Paper -+ nbttagcompound.setDouble(PAPER_RANGE_TAG, this.effectRange); - - this.chestLock.a(nbttagcompound); - return nbttagcompound; -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java -@@ -0,0 +0,0 @@ public class CraftBeacon extends CraftBlockEntityState impleme - public void setLock(String key) { - this.getSnapshot().chestLock = (key == null) ? ChestLock.a : new ChestLock(key); - } -+ -+ @Override -+ public double getEffectRange() { -+ return this.getSnapshot().getEffectRange(); -+ } -+ -+ @Override -+ public void setEffectRange(double range) { -+ this.getSnapshot().setEffectRange(range); -+ } -+ -+ @Override -+ public void resetEffectRange() { -+ this.getSnapshot().resetEffectRange(); -+ } - } diff --git a/Spigot-Server-Patches/Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/Spigot-Server-Patches/Bees-get-gravity-in-void.-Fixes-MC-167279.patch deleted file mode 100644 index baffd443c9..0000000000 --- a/Spigot-Server-Patches/Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 26 Jan 2020 16:30:19 -0600 -Subject: [PATCH] Bees get gravity in void. Fixes MC-167279 - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMove.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.shapes.VoxelShape; - - public class ControllerMove { - -- protected final EntityInsentient a; -+ protected final EntityInsentient a; public final EntityInsentient getEntity() { return a; } // Paper - OBFHELPER - protected double b; - protected double c; - protected double d; -diff --git a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -+++ b/src/main/java/net/minecraft/world/entity/ai/control/ControllerMoveFlying.java -@@ -0,0 +0,0 @@ public class ControllerMoveFlying extends ControllerMove { - } - - @Override -- public void a() { -+ public void a() { tick(); } public void tick() { // Paper - OBFHELPER - if (this.h == ControllerMove.Operation.MOVE_TO) { - this.h = ControllerMove.Operation.WAIT; - this.a.setNoGravity(true); -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - public EntityBee(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.moveController = new ControllerMoveFlying(this, 20, true); -+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 -+ this.moveController = new ControllerMoveFlying(this, 20, true) { -+ @Override -+ public void tick() { -+ if (getEntity().locY() <= 0) { -+ getEntity().setNoGravity(false); -+ } -+ super.tick(); -+ } -+ }; -+ // Paper end - this.lookController = new EntityBee.j(this); - this.a(PathType.DANGER_FIRE, -1.0F); - this.a(PathType.WATER, -1.0F); diff --git a/Spigot-Server-Patches/Block-Enderpearl-Travel-Exploit.patch b/Spigot-Server-Patches/Block-Enderpearl-Travel-Exploit.patch deleted file mode 100644 index f252ae46ae..0000000000 --- a/Spigot-Server-Patches/Block-Enderpearl-Travel-Exploit.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 17:15:26 -0400 -Subject: [PATCH] Block Enderpearl Travel Exploit - -Players are able to use alt accounts and enderpearls to travel -long distances utilizing the pearls in unloaded chunks and loading -the chunk later when convenient. - -This disables that by not saving the thrower when the chunk is unloaded. - -This is mainly useful for survival servers that do not allow freeform teleporting. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableSprintInterruptionOnAttack() { - disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); - } -+ -+ public boolean disableEnderpearlExploit = true; -+ private void disableEnderpearlExploit() { -+ disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); -+ log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -0,0 +0,0 @@ public abstract class IProjectile extends Entity { - protected void loadData(NBTTagCompound nbttagcompound) { - if (nbttagcompound.b("Owner")) { - this.shooter = nbttagcompound.a("Owner"); -+ if (this instanceof EntityEnderPearl && this.world != null && this.world.paperConfig.disableEnderpearlExploit) { this.shooter = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit - } - - this.d = nbttagcompound.getBoolean("LeftOwner"); diff --git a/Spigot-Server-Patches/Block-Entity-remove-from-being-called-on-Players.patch b/Spigot-Server-Patches/Block-Entity-remove-from-being-called-on-Players.patch deleted file mode 100644 index 129b2336d0..0000000000 --- a/Spigot-Server-Patches/Block-Entity-remove-from-being-called-on-Players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Mon, 4 Feb 2019 23:33:24 -0500 -Subject: [PATCH] Block Entity#remove from being called on Players - -This doesn't result in the same behavior as other entities and causes -several problems. Anyone ever complain about the "Cannot send chat -message" thing? That's one of the issues this causes, among others. - -If a plugin developer can come up with a valid reason to call this on a -Player we will look at limiting the scope of this change. It appears to -be unintentional in the few cases we've seen so far. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void resetCooldown() { - getHandle().resetAttackCooldown(); - } -+ -+ @Override -+ public void remove() { -+ if (this.getHandle().getClass().equals(EntityPlayer.class)) { // special case for NMS plugins inheriting -+ throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); -+ } else { -+ super.remove(); -+ } -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/Block-player-logins-during-server-shutdown.patch b/Spigot-Server-Patches/Block-player-logins-during-server-shutdown.patch deleted file mode 100644 index 542217531f..0000000000 --- a/Spigot-Server-Patches/Block-player-logins-during-server-shutdown.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sun, 2 Jul 2017 21:35:56 -0500 -Subject: [PATCH] Block player logins during server shutdown - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - } - - public void tick() { -+ // Paper start - Do not allow logins while the server is shutting down -+ if (!MinecraftServer.getServer().isRunning()) { -+ this.disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(org.spigotmc.SpigotConfig.restartMessage)[0]); -+ return; -+ } -+ // Paper end - if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { - this.c(); - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { diff --git a/Spigot-Server-Patches/BlockDestroyEvent.patch b/Spigot-Server-Patches/BlockDestroyEvent.patch deleted file mode 100644 index a7158f3a75..0000000000 --- a/Spigot-Server-Patches/BlockDestroyEvent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 Feb 2019 00:20:33 -0500 -Subject: [PATCH] BlockDestroyEvent - -Adds an event for when the server is going to destroy a current block, -potentially causing it to drop. This event can be cancelled to avoid -the block destruction, such as preventing signs from popping when -floating in the air. - -This can replace many uses of BlockPhysicsEvent - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ import net.minecraft.core.particles.ParticleParam; - import net.minecraft.network.protocol.Packet; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return false; - } else { - Fluid fluid = this.getFluid(blockposition); -+ // Paper start - while the above setAir method is named same and looks very similar -+ // they are NOT used with same intent and the above should not fire this event. The above method is more of a BlockSetToAirEvent, -+ // it doesn't imply destruction of a block that plays a sound effect / drops an item. -+ boolean playEffect = true; -+ if (com.destroystokyo.paper.event.block.BlockDestroyEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, blockposition), fluid.getBlockData().createCraftBlockData(), flag); -+ if (!event.callEvent()) { -+ return false; -+ } -+ playEffect = event.playEffect(); -+ } -+ // Paper end - -- if (!(iblockdata.getBlock() instanceof BlockFireAbstract)) { -+ if (playEffect && !(iblockdata.getBlock() instanceof BlockFireAbstract)) { // Paper - this.triggerEffect(2001, blockposition, Block.getCombinedId(iblockdata)); - } - diff --git a/Spigot-Server-Patches/Book-Size-Limits.patch b/Spigot-Server-Patches/Book-Size-Limits.patch deleted file mode 100644 index 0a4db2d6bf..0000000000 --- a/Spigot-Server-Patches/Book-Size-Limits.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Nov 2018 23:08:50 -0500 -Subject: [PATCH] Book Size Limits - -Puts some limits on the size of books. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); - } - } -+ -+ public static int maxBookPageSize = 2560; -+ public static double maxBookTotalSizeMultiplier = 0.98D; -+ private static void maxBookSize() { -+ maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize); -+ maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInBEdit packetplayinbedit) { -+ // Paper start -+ ItemStack testStack = packetplayinbedit.getBook(); -+ if (!server.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { -+ NBTTagList pageList = testStack.getTag().getList("pages", 8); -+ if (pageList.size() > 100) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with too many pages"); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ long byteTotal = 0; -+ int maxBookPageSize = com.destroystokyo.paper.PaperConfig.maxBookPageSize; -+ double multiplier = Math.max(0.3D, Math.min(1D, com.destroystokyo.paper.PaperConfig.maxBookTotalSizeMultiplier)); -+ long byteAllowed = maxBookPageSize; -+ for (int i = 0; i < pageList.size(); ++i) { -+ String testString = pageList.getString(i); -+ int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; -+ if (byteLength > 256 * 4) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send a book with with a page too large!"); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ byteTotal += byteLength; -+ int length = testString.length(); -+ int multibytes = 0; -+ if (byteLength != length) { -+ for (char c : testString.toCharArray()) { -+ if (c > 127) { -+ multibytes++; -+ } -+ } -+ } -+ byteAllowed += (maxBookPageSize * Math.min(1, Math.max(0.1D, (double) length / 255D))) * multiplier; -+ -+ if (multibytes > 1) { -+ // penalize MB -+ byteAllowed -= multibytes; -+ } -+ } -+ -+ if (byteTotal > byteAllowed) { -+ PlayerConnection.LOGGER.warn(this.player.getName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -+ minecraftServer.scheduleOnMain(() -> this.disconnect("Book too large!")); -+ return; -+ } -+ } -+ // Paper end - // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { - this.disconnect("Book edited too quickly!"); diff --git a/Spigot-Server-Patches/Bound-Treasure-Maps-to-World-Border.patch b/Spigot-Server-Patches/Bound-Treasure-Maps-to-World-Border.patch deleted file mode 100644 index 215089e4df..0000000000 --- a/Spigot-Server-Patches/Bound-Treasure-Maps-to-World-Border.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:15:11 -0500 -Subject: [PATCH] Bound Treasure Maps to World Border - -Make it so a Treasure Map does not target a structure outside of the -World Border, where players are not even able to reach. - -This also would help the case where a players close to the border, and one -that is outside happens to be closer, but unreachable, yet another reachable -one is in border that would of been missed. - -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -0,0 +0,0 @@ public class WorldBorder { - return (double) (blockposition.getX() + 1) > this.e() && (double) blockposition.getX() < this.g() && (double) (blockposition.getZ() + 1) > this.f() && (double) blockposition.getZ() < this.h(); - } - -+ // Paper start -+ private final BlockPosition.MutableBlockPosition mutPos = new BlockPosition.MutableBlockPosition(); -+ public boolean isBlockInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(chunkX, 64, chunkZ); -+ return this.isInBounds(this.mutPos); -+ } -+ public boolean isChunkInBounds(int chunkX, int chunkZ) { -+ this.mutPos.setValues(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); -+ return this.isInBounds(this.mutPos); -+ } -+ // Paper end -+ - public boolean isInBounds(ChunkCoordIntPair chunkcoordintpair) { - return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -0,0 +0,0 @@ public abstract class StructureGenerator - int i2 = l + k * k1; - int j2 = i1 + k * l1; - ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); -+ if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper - IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); - StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); - diff --git a/Spigot-Server-Patches/Break-up-and-make-tab-spam-limits-configurable.patch b/Spigot-Server-Patches/Break-up-and-make-tab-spam-limits-configurable.patch deleted file mode 100644 index f2286f54ef..0000000000 --- a/Spigot-Server-Patches/Break-up-and-make-tab-spam-limits-configurable.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 29 Jul 2018 05:02:15 +0100 -Subject: [PATCH] Break up and make tab spam limits configurable - -Due to the changes in 1.13, clients will send a tab completion request -for all bukkit commands in order to factor in the lack of support for -brigadier and provide backwards support in the API. - -Craftbukkit, however; has moved the chat spam limiter to also interact -with the tab completion request, which while good for avoiding abuse, -causes 1.13 clients to easilly be kicked from a server in bukkit due -to this. Removing the spam limit could cause issues for servers, however, -there is no way for servers to manipulate this without blindly cancelling -kick events, which only causes additional complications. This also causes -issues in that the tab spam limit and chat share the same field but different -limits, meaning that a player having typed a long command may be kicked from -the server. - -Splitting the field up and making it configurable allows for server owners -to take the burden of this into their own hand without having to rely on -plugins doing unsafe things. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); - } - } -+ -+ public static int tabSpamIncrement = 1; -+ public static int tabSpamLimit = 500; -+ private static void tabSpamLimiters() { -+ tabSpamIncrement = getInt("settings.spam-limiter.tab-spam-increment", tabSpamIncrement); -+ // Older versions used a smaller limit, which is too low for 1.13, we'll bump this up if default -+ if (version < 14) { -+ if (tabSpamIncrement == 10) { -+ set("settings.spam-limiter.tab-spam-increment", 2); -+ tabSpamIncrement = 2; -+ } -+ } -+ tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - multithreaded fields - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); -+ private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits - // CraftBukkit end - private int j; - private final Int2ShortMap k = new Int2ShortOpenHashMap(); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.minecraftServer.getMethodProfiler().exit(); - // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; -+ if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInTabComplete packetplayintabcomplete) { - // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async - // CraftBukkit start -- if (chatSpamField.addAndGet(this, 1) > 500 && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { -+ if (tabSpamLimiter.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.minecraftServer.getPlayerList().isOp(this.player.getProfile())) { // Paper start - split and make configurable - minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper - return; - } diff --git a/Spigot-Server-Patches/Broadcast-join-message-to-console.patch b/Spigot-Server-Patches/Broadcast-join-message-to-console.patch deleted file mode 100644 index 409e9c683e..0000000000 --- a/Spigot-Server-Patches/Broadcast-join-message-to-console.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AvrooVulcan -Date: Fri, 17 Apr 2020 00:15:23 +0100 -Subject: [PATCH] Broadcast join message to console - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure - joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure -- server.getPlayerList().sendAll(new PacketPlayOutChat(joinMessage, ChatMessageType.SYSTEM, SystemUtils.b)); // Paper - Adventure -+ // Paper start - Removed sendAll for loop and broadcasted to console also -+ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure -+ // Paper end - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/Buffer-joins-to-world.patch b/Spigot-Server-Patches/Buffer-joins-to-world.patch deleted file mode 100644 index 4463c2b384..0000000000 --- a/Spigot-Server-Patches/Buffer-joins-to-world.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 19 Aug 2020 05:05:54 +0100 -Subject: [PATCH] Buffer joins to world - -This patch buffers the number of logins which will attempt to join -the world per tick, this attempts to reduce the impact that join floods -has on the server - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; - } - } -+ -+ public static int maxJoinsPerTick; -+ private static void maxJoinsPerTick() { -+ maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); -+ } - } -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; - import net.minecraft.network.protocol.game.PacketPlayOutTitle; - import net.minecraft.server.CancelledPacketHandleException; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.network.LoginListener; - import net.minecraft.server.network.PlayerConnection; -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - // Paper end - -+ private static final int MAX_PER_TICK = com.destroystokyo.paper.PaperConfig.maxJoinsPerTick; // Paper -+ private static int joinAttemptsThisTick; // Paper -+ private static int currTick; // Paper - public void a() { - this.p(); -+ // Paper start -+ if (currTick != MinecraftServer.currentTick) { -+ currTick = MinecraftServer.currentTick; -+ joinAttemptsThisTick = 0; -+ } -+ // Paper end - if (this.packetListener instanceof LoginListener) { -+ if ( ((LoginListener) this.packetListener).getLoginState() != LoginListener.EnumProtocolState.READY_TO_ACCEPT // Paper -+ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick - ((LoginListener) this.packetListener).tick(); -+ } // Paper - } - - if (this.packetListener instanceof PlayerConnection) { -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - return new GameProfile(uuid, gameprofile.getName()); - } - -- static enum EnumProtocolState { -+ public enum EnumProtocolState { // Paper - package private -> public - - HELLO, KEY, AUTHENTICATING, NEGOTIATING, READY_TO_ACCEPT, DELAY_ACCEPT, ACCEPTED; - diff --git a/Spigot-Server-Patches/Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/Spigot-Server-Patches/Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch deleted file mode 100644 index dbe2725dd3..0000000000 --- a/Spigot-Server-Patches/Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 12 Sep 2020 17:21:38 -0400 -Subject: [PATCH] Cache DataFixerUpper Rewrite Rules on demand - -Mojang precaches every single potential rewrite rule that could ever -exist on server startup. This includes rules from all the way back to versions from 6+ years ago. - -This is the source of why the server hogs every CPU core at 100% every start. - -For anyone who hard resets for updates or has force upgraded their entire world, this -results in completely wasted cpu cycles. - -This massive CPU usage also delays server startup time. - -We improve this by making "min version to precache" that defaults to a future version -so that no rewrite rules are precached. - -someone who expects to be converting a lot chunks could theoretically set --DPaper.minPrecachedDatafixVersion= as a startup -parameter and only build from that point on. - -However this will likely never be needed as the server will still run -the same cache logic on demand when it's actually needed. The only -cost would be some delay on the FIRST chunk conversion, but paper already -runs chunk conversions on another thread so this will likely never be -a concern for TPS. - -This patch will significantly reduce CPU use on startup, reduce memory usage, -and improve server startup time. - -diff --git a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -+++ b/src/main/java/com/mojang/datafixers/DataFixerBuilder.java -@@ -0,0 +0,0 @@ public class DataFixerBuilder { - private final Int2ObjectSortedMap schemas = new Int2ObjectAVLTreeMap<>(); - private final List globalList = Lists.newArrayList(); - private final IntSortedSet fixerVersions = new IntAVLTreeSet(); -+ private final int minDataFixPrecacheVersion; // Paper - - public DataFixerBuilder(final int dataVersion) { -+ minDataFixPrecacheVersion = Integer.getInteger("Paper.minPrecachedDatafixVersion", dataVersion+1) * 10; // Paper - default to precache nothing - mojang stores versions * 10 to allow for 'sub versions' - this.dataVersion = dataVersion; - } - -@@ -0,0 +0,0 @@ public class DataFixerBuilder { - final IntBidirectionalIterator iterator = fixerUpper.fixerVersions().iterator(); - while (iterator.hasNext()) { - final int versionKey = iterator.nextInt(); -+ if (versionKey < minDataFixPrecacheVersion) continue; // Paper - final Schema schema = schemas.get(versionKey); - for (final String typeName : schema.types()) { - CompletableFuture.runAsync(() -> { diff --git a/Spigot-Server-Patches/Cache-block-data-strings.patch b/Spigot-Server-Patches/Cache-block-data-strings.patch deleted file mode 100644 index 1b8e7d42f2..0000000000 --- a/Spigot-Server-Patches/Cache-block-data-strings.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 6 Dec 2018 19:52:50 -0500 -Subject: [PATCH] Cache block data strings - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant%s", nms, bukkit); - } - -+ // Paper start - cache block data strings -+ private static Map stringDataCache = new HashMap<>(); -+ -+ static { -+ // cache all of the default states at startup, will not cache ones with the custom states inside of the -+ // brackets in a different order, though -+ reloadCache(); -+ } -+ -+ public static void reloadCache() { -+ stringDataCache.clear(); -+ Block.REGISTRY_ID.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); -+ } -+ // Paper end -+ - public static CraftBlockData newData(Material material, String data) { - Preconditions.checkArgument(material == null || material.isBlock(), "Cannot get data for not block %s", material); - -+ // Paper start - cache block data strings -+ if (material != null) { -+ Block block = CraftMagicNumbers.getBlock(material); -+ if (block != null) { -+ MinecraftKey key = IRegistry.BLOCK.getKey(block); -+ data = data == null ? key.toString() : key + data; -+ } -+ } -+ -+ CraftBlockData cached = stringDataCache.computeIfAbsent(data, s -> createNewData(null, s)); -+ return (CraftBlockData) cached.clone(); -+ } -+ -+ private static CraftBlockData createNewData(Material material, String data) { -+ // Paper end - cache block data strings - IBlockData blockData; - Block block = CraftMagicNumbers.getBlock(material); - Map, Comparable> parsed = null; diff --git a/Spigot-Server-Patches/Cache-burn-durations.patch b/Spigot-Server-Patches/Cache-burn-durations.patch deleted file mode 100644 index 2520a3394a..0000000000 --- a/Spigot-Server-Patches/Cache-burn-durations.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 16:47:00 +0100 -Subject: [PATCH] Cache burn durations - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block.entity; - -+import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - this.c = recipes; - } - -+ private static Map cachedBurnDurations = null; // Paper - cache burn durations -+ -+ public static Map getBurnDurations() { return f(); } // Paper - OBFHELPER - public static Map f() { -+ // Paper start - cache burn durations -+ if(cachedBurnDurations != null) { -+ return cachedBurnDurations; -+ } -+ // Paper end - Map map = Maps.newLinkedHashMap(); - - a(map, (IMaterial) Items.LAVA_BUCKET, 20000); -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - a(map, (IMaterial) Blocks.FLETCHING_TABLE, 300); - a(map, (IMaterial) Blocks.SMITHING_TABLE, 300); - a(map, (IMaterial) Blocks.COMPOSTER, 300); -- return map; -+ // Paper start - cache burn durations -+ cachedBurnDurations = ImmutableMap.copyOf(map); -+ return cachedBurnDurations; -+ // Paper end - } - - // CraftBukkit start - add fields and methods -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - } else { - Item item = itemstack.getItem(); - -- return (Integer) f().getOrDefault(item, 0); -+ return getBurnDurations().getOrDefault(item, 0); // Paper - cache burn durations - } - } - -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - // Paper end - - public static boolean isFuel(ItemStack itemstack) { -- return f().containsKey(itemstack.getItem()); -+ return getBurnDurations().containsKey(itemstack.getItem()); // Paper - cache burn durations - } - - @Override diff --git a/Spigot-Server-Patches/Cache-user-authenticator-threads.patch b/Spigot-Server-Patches/Cache-user-authenticator-threads.patch deleted file mode 100644 index 85b74cbfcd..0000000000 --- a/Spigot-Server-Patches/Cache-user-authenticator-threads.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: vemacs -Date: Wed, 23 Nov 2016 08:31:45 -0500 -Subject: [PATCH] Cache user authenticator threads - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; - import com.mojang.serialization.DataResult; -+import java.util.ArrayDeque; // Paper - import java.util.Collection; -+import java.util.Deque; // Paper - import java.util.Iterator; - import java.util.List; - import java.util.Optional; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public PlayerConnection playerConnection; - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; -- public final List removeQueue = Lists.newLinkedList(); -+ public final Deque removeQueue = new ArrayDeque<>(); // Paper - private final AdvancementDataPlayer advancementDataPlayer; - private final ServerStatisticManager serverStatisticManager; - private float lastHealthScored = Float.MIN_VALUE; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - while (!this.removeQueue.isEmpty()) { - int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); - int[] aint = new int[i]; -- Iterator iterator = this.removeQueue.iterator(); -+ //Iterator iterator = this.removeQueue.iterator(); // Paper - int j = 0; - -- while (iterator.hasNext() && j < i) { -+ // Paper start -+ /* while (iterator.hasNext() && j < i) { - aint[j++] = (Integer) iterator.next(); - iterator.remove(); -+ } */ -+ -+ Integer integer; -+ while (j < i && (integer = this.removeQueue.poll()) != null) { -+ aint[j++] = integer.intValue(); - } -+ // Paper end - - this.playerConnection.sendPacket(new PacketPlayOutEntityDestroy(aint)); - } -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.lastHealthSent = -1.0F; - this.lastFoodSent = -1; - // this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit -- this.removeQueue.addAll(entityplayer.removeQueue); -+ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only -+ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" -+ // type logic so it does need to be called, maybe? This is silly. -+ // this.removeQueue.addAll(entityplayer.removeQueue); -+ if (this.removeQueue != entityplayer.removeQueue) { -+ this.removeQueue.addAll(entityplayer.removeQueue); -+ } -+ // Paper end - this.cd = entityplayer.cd; - this.ci = entityplayer.ci; - this.setShoulderEntityLeft(entityplayer.getShoulderEntityLeft()); diff --git a/Spigot-Server-Patches/Call-PaperServerListPingEvent-for-legacy-pings.patch b/Spigot-Server-Patches/Call-PaperServerListPingEvent-for-legacy-pings.patch deleted file mode 100644 index 073db9e8fd..0000000000 --- a/Spigot-Server-Patches/Call-PaperServerListPingEvent-for-legacy-pings.patch +++ /dev/null @@ -1,154 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 19:30:51 +0200 -Subject: [PATCH] Call PaperServerListPingEvent for legacy pings - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperLegacyStatusClient.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang3.StringUtils; -+import org.bukkit.ChatColor; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+ -+public final class PaperLegacyStatusClient implements StatusClient { -+ -+ private final InetSocketAddress address; -+ private final int protocolVersion; -+ @Nullable private final InetSocketAddress virtualHost; -+ -+ private PaperLegacyStatusClient(InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ this.address = address; -+ this.protocolVersion = protocolVersion; -+ this.virtualHost = virtualHost; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return this.address; -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.virtualHost; -+ } -+ -+ @Override -+ public boolean isLegacy() { -+ return true; -+ } -+ -+ public static PaperServerListPingEvent processRequest(MinecraftServer server, -+ InetSocketAddress address, int protocolVersion, @Nullable InetSocketAddress virtualHost) { -+ -+ PaperServerListPingEvent event = new PaperServerListPingEventImpl(server, -+ new PaperLegacyStatusClient(address, protocolVersion, virtualHost), Byte.MAX_VALUE, null); -+ server.server.getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ return null; -+ } -+ -+ return event; -+ } -+ -+ public static String getMotd(PaperServerListPingEvent event) { -+ return getFirstLine(event.getMotd()); -+ } -+ -+ public static String getUnformattedMotd(PaperServerListPingEvent event) { -+ // Strip color codes and all other occurrences of the color char (because it's used as delimiter) -+ return getFirstLine(StringUtils.remove(ChatColor.stripColor(event.getMotd()), ChatColor.COLOR_CHAR)); -+ } -+ -+ private static String getFirstLine(String s) { -+ int pos = s.indexOf('\n'); -+ return pos >= 0 ? s.substring(0, pos) : s; -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.network.PaperLegacyStatusClient; -+ - import io.netty.buffer.ByteBuf; - import io.netty.buffer.Unpooled; - import io.netty.channel.ChannelFutureListener; -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - MinecraftServer minecraftserver = this.b.d(); - int i = bytebuf.readableBytes(); - String s; -- org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit -+ //org.bukkit.event.server.ServerListPingEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callServerListPingEvent(minecraftserver.server, inetsocketaddress.getAddress(), minecraftserver.getMotd(), minecraftserver.getPlayerCount(), minecraftserver.getMaxPlayers()); // CraftBukkit // Paper -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper - - switch (i) { - case 0: - LegacyPingHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("%s\u00a7%d\u00a7%d", event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 39, null); -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.a(channelhandlercontext, this.a(s)); - break; - case 1: -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - } - - LegacyPingHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); -- s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); // CraftBukkit -+ // Paper start - Call PaperServerListPingEvent and use results -+ event = PaperLegacyStatusClient.processRequest(minecraftserver, inetsocketaddress, 127, null); // Paper -+ if (event == null) { -+ channelhandlercontext.close(); -+ break; -+ } -+ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit -+ // Paper end - this.a(channelhandlercontext, this.a(s)); - break; - default: -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); - -- String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -- Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port); -+ com.destroystokyo.paper.event.server.PaperServerListPingEvent event = PaperLegacyStatusClient.processRequest( -+ server, (InetSocketAddress) ctx.channel().remoteAddress(), protocolVersion, virtualHost); -+ if (event == null) { -+ ctx.close(); -+ return; -+ } -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", event.getProtocolVersion(), event.getVersion(), -+ PaperLegacyStatusClient.getMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.a(ctx, this.a(response)); - } - diff --git a/Spigot-Server-Patches/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/Spigot-Server-Patches/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch deleted file mode 100644 index c4e0343e14..0000000000 --- a/Spigot-Server-Patches/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 13 Mar 2019 20:08:09 +0200 -Subject: [PATCH] Call WhitelistToggleEvent when whitelist is toggled - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void setHasWhitelist(boolean flag) { -+ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(flag).callEvent(); - this.hasWhitelist = flag; - } - diff --git a/Spigot-Server-Patches/Call-player-spectator-target-events-and-improve-impl.patch b/Spigot-Server-Patches/Call-player-spectator-target-events-and-improve-impl.patch deleted file mode 100644 index 999c80995b..0000000000 --- a/Spigot-Server-Patches/Call-player-spectator-target-events-and-improve-impl.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Caleb Bassham -Date: Fri, 28 Sep 2018 02:32:19 -0500 -Subject: [PATCH] Call player spectator target events and improve - implementation - -Use a proper teleport for teleporting to entities in different -worlds. - -Implementation improvements authored by Spottedleaf -Validate that the target entity is valid and deny spectate -requests from frozen players. - -Also, make sure the entity is spawned to the client before -sending the camera packet. If the entity isn't spawned clientside -when it receives the camera packet, then the client will not -spectate the target entity. - -Co-authored-by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return (Entity) (this.spectatedEntity == null ? this : this.spectatedEntity); - } - -- public void setSpectatorTarget(Entity entity) { -+ public void setSpectatorTarget(Entity newSpectatorTarget) { -+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation - Entity entity1 = this.getSpecatorTarget(); - -- this.spectatedEntity = (Entity) (entity == null ? this : entity); -- if (entity1 != this.spectatedEntity) { -- this.playerConnection.sendPacket(new PacketPlayOutCamera(this.spectatedEntity)); -- this.playerConnection.a(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit -+ if (newSpectatorTarget == null) { -+ newSpectatorTarget = this; - } - -+ if (entity1 == newSpectatorTarget) return; // new spec target is the current spec target -+ -+ if (newSpectatorTarget == this) { -+ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity()); -+ -+ if (!playerStopSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } else { -+ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), newSpectatorTarget.getBukkitEntity()); -+ -+ if (!playerStartSpectatingEntityEvent.callEvent()) { -+ return; -+ } -+ } -+ // Validate -+ if (newSpectatorTarget != this) { -+ if (newSpectatorTarget.dead || newSpectatorTarget.shouldBeRemoved || !newSpectatorTarget.valid || newSpectatorTarget.world == null) { -+ MinecraftServer.LOGGER.info("Blocking player " + this.toString() + " from spectating invalid entity " + newSpectatorTarget.toString()); -+ return; -+ } -+ if (this.isFrozen()) { -+ // use debug: clients might maliciously spam this -+ MinecraftServer.LOGGER.debug("Blocking frozen player " + this.toString() + " from spectating entity " + newSpectatorTarget.toString()); -+ return; -+ } -+ } -+ -+ this.spectatedEntity = newSpectatorTarget; // only set after validating state -+ -+ if (newSpectatorTarget != this) { -+ // Make sure we're in the right place -+ this.ejectPassengers(); // teleport can fail if we have passengers... -+ this.getBukkitEntity().teleport(new Location(newSpectatorTarget.getWorld().getWorld(), newSpectatorTarget.locX(), newSpectatorTarget.locY(), newSpectatorTarget.locZ(), this.yaw, this.pitch), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport -+ -+ // Make sure we're tracking the entity before sending -+ PlayerChunkMap.EntityTracker tracker = ((WorldServer)newSpectatorTarget.world).getChunkProvider().playerChunkMap.trackedEntities.get(newSpectatorTarget.getId()); -+ if (tracker != null) { // dumb plugins... -+ tracker.updatePlayer(this); -+ } -+ } else { -+ this.playerConnection.teleport(this.spectatedEntity.locX(), this.spectatedEntity.locY(), this.spectatedEntity.locZ(), this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit -+ } -+ this.playerConnection.sendPacket(new PacketPlayOutCamera(newSpectatorTarget)); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - // CraftBukkit start - Delegate to teleport(Location) -+ public final void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { this.a(d0, d1, d2, f, f1, cause); } // Paper - OBFHELPER - public void a(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { - this.a(d0, d1, d2, f, f1, Collections.emptySet(), cause); - } diff --git a/Spigot-Server-Patches/Cap-Entity-Collisions.patch b/Spigot-Server-Patches/Cap-Entity-Collisions.patch deleted file mode 100644 index 923d549fb2..0000000000 --- a/Spigot-Server-Patches/Cap-Entity-Collisions.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 22 Jan 2017 18:07:56 -0500 -Subject: [PATCH] Cap Entity Collisions - -Limit a single entity to colliding a max of configurable times per tick. -This will alleviate issues where living entities are hoarded in 1x1 pens - -This is not tied to the maxEntityCramming rule. Cramming will still apply -just as it does in Vanilla, but entity pushing logic will be capped. - -You can set this to 0 to disable collisions. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - log("Treasure Maps will return already discovered locations"); - } - } -+ -+ public int maxCollisionsPerEntity; -+ private void maxEntityCollision() { -+ maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -+ log( "Max Entity Collisions: " + maxCollisionsPerEntity ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - } - -- for (j = 0; j < list.size(); ++j) { -+ numCollisions = Math.max(0, numCollisions - world.paperConfig.maxCollisionsPerEntity); // Paper -+ for (j = 0; j < list.size() && numCollisions < world.paperConfig.maxCollisionsPerEntity; ++j) { // Paper - Entity entity = (Entity) list.get(j); -+ entity.numCollisions++; // Paper -+ numCollisions++; // Paper - - this.C(entity); - } diff --git a/Spigot-Server-Patches/Catch-JsonParseException-in-Entity-and-TE-names.patch b/Spigot-Server-Patches/Catch-JsonParseException-in-Entity-and-TE-names.patch deleted file mode 100644 index 33fd6333d7..0000000000 --- a/Spigot-Server-Patches/Catch-JsonParseException-in-Entity-and-TE-names.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sat, 22 Sep 2018 15:56:59 -0400 -Subject: [PATCH] Catch JsonParseException in Entity and TE names - -As a result, data that no longer parses correctly will not crash the server -instead just logging the exception and continuing (and in most cases should -fix the data) - -Player data is fixed pretty much immediately but some block data (like -Shulkers) may need to be changed in order for it to re-save properly - -No more crashing though. - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -0,0 +0,0 @@ public final class MCUtil { - return null; - } - } -+ -+ @Nullable -+ public static IChatBaseComponent getBaseComponentFromNbt(String key, NBTTagCompound compound) { -+ if (!compound.hasKey(key)) { -+ return null; -+ } -+ String string = compound.getString(key); -+ try { -+ return IChatBaseComponent.ChatSerializer.jsonToComponent(string); -+ } catch (com.google.gson.JsonParseException e) { -+ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); -+ } -+ -+ return null; -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/CommandBlockListenerAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.commands.ICommandListener; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.UtilColor; -@@ -0,0 +0,0 @@ public abstract class CommandBlockListenerAbstract implements ICommandListener { - this.command = nbttagcompound.getString("Command"); - this.successCount = nbttagcompound.getInt("SuccessCount"); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.setName(IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName"))); -+ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound)); // Paper - Catch ParseException - } - - if (nbttagcompound.hasKeyOfType("TrackOutput", 1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBanner.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.ItemStack; -@@ -0,0 +0,0 @@ public class TileEntityBanner extends TileEntity implements INamableTileEntity { - public void load(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - super.load(iblockdata, nbttagcompound); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.a = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); -+ this.a = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException - } - - if (this.hasWorld()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityContainer.java -@@ -0,0 +0,0 @@ import javax.annotation.Nullable; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.ChestLock; -@@ -0,0 +0,0 @@ public abstract class TileEntityContainer extends TileEntity implements IInvento - super.load(iblockdata, nbttagcompound); - this.chestLock = ChestLock.b(nbttagcompound); - if (nbttagcompound.hasKeyOfType("CustomName", 8)) { -- this.customName = IChatBaseComponent.ChatSerializer.a(nbttagcompound.getString("CustomName")); -+ this.customName = MCUtil.getBaseComponentFromNbt("CustomName", nbttagcompound); // Paper - Catch ParseException - } - - } diff --git a/Spigot-Server-Patches/Catch-exceptions-from-dispenser-entity-spawns.patch b/Spigot-Server-Patches/Catch-exceptions-from-dispenser-entity-spawns.patch deleted file mode 100644 index dee3ad4e06..0000000000 --- a/Spigot-Server-Patches/Catch-exceptions-from-dispenser-entity-spawns.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 10 Jun 2019 09:36:40 +0100 -Subject: [PATCH] Catch exceptions from dispenser entity spawns - - -diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.ISourceBlock; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -0,0 +0,0 @@ public interface IDispenseBehavior { - } - } - -+ try { // Paper - entitytypes.spawnCreature(isourceblock.getWorld(), itemstack, (EntityHuman) null, isourceblock.getBlockPosition().shift(enumdirection), EnumMobSpawn.DISPENSER, enumdirection != EnumDirection.UP, false); -+ // Paper start -+ } catch (Exception ex){ -+ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), isourceblock.getBlockPosition(), ex); -+ } -+ // Paper end -+ - // itemstack.subtract(1); // Handled during event processing - // CraftBukkit end - return itemstack; diff --git a/Spigot-Server-Patches/Change-implementation-of-tile-entity-removal-list.patch b/Spigot-Server-Patches/Change-implementation-of-tile-entity-removal-list.patch deleted file mode 100644 index 6beb221b0a..0000000000 --- a/Spigot-Server-Patches/Change-implementation-of-tile-entity-removal-list.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:39:54 -0600 -Subject: [PATCH] Change implementation of (tile)entity removal list - -use sets for faster removal - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public final List tileEntityList = Lists.newArrayList(); - public final List tileEntityListTick = Lists.newArrayList(); - protected final List tileEntityListPending = Lists.newArrayList(); -- protected final List tileEntityListUnload = Lists.newArrayList(); -+ protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); - public final Thread serverThread; - private final boolean debugWorld; - private int d; diff --git a/Spigot-Server-Patches/Check-Drowned-for-Villager-Aggression-Config.patch b/Spigot-Server-Patches/Check-Drowned-for-Villager-Aggression-Config.patch deleted file mode 100644 index aba90b0b18..0000000000 --- a/Spigot-Server-Patches/Check-Drowned-for-Villager-Aggression-Config.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Wed, 10 Oct 2018 21:22:44 -0500 -Subject: [PATCH] Check Drowned for Villager Aggression Config - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityDrowned.java -@@ -0,0 +0,0 @@ public class EntityDrowned extends EntityZombie implements IRangedEntity { - this.goalSelector.a(7, new PathfinderGoalRandomStroll(this, 1.0D)); - this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityDrowned.class})).a(EntityPigZombie.class)); - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::i)); -- this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); -+ if ( world.spigotConfig.zombieAggressiveTowardsVillager ) this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false)); // Paper - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); - this.targetSelector.a(5, new PathfinderGoalNearestAttackableTarget<>(this, EntityTurtle.class, 10, true, false, EntityTurtle.bo)); - } diff --git a/Spigot-Server-Patches/Check-online-mode-before-converting-and-renaming-pla.patch b/Spigot-Server-Patches/Check-online-mode-before-converting-and-renaming-pla.patch deleted file mode 100644 index 0324b67f96..0000000000 --- a/Spigot-Server-Patches/Check-online-mode-before-converting-and-renaming-pla.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Wed, 2 Mar 2016 00:03:55 -0600 -Subject: [PATCH] Check online mode before converting and renaming player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -@@ -0,0 +0,0 @@ public class WorldNBTStorage { - File file = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat"); - // Spigot Start - boolean usingWrongFile = false; -- if ( !file.exists() ) -+ if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first - { - file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); - if ( file.exists() ) diff --git a/Spigot-Server-Patches/Chunk-Save-Reattempt.patch b/Spigot-Server-Patches/Chunk-Save-Reattempt.patch deleted file mode 100644 index fd72511ff3..0000000000 --- a/Spigot-Server-Patches/Chunk-Save-Reattempt.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 Mar 2013 23:46:10 -0500 -Subject: [PATCH] Chunk Save Reattempt - -We commonly have "Stream Closed" errors on chunk saving, so this code should re-try to save the chunk in the event of failure and hopefully prevent rollbacks. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - return true; - } - } catch (IOException ioexception) { -- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioexception); // Paper - we want the upper try/catch to retry this - return false; - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -0,0 +0,0 @@ import java.io.IOException; - import javax.annotation.Nullable; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; - -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - - protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { - RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit -+ int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper - DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); - Throwable throwable = null; - -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - - } - -+ // Paper start -+ return; -+ } catch (Exception ex) { -+ laste = ex; -+ } -+ } -+ -+ if (laste != null) { -+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(laste); -+ MinecraftServer.LOGGER.error("Failed to save chunk", laste); -+ } -+ // Paper end - } - - public void close() throws IOException { diff --git a/Spigot-Server-Patches/Chunk-debug-command.patch b/Spigot-Server-Patches/Chunk-debug-command.patch deleted file mode 100644 index cfe98045b6..0000000000 --- a/Spigot-Server-Patches/Chunk-debug-command.patch +++ /dev/null @@ -1,486 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 1 Jun 2019 13:00:55 -0700 -Subject: [PATCH] Chunk debug command - -Prints all chunk information to a text file into the debug -folder in the root server folder. The format is in JSON, and -the data format is described in MCUtil#dumpChunks(File) - -The command will output server version and all online players to the -file as well. We do not log anything but the location, world and -username of the player. - -Also logs the value of these config values (note not all are paper's): -- keep spawn loaded value -- spawn radius -- view distance - -Each chunk has the following logged: -- Coordinate -- Ticket level & its corresponding state -- Whether it is queued for unload -- Chunk status (may be unloaded) -- All tickets on the chunk - -Example log: -https://gist.githubusercontent.com/Spottedleaf/0131e7710ffd5d531e5fd246c3367380/raw/169ae1b2e240485f99bc7a6bd8e78d90e3af7397/chunks-2019-06-01_19.57.05.txt - -For references on certain keywords (ticket, status, etc), please see: - -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528273&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528273 -https://bugs.mojang.com/browse/MC-141484?focusedCommentId=528577&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-528577 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ import com.google.common.collect.Maps; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.server.MCUtil; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -0,0 +0,0 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - if (args.length == 3) - return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); - break; -+ case "debug": -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, "help", "chunks"); -+ } -+ break; -+ case "chunkinfo": -+ List worldNames = new ArrayList<>(); -+ worldNames.add("*"); -+ for (org.bukkit.World world : Bukkit.getWorlds()) { -+ worldNames.add(world.getName()); -+ } -+ if (args.length == 2) { -+ return getListMatchingLast(sender, args, worldNames); -+ } -+ break; - } - return Collections.emptyList(); - } -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "debug": -+ doDebug(sender, args); -+ break; -+ case "chunkinfo": -+ doChunkInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doChunkInfo(CommandSender sender, String[] args) { -+ List worlds; -+ if (args.length < 2 || args[1].equals("*")) { -+ worlds = Bukkit.getWorlds(); -+ } else { -+ worlds = new ArrayList<>(args.length - 1); -+ for (int i = 1; i < args.length; ++i) { -+ org.bukkit.World world = Bukkit.getWorld(args[i]); -+ if (world == null) { -+ sender.sendMessage(ChatColor.RED + "World '" + args[i] + "' is invalid"); -+ return; -+ } -+ worlds.add(world); -+ } -+ } -+ -+ int accumulatedTotal = 0; -+ int accumulatedInactive = 0; -+ int accumulatedBorder = 0; -+ int accumulatedTicking = 0; -+ int accumulatedEntityTicking = 0; -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ WorldServer world = ((CraftWorld)bukkitWorld).getHandle(); -+ -+ int total = 0; -+ int inactive = 0; -+ int border = 0; -+ int ticking = 0; -+ int entityTicking = 0; -+ -+ for (PlayerChunk chunk : world.getChunkProvider().playerChunkMap.updatingChunks.values()) { -+ if (chunk.getFullChunkIfCached() == null) { -+ continue; -+ } -+ -+ ++total; -+ -+ PlayerChunk.State state = PlayerChunk.getChunkState(chunk.getTicketLevel()); -+ -+ switch (state) { -+ case INACCESSIBLE: -+ ++inactive; -+ continue; -+ case BORDER: -+ ++border; -+ continue; -+ case TICKING: -+ ++ticking; -+ continue; -+ case ENTITY_TICKING: -+ ++entityTicking; -+ continue; -+ } -+ } -+ -+ accumulatedTotal += total; -+ accumulatedInactive += inactive; -+ accumulatedBorder += border; -+ accumulatedTicking += ticking; -+ accumulatedEntityTicking += entityTicking; -+ -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + bukkitWorld.getName() + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + total + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + inactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + border + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + ticking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + entityTicking); -+ } -+ if (worlds.size() > 1) { -+ sender.sendMessage(ChatColor.BLUE + "Chunks in " + ChatColor.GREEN + "all listed worlds" + ChatColor.DARK_AQUA + ":"); -+ sender.sendMessage(ChatColor.BLUE + "Total: " + ChatColor.DARK_AQUA + accumulatedTotal + ChatColor.BLUE + " Inactive: " + ChatColor.DARK_AQUA -+ + accumulatedInactive + ChatColor.BLUE + " Border: " + ChatColor.DARK_AQUA + accumulatedBorder + ChatColor.BLUE + " Ticking: " -+ + ChatColor.DARK_AQUA + accumulatedTicking + ChatColor.BLUE + " Entity: " + ChatColor.DARK_AQUA + accumulatedEntityTicking); -+ } -+ } -+ -+ private void doDebug(CommandSender sender, String[] args) { -+ if (args.length < 2) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ -+ String debugType = args[1].toLowerCase(Locale.ENGLISH); -+ switch (debugType) { -+ case "chunks": -+ if (args.length >= 3 && args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper debug chunks to dump loaded chunk information to a file"); -+ break; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "chunks-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ sender.sendMessage(ChatColor.GREEN + "Writing chunk information dump to " + file.toString()); -+ try { -+ MCUtil.dumpChunks(file); -+ sender.sendMessage(ChatColor.GREEN + "Successfully written chunk information!"); -+ } catch (Throwable thr) { -+ MinecraftServer.LOGGER.warn("Failed to dump chunk information to file " + file.toString(), thr); -+ sender.sendMessage(ChatColor.RED + "Failed to dump chunk information, see console"); -+ } -+ -+ break; -+ case "help": -+ // fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Use /paper debug [chunks] help for more information on a specific command"); -+ return; -+ } -+ } -+ - /* - * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 - */ -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.level.ChunkMapDistance; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.Ticket; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.level.World; -+import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.IChunkAccess; - import org.apache.commons.lang.exception.ExceptionUtils; -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; - import com.mojang.authlib.GameProfile; -+import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import org.bukkit.Location; - import org.bukkit.block.BlockFace; - import org.bukkit.craftbukkit.CraftWorld; -@@ -0,0 +0,0 @@ import org.spigotmc.AsyncCatcher; - - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import java.io.*; -+import java.util.ArrayList; - import java.util.List; - import java.util.Queue; -+import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.ExecutionException; - import java.util.concurrent.LinkedBlockingQueue; -@@ -0,0 +0,0 @@ public final class MCUtil { - - return null; - } -+ -+ public static ChunkStatus getChunkStatus(PlayerChunk chunk) { -+ List statuses = ChunkProviderServer.getPossibleChunkStatuses(); -+ for (int i = statuses.size() - 1; i >= 0; --i) { -+ ChunkStatus curr = statuses.get(i); -+ CompletableFuture> future = chunk.getStatusFutureUnchecked(curr); -+ if (future != PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE) { -+ return curr; -+ } -+ } -+ return null; // unloaded -+ } -+ -+ public static void dumpChunks(File file) throws IOException { -+ file.getParentFile().mkdirs(); -+ file.createNewFile(); -+ /* -+ * Json format: -+ * -+ * Main data format: -+ * -server-version: -+ * -data-version: -+ * -worlds: -+ * -name: -+ * -view-distance: -+ * -keep-spawn-loaded: -+ * -keep-spawn-loaded-range: -+ * -visible-chunk-count: -+ * -loaded-chunk-count: -+ * -verified-fully-loaded-chunks: -+ * -players: -+ * -chunk-data: -+ * -+ * Player format: -+ * -name: -+ * -x: -+ * -y: -+ * -z: -+ * -+ * Chunk Format: -+ * -x: -+ * -z: -+ * -ticket-level: -+ * -state: -+ * -queued-for-unload: -+ * -status: -+ * -tickets: -+ * -+ * -+ * Ticket format: -+ * -ticket-type: -+ * -ticket-level: -+ * -add-tick: -+ * -object-reason: // This depends on the type of ticket. ie POST_TELEPORT -> entity id -+ */ -+ List worlds = org.bukkit.Bukkit.getWorlds(); -+ JsonObject data = new JsonObject(); -+ -+ data.addProperty("server-version", org.bukkit.Bukkit.getVersion()); -+ data.addProperty("data-version", 0); -+ -+ JsonArray worldsData = new JsonArray(); -+ -+ for (org.bukkit.World bukkitWorld : worlds) { -+ JsonObject worldData = new JsonObject(); -+ -+ WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); -+ PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; -+ ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; -+ List allChunks = new ArrayList<>(visibleChunks.values()); -+ List players = world.players; -+ -+ int fullLoadedChunks = 0; -+ -+ for (PlayerChunk chunk : allChunks) { -+ if (chunk.getFullChunkIfCached() != null) { -+ ++fullLoadedChunks; -+ } -+ } -+ -+ // sorting by coordinate makes the log easier to read -+ allChunks.sort((PlayerChunk v1, PlayerChunk v2) -> { -+ if (v1.location.x != v2.location.x) { -+ return Integer.compare(v1.location.x, v2.location.x); -+ } -+ return Integer.compare(v1.location.z, v2.location.z); -+ }); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); -+ worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); -+ worldData.addProperty("visible-chunk-count", visibleChunks.size()); -+ worldData.addProperty("loaded-chunk-count", chunkMap.loadedChunks.size()); -+ worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); -+ -+ JsonArray playersData = new JsonArray(); -+ -+ for (EntityPlayer player : players) { -+ JsonObject playerData = new JsonObject(); -+ -+ playerData.addProperty("name", player.getName()); -+ playerData.addProperty("x", player.locX()); -+ playerData.addProperty("y", player.locY()); -+ playerData.addProperty("z", player.locZ()); -+ -+ playersData.add(playerData); -+ -+ } -+ -+ worldData.add("players", playersData); -+ -+ JsonArray chunksData = new JsonArray(); -+ -+ for (PlayerChunk playerChunk : allChunks) { -+ JsonObject chunkData = new JsonObject(); -+ -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.location.pair()); -+ ChunkStatus status = getChunkStatus(playerChunk); -+ -+ chunkData.addProperty("x", playerChunk.location.x); -+ chunkData.addProperty("z", playerChunk.location.z); -+ chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); -+ chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); -+ chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); -+ -+ JsonArray ticketsData = new JsonArray(); -+ -+ if (tickets != null) { -+ for (Ticket ticket : tickets) { -+ JsonObject ticketData = new JsonObject(); -+ -+ ticketData.addProperty("ticket-type", ticket.getTicketType().toString()); -+ ticketData.addProperty("ticket-level", ticket.getTicketLevel()); -+ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); -+ ticketData.addProperty("add-tick", ticket.getCreationTick()); -+ -+ ticketsData.add(ticketData); -+ } -+ } -+ -+ chunkData.add("tickets", ticketsData); -+ chunksData.add(chunkData); -+ } -+ -+ -+ worldData.add("chunk-data", chunksData); -+ worldsData.add(worldData); -+ } -+ -+ data.add("worlds", worldsData); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { -+ out.print(fileData); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - - public class ChunkProviderServer extends IChunkProvider { - -- private static final List b = ChunkStatus.a(); -+ private static final List b = ChunkStatus.a(); public static final List getPossibleChunkStatuses() { return ChunkProviderServer.b; } // Paper - OBFHELPER - private final ChunkMapDistance chunkMapDistance; - public final ChunkGenerator chunkGenerator; - private final WorldServer world; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - public int oldTicketLevel; - private int ticketLevel; - private int n; -- private final ChunkCoordIntPair location; -+ final ChunkCoordIntPair location; // Paper - private -> package - private boolean p; - private final ShortSet[] dirtyBlocks; - private int r; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); - public volatile Long2ObjectLinkedOpenHashMap visibleChunks; - private final Long2ObjectLinkedOpenHashMap pendingUnload; -- private final LongSet loadedChunks; -+ public final LongSet loadedChunks; // Paper - private -> public - public final WorldServer world; - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -0,0 +0,0 @@ public final class Ticket implements Comparable> { - - private final TicketType a; - private final int b; -- public final T identifier; -- private long d; -+ public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER -+ private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; -@@ -0,0 +0,0 @@ public final class Ticket implements Comparable> { - return this.a; - } - -+ public final int getTicketLevel() { return this.b(); } // Paper - OBFHELPER - public int b() { - return this.b; - } diff --git a/Spigot-Server-Patches/Chunk-registration-fixes.patch b/Spigot-Server-Patches/Chunk-registration-fixes.patch deleted file mode 100644 index 283f012baa..0000000000 --- a/Spigot-Server-Patches/Chunk-registration-fixes.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Sep 2016 22:54:28 -0400 -Subject: [PATCH] Chunk registration fixes - -World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated - -Keep them consistent - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity.cl()) { - this.getMethodProfiler().enter("chunkCheck"); - int i = MathHelper.floor(entity.locX() / 16.0D); -- int j = MathHelper.floor(entity.locY() / 16.0D); -+ int j = Math.min(15, Math.max(0, MathHelper.floor(entity.locY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior - int k = MathHelper.floor(entity.locZ() / 16.0D); - - if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { diff --git a/Spigot-Server-Patches/ChunkMapDistance-CME.patch b/Spigot-Server-Patches/ChunkMapDistance-CME.patch deleted file mode 100644 index 84c520675f..0000000000 --- a/Spigot-Server-Patches/ChunkMapDistance-CME.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 29 May 2019 04:01:22 +0100 -Subject: [PATCH] ChunkMapDistance CME - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); - private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); - private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); -- private final Set pendingChunkUpdates = Sets.newHashSet(); -+ // Paper start use a queue, but still keep unique requirement -+ public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -+ @Override -+ public boolean add(PlayerChunk o) { -+ if (o.isUpdateQueued) return true; -+ o.isUpdateQueued = true; -+ return super.add(o); -+ } -+ }; -+ // Paper end - private final ChunkTaskQueueSorter i; - private final Mailbox> j; - private final Mailbox k; -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - ; - } - -+ // Paper start - if (!this.pendingChunkUpdates.isEmpty()) { -- // CraftBukkit start -- // Iterate pending chunk updates with protection against concurrent modification exceptions -- java.util.Iterator iter = this.pendingChunkUpdates.iterator(); -- int expectedSize = this.pendingChunkUpdates.size(); -- do { -- PlayerChunk playerchunk = iter.next(); -- iter.remove(); -- expectedSize--; -- -- playerchunk.a(playerchunkmap); -- -- // Reset iterator if set was modified using add() -- if (this.pendingChunkUpdates.size() != expectedSize) { -- expectedSize = this.pendingChunkUpdates.size(); -- iter = this.pendingChunkUpdates.iterator(); -- } -- } while (iter.hasNext()); -- // CraftBukkit end -- -+ while(!this.pendingChunkUpdates.isEmpty()) { -+ PlayerChunk remove = this.pendingChunkUpdates.remove(); -+ remove.isUpdateQueued = false; -+ remove.a(playerchunkmap); -+ } -+ // Paper end - return true; - } else { - if (!this.l.isEmpty()) { -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); -+ Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - private static final CompletableFuture> UNLOADED_CHUNK_FUTURE = CompletableFuture.completedFuture(PlayerChunk.UNLOADED_CHUNK); - private static final List CHUNK_STATUSES = ChunkStatus.a(); - private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); -+ boolean isUpdateQueued = false; // Paper - private final AtomicReferenceArray>> statusFutures; - private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage - private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage diff --git a/Spigot-Server-Patches/Clean-up-duplicated-GameProfile-Properties.patch b/Spigot-Server-Patches/Clean-up-duplicated-GameProfile-Properties.patch deleted file mode 100644 index f5395c0446..0000000000 --- a/Spigot-Server-Patches/Clean-up-duplicated-GameProfile-Properties.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 03:12:06 -0400 -Subject: [PATCH] Clean up duplicated GameProfile Properties - -We had a bug where we accidently cloned properties resulting in skulls -growing to large sizes and preventing login. - -This now automatically cleans up the extra properties. - -diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -+++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -@@ -0,0 +0,0 @@ public final class GameProfileSerializer { - while (iterator.hasNext()) { - String s1 = (String) iterator.next(); - NBTTagList nbttaglist = nbttagcompound1.getList(s1, 10); -- -- for (int i = 0; i < nbttaglist.size(); ++i) { -+ if (nbttaglist.size() == 0) continue; // Paper - remove duplicate properties -+ for (int i = nbttaglist.size() - 1; i < nbttaglist.size(); ++i) { // Paper - remove duplicate properties - NBTTagCompound nbttagcompound2 = nbttaglist.getCompound(i); - String s2 = nbttagcompound2.getString("Value"); - -@@ -0,0 +0,0 @@ public final class GameProfileSerializer { - Optional optional = iblockstate.b(nbttagcompound.getString(s)); - - if (optional.isPresent()) { -- return (IBlockDataHolder) s0.set(iblockstate, (Comparable) optional.get()); -+ return s0.set(iblockstate, optional.get()); // Paper - decompile error - } else { - GameProfileSerializer.LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", s, nbttagcompound.getString(s), nbttagcompound1.toString()); - return s0; -@@ -0,0 +0,0 @@ public final class GameProfileSerializer { - return nbttagcompound; - } - -- private static > String a(IBlockState iblockstate, Comparable comparable) { -- return iblockstate.a(comparable); -+ private static > String a(IBlockState iblockstate, Comparable comparable) {// Paper - decompile error -+ return iblockstate.a((T) comparable);// Paper - decompile error - } - - public static NBTTagCompound a(DataFixer datafixer, DataFixTypes datafixtypes, NBTTagCompound nbttagcompound, int i) { -diff --git a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -+++ b/src/main/java/net/minecraft/world/item/ItemSkullPlayer.java -@@ -0,0 +0,0 @@ public class ItemSkullPlayer extends ItemBlockWallable { - return true; - } else { - // CraftBukkit start -+ // Paper start - clean up old duplicated properties -+ NBTTagCompound properties = nbttagcompound.getCompound("SkullOwner").getCompound("Properties"); -+ for (String key : properties.getKeys()) { -+ net.minecraft.nbt.NBTTagList values = properties.getList(key, 10); -+ if (values.size() > 1) { -+ net.minecraft.nbt.NBTBase texture = values.get(values.size() - 1); -+ values = new net.minecraft.nbt.NBTTagList(); -+ values.add(texture); -+ properties.set(key, values); -+ } -+ } -+ // Paper end - net.minecraft.nbt.NBTTagList textures = nbttagcompound.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts - for (int i = 0; i < textures.size(); i++) { - if (textures.get(i) instanceof NBTTagCompound && !((NBTTagCompound) textures.get(i)).hasKeyOfType("Signature", 8) && ((NBTTagCompound) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/Spigot-Server-Patches/Clear-SyncLoadInfo.patch b/Spigot-Server-Patches/Clear-SyncLoadInfo.patch deleted file mode 100644 index 53556925c5..0000000000 --- a/Spigot-Server-Patches/Clear-SyncLoadInfo.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:10:53 -0600 -Subject: [PATCH] Clear SyncLoadInfo - -This patch merely adds the extra argument "clear" after /paper syncloadinfo to clear currently stored syncload info. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); - return; - } -+ -+ if (args.length > 1 && args[1].equals("clear")) { -+ SyncLoadFinder.clear(); -+ sender.sendMessage(ChatColor.GRAY + "Sync load data cleared."); -+ return; -+ } -+ - File file = new File(new File(new File("."), "debug"), - "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); - file.getParentFile().mkdirs(); -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -0,0 +0,0 @@ public class SyncLoadFinder { - public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); - } - -+ public static void clear() { -+ SYNC_LOADS.clear(); -+ } -+ - public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { - if (!ENABLED) { - return; diff --git a/Spigot-Server-Patches/Climbing-should-not-bypass-cramming-gamerule.patch b/Spigot-Server-Patches/Climbing-should-not-bypass-cramming-gamerule.patch deleted file mode 100644 index 42f1a3a483..0000000000 --- a/Spigot-Server-Patches/Climbing-should-not-bypass-cramming-gamerule.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 23 Aug 2020 20:59:00 +0200 -Subject: [PATCH] Climbing should not bypass cramming gamerule - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - wanderingTraderSpawnChanceMin = getInt("wandering-trader.spawn-chance-min", wanderingTraderSpawnChanceMin); - wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); - } -+ -+ public boolean fixClimbingBypassingCrammingRule = false; -+ private void fixClimbingBypassingCrammingRule() { -+ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isCollidable() { -+ // Paper start -+ return isCollidable(false); -+ } -+ -+ public boolean isCollidable(boolean ignoreClimbing) { -+ // Paper end - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class EntityLiving extends Entity { - -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return; - } - // Paper - end don't run getEntities if we're not going to use its result -- List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); -+ List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.pushable(this, world.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule - - if (!list.isEmpty()) { - // Paper - move up -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return !this.dead && this.collides; // CraftBukkit - } - -+ // Paper start - @Override - public boolean isCollidable() { -- return this.isAlive() && !this.isSpectator() && !this.isClimbing() && this.collides; // CraftBukkit -+ return this.isCollidable(world.paperConfig.fixClimbingBypassingCrammingRule); -+ } -+ -+ @Override -+ public boolean isCollidable(boolean ignoreClimbing) { -+ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.isClimbing()) && this.collides; // CraftBukkit -+ // Paper end - } - - // CraftBukkit start - collidable API -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -0,0 +0,0 @@ public final class IEntitySelector { - } - - public static Predicate a(Entity entity) { -+ // Paper start - ignoreClimbing param -+ return pushable(entity, false); -+ } -+ -+ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { -+ // Paper end - ScoreboardTeamBase scoreboardteambase = entity.getScoreboardTeam(); - ScoreboardTeamBase.EnumTeamPush scoreboardteambase_enumteampush = scoreboardteambase == null ? ScoreboardTeamBase.EnumTeamPush.ALWAYS : scoreboardteambase.getCollisionRule(); - - return (Predicate) (scoreboardteambase_enumteampush == ScoreboardTeamBase.EnumTeamPush.NEVER ? Predicates.alwaysFalse() : IEntitySelector.g.and((entity1) -> { -- if (!entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API -+ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWith(entity) || !entity.canCollideWith(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable - return false; - } else if (entity.world.isClientSide && (!(entity1 instanceof EntityHuman) || !((EntityHuman) entity1).ez())) { - return false; -diff --git a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -+++ b/src/main/java/net/minecraft/world/entity/ambient/EntityBat.java -@@ -0,0 +0,0 @@ public class EntityBat extends EntityAmbient { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityParrot.java -@@ -0,0 +0,0 @@ public class EntityParrot extends EntityPerchable implements EntityBird { - } - - @Override -- public boolean isCollidable() { -- return super.isCollidable(); // CraftBukkit - collidable API -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper -+ return super.isCollidable(ignoreClimbing); // CraftBukkit - collidable API // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return !this.isVehicle(); - } - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return false; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityMinecartAbstract extends Entity { - } - - @Override -- public boolean isCollidable() { -+ public boolean isCollidable(boolean ignoreClimbing) { // Paper - return true; - } - diff --git a/Spigot-Server-Patches/Collision-option-for-requiring-a-player-participant.patch b/Spigot-Server-Patches/Collision-option-for-requiring-a-player-participant.patch deleted file mode 100644 index 597b2b9b6e..0000000000 --- a/Spigot-Server-Patches/Collision-option-for-requiring-a-player-participant.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sat, 14 Nov 2020 16:48:37 +0100 -Subject: [PATCH] Collision option for requiring a player participant - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - } - } - -+ public boolean onlyPlayersCollide = false; -+ public boolean allowVehicleCollisions = true; -+ private void onlyPlayersCollide() { -+ onlyPlayersCollide = getBoolean("only-players-collide", onlyPlayersCollide); -+ allowVehicleCollisions = getBoolean("allow-vehicle-collisions", allowVehicleCollisions); -+ if (onlyPlayersCollide && !allowVehicleCollisions) { -+ log("Collisions will only work if a player is one of the two entities colliding."); -+ } else if (onlyPlayersCollide) { -+ log("Collisions will only work if a player OR a vehicle is one of the two entities colliding."); -+ } -+ } -+ - public int wanderingTraderSpawnMinuteTicks = 1200; - public int wanderingTraderSpawnDayTicks = 24000; - public int wanderingTraderSpawnChanceFailureIncrement = 25; -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public void collide(Entity entity) { - if (!this.isSameVehicle(entity)) { - if (!entity.noclip && !this.noclip) { -+ if (this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer || this instanceof EntityPlayer)) return; // Paper - double d0 = entity.locX() - this.locX(); - double d1 = entity.locZ() - this.locZ(); - double d2 = MathHelper.a(d0, d1); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - - @Override - public void collide(Entity entity) { -+ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper - if (entity instanceof EntityBoat) { - if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.util.MathHelper; -@@ -0,0 +0,0 @@ public abstract class EntityMinecartAbstract extends Entity { - public void collide(Entity entity) { - if (!this.world.isClientSide) { - if (!entity.noclip && !this.noclip) { -+ if (!this.world.paperConfig.allowVehicleCollisions && this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer)) return; // Paper - if (!this.w(entity)) { - // CraftBukkit start - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); diff --git a/Spigot-Server-Patches/Complete-resource-pack-API.patch b/Spigot-Server-Patches/Complete-resource-pack-API.patch deleted file mode 100644 index 8b227d16b4..0000000000 --- a/Spigot-Server-Patches/Complete-resource-pack-API.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 4 Apr 2015 23:17:52 -0400 -Subject: [PATCH] Complete resource pack API - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - public void a(PacketPlayInResourcePackStatus packetplayinresourcepackstatus) { - PlayerConnectionUtils.ensureMainThread(packetplayinresourcepackstatus, this, this.player.getWorldServer()); -- this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()])); -+ // Paper start -+ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; -+ player.getBukkitEntity().setResourcePackStatus(packStatus); -+ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - private double health = 20; - private boolean scaledHealth = false; - private double healthScale = 20; -+ // Paper start -+ private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; -+ private String resourcePackHash; -+ // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { - super(server, entity); -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public boolean getAffectsSpawning() { - return this.getHandle().affectsSpawning; - } -+ -+ @Override -+ public void setResourcePack(String url, String hash) { -+ Validate.notNull(url, "Resource pack URL cannot be null"); -+ Validate.notNull(hash, "Hash cannot be null"); -+ this.getHandle().setResourcePack(url, hash); -+ } -+ -+ @Override -+ public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status getResourcePackStatus() { -+ return this.resourcePackStatus; -+ } -+ -+ @Override -+ public String getResourcePackHash() { -+ return this.resourcePackHash; -+ } -+ -+ @Override -+ public boolean hasResourcePack() { -+ return this.resourcePackStatus == org.bukkit.event.player.PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED; -+ } -+ -+ public void setResourcePackStatus(org.bukkit.event.player.PlayerResourcePackStatusEvent.Status status) { -+ this.resourcePackStatus = status; -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/Configurable-Alternative-LootPool-Luck-Formula.patch b/Spigot-Server-Patches/Configurable-Alternative-LootPool-Luck-Formula.patch deleted file mode 100644 index 3048e10002..0000000000 --- a/Spigot-Server-Patches/Configurable-Alternative-LootPool-Luck-Formula.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 00:30:32 -0400 -Subject: [PATCH] Configurable Alternative LootPool Luck Formula - -Rewrites the Vanilla luck application formula so that luck can be -applied to items that do not have any quality defined. - -See: https://luckformula.emc.gs for data and details ------------ - -The rough summary is: -My goal was that in a pool, when luck was applied, the pool -rebalances so the percentages for bigger items is -lowered and smaller items is boosted. - -Do this by boosting and then reducing the weight value, -so that larger numbers are penalized more than smaller numbers. -resulting in a larger reduction of entries for more common -items than the reduction on small weights, -giving smaller weights more of a chance - ------------ - -This work kind of obsoletes quality, but quality would be useful -for 2 items with same weight that you want luck to impact -in varying directions. - -Fishing still falls into that as the weights are closer, so luck -will invalidate junk more. - -This change will result in some major changes to fishing formulas. - ------------ - -I would love to see this change in Vanilla, so Mojang please pull :) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - SpigotConfig.save(); - } - } -+ -+ public static boolean useAlternativeLuckFormula = false; -+ private static void useAlternativeLuckFormula() { -+ useAlternativeLuckFormula = getBoolean("settings.use-alternative-luck-formula", false); -+ if (useAlternativeLuckFormula) { -+ Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -@@ -0,0 +0,0 @@ import org.apache.commons.lang3.ArrayUtils; - - public abstract class LootSelectorEntry extends LootEntryAbstract { - -- protected final int c; -- protected final int e; -+ protected final int c; public int getWeight() { return c; } // Paper - OBFHELPER -+ protected final int e; public int getQuality() { return e; } // Paper - OBFHELPER - protected final LootItemFunction[] f; - private final BiFunction g; - private final LootEntry h = new LootSelectorEntry.c() { -@@ -0,0 +0,0 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - - public abstract class c implements LootEntry { - -- protected c() {} -+ protected c() { -+ } - - @Override - public int a(float f) { -- return Math.max(MathHelper.d((float) LootSelectorEntry.this.c + (float) LootSelectorEntry.this.e * f), 0); -+ // Paper start - Offer an alternative loot formula to refactor how luck bonus applies -+ // SEE: https://luckformula.emc.gs for details and data -+ if (lastLuck != null && lastLuck == f) { -+ return lastWeight; -+ } -+ // This is vanilla -+ float qualityModifer = (float) getQuality() * f; -+ double baseWeight = (getWeight() + qualityModifer); -+ if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { -+ // Random boost to avoid losing precision in the final int cast on return -+ final int weightBoost = 100; -+ baseWeight *= weightBoost; -+ // If we have vanilla 1, bump that down to 0 so nothing is is impacted -+ // vanilla 3 = 300, 200 basis = impact 2% -+ // =($B2*(($B2-100)/100/100)) -+ double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); -+ // =($B$7/100) -+ float luckModifier = Math.min(100, f * 10) / 100; -+ // =B2 - (C2 *($B$7/100)) -+ baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); -+ } -+ lastLuck = f; -+ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); -+ return lastWeight; - } - } -+ private Float lastLuck = null; -+ private int lastWeight = 0; -+ // Paper end - } diff --git a/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch b/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch deleted file mode 100644 index 1db2b7b30d..0000000000 --- a/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 20 Dec 2016 15:26:27 -0500 -Subject: [PATCH] Configurable Cartographer Treasure Maps - -Allow configuring for cartographers to return the same map location - -Also allow turning off treasure maps all together as they can eat up Map ID's -which are limited in quantity. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); - } - } -+ -+ public boolean enableTreasureMaps = true; -+ public boolean treasureMapsAlreadyDiscovered = false; -+ private void treasureMapsAlreadyDiscovered() { -+ enableTreasureMaps = getBoolean("enable-treasure-maps", true); -+ treasureMapsAlreadyDiscovered = getBoolean("treasure-maps-return-already-discovered", false); -+ if (treasureMapsAlreadyDiscovered) { -+ log("Treasure Maps will return already discovered locations"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -0,0 +0,0 @@ public class VillagerTrades { - return null; - } else { - WorldServer worldserver = (WorldServer) entity.world; -- BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, true); -+ if (!worldserver.paperConfig.enableTreasureMaps) return null; // Paper -+ BlockPosition blockposition = worldserver.a(this.b, entity.getChunkCoordinates(), 100, !worldserver.paperConfig.treasureMapsAlreadyDiscovered); // Paper - - if (blockposition != null) { - ItemStack itemstack = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), (byte) 2, true, true); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -@@ -0,0 +0,0 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional - - if (vec3d != null) { - WorldServer worldserver = loottableinfo.getWorld(); -- BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, this.i); -+ // Paper start -+ if (!worldserver.paperConfig.enableTreasureMaps) { -+ /* -+ * NOTE: I fear users will just get a plain map as their "treasure" -+ * This is preferable to disrespecting the config. -+ */ -+ return itemstack; -+ } -+ // Paper end -+ BlockPosition blockposition = worldserver.a(this.e, new BlockPosition(vec3d), this.h, !worldserver.paperConfig.treasureMapsAlreadyDiscovered && this.i); // Paper - - if (blockposition != null) { - ItemStack itemstack1 = ItemWorldMap.createFilledMapView(worldserver, blockposition.getX(), blockposition.getZ(), this.g, true, true); diff --git a/Spigot-Server-Patches/Configurable-Chunk-Inhabited-Time.patch b/Spigot-Server-Patches/Configurable-Chunk-Inhabited-Time.patch deleted file mode 100644 index 3c0704a53d..0000000000 --- a/Spigot-Server-Patches/Configurable-Chunk-Inhabited-Time.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:46:14 -0400 -Subject: [PATCH] Configurable Chunk Inhabited Time - -Vanilla stores how long a chunk has been active on a server, and dynamically scales some -aspects of vanilla gameplay to this factor. - -For people who want all chunks to be treated equally, you can chose a fixed value. - -This allows to fine-tune vanilla gameplay. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - skeleHorseSpawnChance = 0.01D; // Vanilla value - } - } -+ -+ public int fixedInhabitedTime; -+ private void fixedInhabitedTime() { -+ if (PaperConfig.version < 16) { -+ if (!config.getBoolean("world-settings.default.use-chunk-inhabited-timer", true)) config.set("world-settings.default.fixed-chunk-inhabited-time", 0); -+ if (!config.getBoolean("world-settings." + worldName + ".use-chunk-inhabited-timer", true)) config.set("world-settings." + worldName + ".fixed-chunk-inhabited-time", 0); -+ set("use-chunk-inhabited-timer", null); -+ } -+ fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - @Override - public long getInhabitedTime() { -- return this.inhabitedTime; -+ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper - } - - @Override diff --git a/Spigot-Server-Patches/Configurable-Disabling-Cat-Chest-Detection.patch b/Spigot-Server-Patches/Configurable-Disabling-Cat-Chest-Detection.patch deleted file mode 100644 index 28bf04eaad..0000000000 --- a/Spigot-Server-Patches/Configurable-Disabling-Cat-Chest-Detection.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:13:45 -0600 -Subject: [PATCH] Configurable Disabling Cat Chest Detection - -Offers a gameplay feature to stop cats from blocking chests - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void containerUpdateTickRate() { - containerUpdateTickRate = getInt("container-update-tick-rate", 1); - } -+ -+ public boolean disableChestCatDetection; -+ private void disableChestCatDetection() { -+ disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -0,0 +0,0 @@ public class BlockChest extends BlockChestAbstract implements I - } - - private static boolean b(GeneratorAccess generatoraccess, BlockPosition blockposition) { -+ // Paper start - Option to disable chest cat detection -+ if (((World) generatoraccess).paperConfig.disableChestCatDetection) { -+ return false; -+ } -+ // Paper end - List list = generatoraccess.a(EntityCat.class, new AxisAlignedBB((double) blockposition.getX(), (double) (blockposition.getY() + 1), (double) blockposition.getZ(), (double) (blockposition.getX() + 1), (double) (blockposition.getY() + 2), (double) (blockposition.getZ() + 1))); - - if (!list.isEmpty()) { diff --git a/Spigot-Server-Patches/Configurable-Grass-Spread-Tick-Rate.patch b/Spigot-Server-Patches/Configurable-Grass-Spread-Tick-Rate.patch deleted file mode 100644 index 25c227684c..0000000000 --- a/Spigot-Server-Patches/Configurable-Grass-Spread-Tick-Rate.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 16:28:17 -0400 -Subject: [PATCH] Configurable Grass Spread Tick Rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - } - fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); - } -+ -+ public int grassUpdateRate = 1; -+ private void grassUpdateRate() { -+ grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); -+ log("Grass Spread Tick Rate: " + grassUpdateRate); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDirtSnowSpreadable.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.block; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsFluid; -@@ -0,0 +0,0 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow { - - @Override - public void tick(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { -+ if (this instanceof BlockGrass && worldserver.paperConfig.grassUpdateRate != 1 && (worldserver.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + blockposition.hashCode()) % worldserver.paperConfig.grassUpdateRate != 0)) { return; } // Paper - if (!b(iblockdata, (IWorldReader) worldserver, blockposition)) { - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.DIRT.getBlockData()).isCancelled()) { diff --git a/Spigot-Server-Patches/Configurable-Keep-Spawn-Loaded-range-per-world.patch b/Spigot-Server-Patches/Configurable-Keep-Spawn-Loaded-range-per-world.patch deleted file mode 100644 index 7bb6222793..0000000000 --- a/Spigot-Server-Patches/Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ /dev/null @@ -1,261 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 13 Sep 2014 23:14:43 -0400 -Subject: [PATCH] Configurable Keep Spawn Loaded range per world - -This lets you disable it for some worlds and lower it for others. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - break; - } - } -+ -+ public short keepLoadedRange; -+ private void keepLoadedRange() { -+ keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); -+ log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant> 4).forEach(pair -> { -+ getChunkProvider().getChunkAtMainThread(pair.x, pair.z); -+ }); -+ } -+ public void removeTicketsForSpawn(int radiusInBlocks, BlockPosition spawn) { -+ // In order to respect vanilla behavior, which is ensuring everything but the spawn border can tick, we added tickets -+ // with level 31 for the non-border spawn chunks -+ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); -+ int tickRadius = radiusInBlocks - 16; -+ -+ // remove ticking chunks -+ for (int x = -tickRadius; x <= tickRadius; x += 16) { -+ for (int z = -tickRadius; z <= tickRadius; z += 16) { -+ // radius of 2 will have the current chunk be level 31 -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, z)), 2, Unit.INSTANCE); -+ } -+ } -+ -+ // remove border chunks -+ -+ // remove border along x axis (including corner chunks) -+ for (int x = -radiusInBlocks; x <= radiusInBlocks; x += 16) { -+ // top -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ // bottom -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(x, 0, -radiusInBlocks)), 1, Unit.INSTANCE); // level 32 -+ } -+ -+ // remove border along z axis (excluding corner chunks) -+ for (int z = -radiusInBlocks + 16; z < radiusInBlocks; z += 16) { -+ // right -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ // left -+ chunkproviderserver.removeTicket(TicketType.START, new ChunkCoordIntPair(spawn.add(-radiusInBlocks, 0, z)), 1, Unit.INSTANCE); // level 32 -+ } -+ } -+ // Paper end -+ - public void a(BlockPosition blockposition, float f) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); -+ // Paper - configurable spawn radius -+ BlockPosition prevSpawn = this.getSpawn(); -+ //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.worldData.setSpawn(blockposition, f); -- this.getChunkProvider().removeTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); -- this.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(blockposition), 11, Unit.INSTANCE); -+ if (this.keepSpawnInMemory) { -+ // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add -+ this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -+ this.addTicketsForSpawn(this.paperConfig.keepLoadedRange, blockposition); -+ } - this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); - } - -diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -+++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java -@@ -0,0 +0,0 @@ public interface WorldLoadListener { - void a(ChunkCoordIntPair chunkcoordintpair, @Nullable ChunkStatus chunkstatus); - - void b(); -+ -+ void setChunkRadius(int radius); // Paper - allow changing chunk radius - } -diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -+++ b/src/main/java/net/minecraft/server/level/progress/WorldLoadListenerLogger.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - public class WorldLoadListenerLogger implements WorldLoadListener { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final int b; -+ private int b; // Paper - remove final - private int c; - private long d; - private long e = Long.MAX_VALUE; - - public WorldLoadListenerLogger(int i) { -- int j = i * 2 + 1; -+ // Paper start - Allow changing radius later for configurable spawn patch -+ this.setChunkRadius(i); // Move to method -+ } -+ -+ @Override -+ public void setChunkRadius(int radius) { -+ // Paper - copied from above -+ int j = radius * 2 + 1; - - this.b = j * j; - } -+ // Paper end - - @Override - public void a(ChunkCoordIntPair chunkcoordintpair) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public void setKeepSpawnInMemory(boolean keepLoaded) { -+ // Paper start - Configurable spawn radius -+ if (keepLoaded == world.keepSpawnInMemory) { -+ // do nothing, nothing has changed -+ return; -+ } - world.keepSpawnInMemory = keepLoaded; - // Grab the worlds spawn chunk -- BlockPosition chunkcoordinates = this.world.getSpawn(); -+ BlockPosition prevSpawn = this.world.getSpawn(); - if (keepLoaded) { -- world.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); -+ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } else { -- // TODO: doesn't work well if spawn changed.... -- world.getChunkProvider().removeTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); -+ // TODO: doesn't work well if spawn changed.... // paper - resolved -+ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); - } -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/Configurable-Non-Player-Arrow-Despawn-Rate.patch b/Spigot-Server-Patches/Configurable-Non-Player-Arrow-Despawn-Rate.patch deleted file mode 100644 index c1621a49aa..0000000000 --- a/Spigot-Server-Patches/Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 15:12:22 -0400 -Subject: [PATCH] Configurable Non Player Arrow Despawn Rate - -Can set a much shorter despawn rate for arrows that players can not pick up. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void nonPlayerEntitiesOnScoreboards() { - nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); - } -+ -+ public int nonPlayerArrowDespawnRate = -1; -+ public int creativeArrowDespawnRate = -1; -+ private void nonPlayerArrowDespawnRate() { -+ nonPlayerArrowDespawnRate = getInt("non-player-arrow-despawn-rate", -1); -+ if (nonPlayerArrowDespawnRate == -1) { -+ nonPlayerArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ creativeArrowDespawnRate = getInt("creative-arrow-despawn-rate", -1); -+ if (creativeArrowDespawnRate == -1) { -+ creativeArrowDespawnRate = spigotConfig.arrowDespawnRate; -+ } -+ log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); -+ log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile { - - protected void h() { - ++this.despawnCounter; -- if (this.despawnCounter >= ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)) { // Spigot -+ if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? - this.die(); - } - diff --git a/Spigot-Server-Patches/Configurable-Player-Collision.patch b/Spigot-Server-Patches/Configurable-Player-Collision.patch deleted file mode 100644 index 00c04944a3..0000000000 --- a/Spigot-Server-Patches/Configurable-Player-Collision.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 02:10:49 -0400 -Subject: [PATCH] Configurable Player Collision - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void regionFileCacheSize() { - regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); - } -+ -+ public static boolean enablePlayerCollisions = true; -+ private static void enablePlayerCollisions() { -+ enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutScoreboardTeam.java -@@ -0,0 +0,0 @@ public class PacketPlayOutScoreboardTeam implements Packet toRemove = scoreboard.getTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(ScoreboardTeam::getName).collect(java.util.stream.Collectors.toList()); -+ for (String teamName : toRemove) { -+ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves -+ } -+ -+ if (!com.destroystokyo.paper.PaperConfig.enablePlayerCollisions) { -+ this.getPlayerList().collideRuleTeamName = org.apache.commons.lang3.StringUtils.left("collideRule_" + java.util.concurrent.ThreadLocalRandom.current().nextInt(), 16); -+ ScoreboardTeam collideTeam = scoreboard.createTeam(this.getPlayerList().collideRuleTeamName); -+ collideTeam.setCanSeeFriendlyInvisibles(false); // Because we want to mimic them not being on a team at all -+ } -+ // Paper end -+ - this.server.enablePlugins(org.bukkit.plugin.PluginLoadOrder.POSTWORLD); - this.server.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.STARTUP)); - this.serverConnection.acceptConnections(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.SavedFile; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.level.storage.WorldNBTStorage; - import net.minecraft.world.phys.Vec3D; -+import net.minecraft.world.scores.Scoreboard; - import net.minecraft.world.scores.ScoreboardObjective; - import net.minecraft.world.scores.ScoreboardTeam; - import net.minecraft.world.scores.ScoreboardTeamBase; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // CraftBukkit start - private CraftServer cserver; - private final Map playersByName = new java.util.HashMap<>(); -+ public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule - - public PlayerList(MinecraftServer minecraftserver, IRegistryCustom.Dimension iregistrycustom_dimension, WorldNBTStorage worldnbtstorage, int i) { - this.cserver = minecraftserver.server = new CraftServer((DedicatedServer) minecraftserver, this); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - entityplayer.syncInventory(); -+ // Paper start - Add to collideRule team if needed -+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam collideRuleTeam = scoreboard.getTeam(collideRuleTeamName); -+ if (this.collideRuleTeamName != null && collideRuleTeam != null && entityplayer.getScoreboardTeam() == null) { -+ scoreboard.addPlayerToTeam(entityplayer.getName(), collideRuleTeam); -+ } -+ // Paper end - // CraftBukkit - Moved from above, added world - PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", entityplayer.getDisplayName().getString(), s1, entityplayer.getId(), worldserver1.worldDataServer.getName(), entityplayer.locX(), entityplayer.locY(), entityplayer.locZ()); - } -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.playerTick(); // SPIGOT-924 - // CraftBukkit end - -+ // Paper start - Remove from collideRule team if needed -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreBoard = this.server.getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam team = scoreBoard.getTeam(this.collideRuleTeamName); -+ if (entityplayer.getScoreboardTeam() == team && team != null) { -+ scoreBoard.removePlayerFromTeam(entityplayer.getName(), team); -+ } -+ } -+ // Paper end -+ - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - // CraftBukkit end - -+ // Paper start - Remove collideRule team if it exists -+ if (this.collideRuleTeamName != null) { -+ final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); -+ final ScoreboardTeam team = scoreboard.getTeam(this.collideRuleTeamName); -+ if (team != null) scoreboard.removeTeam(team); -+ } -+ // Paper end - } - - // CraftBukkit start diff --git a/Spigot-Server-Patches/Configurable-RCON-IP-address.patch b/Spigot-Server-Patches/Configurable-RCON-IP-address.patch deleted file mode 100644 index e35ad00e49..0000000000 --- a/Spigot-Server-Patches/Configurable-RCON-IP-address.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Apr 2016 00:39:33 -0400 -Subject: [PATCH] Configurable RCON IP address - -For servers with multiple IP's, ability to bind to a specific interface. - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -0,0 +0,0 @@ public class DedicatedServerProperties extends PropertyManager.EditableProperty whiteList; - public final GeneratorSettings generatorSettings; - -+ public final String rconIp; // Paper - Add rcon ip -+ - // CraftBukkit start - public DedicatedServerProperties(Properties properties, IRegistryCustom iregistrycustom, OptionSet optionset) { - super(properties, optionset); -@@ -0,0 +0,0 @@ public class DedicatedServerProperties extends PropertyManager> { - }; - } - -- @Nullable -- private String c(String s) { -+ @Nullable String getSettingIfExists(final String path) { return this.c(path); } // Paper - OBFHELPER -+ @Nullable private String c(String s) { // Paper - OBFHELPER - return (String) getOverride(s, this.properties.getProperty(s)); // CraftBukkit - } - -diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteControlListener.java -@@ -0,0 +0,0 @@ public class RemoteControlListener extends RemoteConnectionThread { - @Nullable - public static RemoteControlListener a(IMinecraftServer iminecraftserver) { - DedicatedServerProperties dedicatedserverproperties = iminecraftserver.getDedicatedServerProperties(); -- String s = iminecraftserver.h_(); -+ String s = dedicatedserverproperties.rconIp; // Paper - Configurable rcon ip - - if (s.isEmpty()) { - s = "0.0.0.0"; diff --git a/Spigot-Server-Patches/Configurable-baby-zombie-movement-speed.patch b/Spigot-Server-Patches/Configurable-baby-zombie-movement-speed.patch deleted file mode 100644 index ac9b2a945f..0000000000 --- a/Spigot-Server-Patches/Configurable-baby-zombie-movement-speed.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 1 Mar 2016 13:09:16 -0600 -Subject: [PATCH] Configurable baby zombie movement speed - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); - - } -+ -+ public double babyZombieMovementModifier; -+ private void babyZombieMovementModifier() { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-modifier", 0.5D); -+ if (PaperConfig.version < 20) { -+ babyZombieMovementModifier = getDouble("baby-zombie-movement-speed", 0.5D); -+ set("baby-zombie-movement-modifier", babyZombieMovementModifier); -+ } -+ -+ log("Baby zombies will move at the speed of " + babyZombieMovementModifier); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTransformEvent; - public class EntityZombie extends EntityMonster { - - private static final UUID b = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); -- private static final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); -+ private final AttributeModifier c = new AttributeModifier(EntityZombie.b, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.c; // Paper - remove static - Make baby speed configurable - private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); - private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); - public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - if (this.world != null && !this.world.isClientSide) { - AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); - -- attributemodifiable.removeModifier(EntityZombie.c); -+ attributemodifiable.removeModifier(this.babyModifier); // Paper - if (flag) { -- attributemodifiable.b(EntityZombie.c); -+ attributemodifiable.b(this.babyModifier); // Paper - } - } - diff --git a/Spigot-Server-Patches/Configurable-cactus-bamboo-and-reed-growth-heights.patch b/Spigot-Server-Patches/Configurable-cactus-bamboo-and-reed-growth-heights.patch deleted file mode 100644 index a219a21244..0000000000 --- a/Spigot-Server-Patches/Configurable-cactus-bamboo-and-reed-growth-heights.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 1 Mar 2016 13:02:51 -0600 -Subject: [PATCH] Configurable cactus bamboo and reed growth heights - -Bamboo - Both the minimum fully-grown heights and the maximum are configurable -- Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - config.addDefault("world-settings.default." + path, def); - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } -+ -+ public int cactusMaxHeight; -+ public int reedMaxHeight; -+ public int bambooMaxHeight; -+ public int bambooMinHeight; -+ private void blockGrowthHeight() { -+ cactusMaxHeight = getInt("max-growth-height.cactus", 3); -+ reedMaxHeight = getInt("max-growth-height.reeds", 3); -+ bambooMaxHeight = getInt("max-growth-height.bamboo.max", 16); -+ bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); -+ log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); -+ -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockBamboo.java -@@ -0,0 +0,0 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - if (random.nextInt(Math.max(1, (int) (100.0F / worldserver.spigotConfig.bambooModifier) * 3)) == 0 && worldserver.isEmpty(blockposition.up()) && worldserver.getLightLevel(blockposition.up(), 0) >= 9) { // Spigot - int i = this.b(worldserver, blockposition) + 1; - -- if (i < 16) { -+ if (i < worldserver.paperConfig.bambooMaxHeight) { // Paper - this.a(iblockdata, (World) worldserver, blockposition, random, i); - } - } -@@ -0,0 +0,0 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - int i = this.a(iblockaccess, blockposition); - int j = this.b(iblockaccess, blockposition); - -- return i + j + 1 < 16 && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; -+ return i + j + 1 < ((World) iblockaccess).paperConfig.bambooMaxHeight && (Integer) iblockaccess.getType(blockposition.up(i)).get(BlockBamboo.f) != 1; // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - BlockPosition blockposition1 = blockposition.up(i); - IBlockData iblockdata1 = worldserver.getType(blockposition1); - -- if (k >= 16 || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here -+ if (k >= worldserver.paperConfig.bambooMaxHeight || !iblockdata1.a(Blocks.BAMBOO) || (Integer) iblockdata1.get(BlockBamboo.f) == 1 || !worldserver.isEmpty(blockposition1.up())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here // Paper - Configurable cactus bamboo and reed growth heights - return; - } - -@@ -0,0 +0,0 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - } - - int j = (Integer) iblockdata.get(BlockBamboo.d) != 1 && !iblockdata2.a(Blocks.BAMBOO) ? 0 : 1; -- int k = (i < 11 || random.nextFloat() >= 0.25F) && i != 15 ? 0 : 1; -+ int k = (i < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && i != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper - - // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, blockposition, blockposition.up(), (IBlockData) ((IBlockData) ((IBlockData) this.getBlockData().set(BlockBamboo.d, j)).set(BlockBamboo.e, blockpropertybamboosize)).set(BlockBamboo.f, k), 3)) { -@@ -0,0 +0,0 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - protected int a(IBlockAccess iblockaccess, BlockPosition blockposition) { - int i; - -- for (i = 0; i < 16 && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.up(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper - ; - } - -@@ -0,0 +0,0 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement { - protected int b(IBlockAccess iblockaccess, BlockPosition blockposition) { - int i; - -- for (i = 0; i < 16 && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { -+ for (i = 0; i < ((World) iblockaccess).paperConfig.bambooMaxHeight && iblockaccess.getType(blockposition.down(i + 1)).a(Blocks.BAMBOO); ++i) { // Paper - ; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockCactus.java b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockCactus.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockCactus.java -@@ -0,0 +0,0 @@ public class BlockCactus extends Block { - ; - } - -- if (i < 3) { -+ if (i < worldserver.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height - int j = (Integer) iblockdata.get(BlockCactus.AGE); - - if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot -diff --git a/src/main/java/net/minecraft/world/level/block/BlockReed.java b/src/main/java/net/minecraft/world/level/block/BlockReed.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockReed.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockReed.java -@@ -0,0 +0,0 @@ public class BlockReed extends Block { - ; - } - -- if (i < 3) { -+ if (i < worldserver.paperConfig.reedMaxHeight) { // Paper - Configurable growth height - int j = (Integer) iblockdata.get(BlockReed.AGE); - - if (j >= (byte) range(3, ((100.0F / worldserver.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/Spigot-Server-Patches/Configurable-chance-of-villager-zombie-infection.patch b/Spigot-Server-Patches/Configurable-chance-of-villager-zombie-infection.patch deleted file mode 100644 index 09eca278d0..0000000000 --- a/Spigot-Server-Patches/Configurable-chance-of-villager-zombie-infection.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zero -Date: Sat, 22 Feb 2020 16:10:31 -0500 -Subject: [PATCH] Configurable chance of villager zombie infection - -This allows you to solve an issue in vanilla behavior where: -* On easy difficulty your villagers will NEVER get infected, meaning they will always die. -* On normal difficulty they will have a 50% of getting infected or dying. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void nerfNetherPortalPigmen() { - nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); - } -+ -+ public double zombieVillagerInfectionChance = -1.0; -+ private void zombieVillagerInfectionChance() { -+ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - @Override - public void a(WorldServer worldserver, EntityLiving entityliving) { - super.a(worldserver, entityliving); -- if ((worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { -- if (worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { -+ // Paper start -+ if (world.paperConfig.zombieVillagerInfectionChance != 0.0 && (world.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == EnumDifficulty.NORMAL || worldserver.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { -+ if (world.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { - return; - } -+ if (world.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > world.paperConfig.zombieVillagerInfectionChance) { -+ return; -+ } // Paper end - - EntityVillager entityvillager = (EntityVillager) entityliving; - // CraftBukkit start diff --git a/Spigot-Server-Patches/Configurable-connection-throttle-kick-message.patch b/Spigot-Server-Patches/Configurable-connection-throttle-kick-message.patch deleted file mode 100644 index 7af28c95de..0000000000 --- a/Spigot-Server-Patches/Configurable-connection-throttle-kick-message.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 2 Oct 2018 09:57:50 +0100 -Subject: [PATCH] Configurable connection throttle kick message - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } - -+ public static String connectionThrottleKickMessage = "Connection throttled! Please wait before reconnecting."; -+ private static void connectionThrottleKickMessage() { -+ connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- ChatMessage chatmessage = new ChatMessage("Connection throttled! Please wait before reconnecting."); -+ ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.c.close(chatmessage); - return; diff --git a/Spigot-Server-Patches/Configurable-container-update-tick-rate.patch b/Spigot-Server-Patches/Configurable-container-update-tick-rate.patch deleted file mode 100644 index 13cf2d78b0..0000000000 --- a/Spigot-Server-Patches/Configurable-container-update-tick-rate.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 23:34:44 -0600 -Subject: [PATCH] Configurable container update tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void mobSpawnerTickRate() { - mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); - } -+ -+ public int containerUpdateTickRate; -+ private void containerUpdateTickRate() { -+ containerUpdateTickRate = getInt("container-update-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean e; - public int ping; - public boolean viewingCredits; -+ private int containerUpdateDelay; // Paper - - // CraftBukkit start - public String displayName; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - --this.noDamageTicks; - } - -- this.activeContainer.c(); -+ // Paper start - Configurable container update tick rate -+ if (--containerUpdateDelay <= 0) { -+ this.activeContainer.c(); -+ containerUpdateDelay = world.paperConfig.containerUpdateTickRate; -+ } -+ // Paper end - if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { - this.closeInventory(); - this.activeContainer = this.defaultContainer; diff --git a/Spigot-Server-Patches/Configurable-door-breaking-difficulty.patch b/Spigot-Server-Patches/Configurable-door-breaking-difficulty.patch deleted file mode 100644 index 07939e1a35..0000000000 --- a/Spigot-Server-Patches/Configurable-door-breaking-difficulty.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 22:27:43 -0800 -Subject: [PATCH] Configurable door breaking difficulty - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ import java.util.EnumMap; - import java.util.HashMap; - import java.util.List; - import java.util.Map; -+import java.util.stream.Collectors; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; -+import net.minecraft.world.EnumDifficulty; -+import net.minecraft.world.entity.monster.EntityVindicator; -+import net.minecraft.world.entity.monster.EntityZombie; - import org.bukkit.Bukkit; - import org.bukkit.Material; - import org.bukkit.configuration.ConfigurationSection; -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); - } - -+ private > List getEnumList(String path, List def, Class type) { -+ config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); -+ return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); -+ } -+ - public int cactusMaxHeight; - public int reedMaxHeight; - public int bambooMaxHeight; -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableMobSpawnerSpawnEggTransformation() { - disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); - } -+ -+ public List zombieBreakDoors; -+ public List vindicatorBreakDoors; -+ private void setupEntityBreakingDoors() { -+ zombieBreakDoors = getEnumList( -+ "door-breaking-difficulty.zombie", -+ Arrays.stream(EnumDifficulty.values()) -+ .filter(EntityZombie.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ EnumDifficulty.class -+ ); -+ vindicatorBreakDoors = getEnumList( -+ "door-breaking-difficulty.vindicator", -+ Arrays.stream(EnumDifficulty.values()) -+ .filter(EntityVindicator.getDoorBreakingPredicate()) -+ .collect(Collectors.toList()), -+ EnumDifficulty.class -+ ); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.WorldAccess; - - public class EntityVindicator extends EntityIllagerAbstract { - -+ public static final Predicate getDoorBreakingPredicate() { return b; } // Paper - OBFHELPER - private static final Predicate b = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; - }; -@@ -0,0 +0,0 @@ public class EntityVindicator extends EntityIllagerAbstract { - static class a extends PathfinderGoalBreakDoor { - - public a(EntityInsentient entityinsentient) { -- super(entityinsentient, 6, EntityVindicator.b); -+ super(entityinsentient, 6, com.google.common.base.Predicates.in(entityinsentient.world.paperConfig.vindicatorBreakDoors)); // Paper - this.a(EnumSet.of(PathfinderGoal.Type.MOVE)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - private static final DataWatcherObject d = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); - private static final DataWatcherObject bo = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.b); - public static final DataWatcherObject DROWN_CONVERTING = DataWatcher.a(EntityZombie.class, DataWatcherRegistry.i); -+ public static final Predicate getDoorBreakingPredicate() { return bq; } // Paper - OBFHELPER - private static final Predicate bq = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.HARD; - }; -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - - public EntityZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.br = new PathfinderGoalBreakDoor(this, EntityZombie.bq); -+ this.br = new PathfinderGoalBreakDoor(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper - } - - public EntityZombie(World world) { diff --git a/Spigot-Server-Patches/Configurable-end-credits.patch b/Spigot-Server-Patches/Configurable-end-credits.patch deleted file mode 100644 index becd02ee01..0000000000 --- a/Spigot-Server-Patches/Configurable-end-credits.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DoctorDark -Date: Wed, 16 Mar 2016 02:21:39 -0500 -Subject: [PATCH] Configurable end credits - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean disableEndCredits; -+ private void disableEndCredits() { -+ disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -+ log("End credits disabled: " + disableEndCredits); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private long ca = SystemUtils.getMonotonicMillis(); - private Entity spectatedEntity; - public boolean worldChangeInvuln; -- private boolean cd; -+ private boolean cd; private void setHasSeenCredits(boolean has) { this.cd = has; } // Paper - OBFHELPER - private final RecipeBookServer recipeBook = new RecipeBookServer(); - private Vec3D cf; - private int cg; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.decouple(); - this.getWorldServer().removePlayer(this); - if (!this.viewingCredits) { -+ if (world.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits - this.viewingCredits = true; - this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.e, this.cd ? 0.0F : 1.0F)); - this.cd = true; diff --git a/Spigot-Server-Patches/Configurable-fishing-time-ranges.patch b/Spigot-Server-Patches/Configurable-fishing-time-ranges.patch deleted file mode 100644 index 7952235d02..0000000000 --- a/Spigot-Server-Patches/Configurable-fishing-time-ranges.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 1 Mar 2016 13:14:11 -0600 -Subject: [PATCH] Configurable fishing time ranges - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - - log("Baby zombies will move at the speed of " + babyZombieMovementModifier); - } -+ -+ public int fishingMinTicks; -+ public int fishingMaxTicks; -+ private void fishingTickRange() { -+ fishingMinTicks = getInt("fishing-time-range.MinimumTicks", 100); -+ fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); -+ log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile { - entityhuman.hookedFish = this; - this.an = Math.max(0, i); - this.lureLevel = Math.max(0, j); -+ // Paper start -+ minWaitTime = world.paperConfig.fishingMinTicks; -+ maxWaitTime = world.paperConfig.fishingMaxTicks; -+ // paper end - } - - public EntityFishingHook(EntityHuman entityhuman, World world, int i, int j) { diff --git a/Spigot-Server-Patches/Configurable-flying-kick-messages.patch b/Spigot-Server-Patches/Configurable-flying-kick-messages.patch deleted file mode 100644 index a46d5752f9..0000000000 --- a/Spigot-Server-Patches/Configurable-flying-kick-messages.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Tue, 20 Sep 2016 00:58:01 +0000 -Subject: [PATCH] Configurable flying kick messages - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - } - packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); - } -+ -+ public static String flyingKickPlayerMessage = "Flying is not enabled on this server"; -+ public static String flyingKickVehicleMessage = "Flying is not enabled on this server"; -+ private static void flyingKickMessages() { -+ flyingKickPlayerMessage = getString("messages.kick.flying-player", flyingKickPlayerMessage); -+ flyingKickVehicleMessage = getString("messages.kick.flying-vehicle", flyingKickVehicleMessage); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.B && !this.player.isSleeping()) { - if (++this.C > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating too long!", this.player.getDisplayName().getString()); -- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickPlayerMessage); // Paper - use configurable kick message - return; - } - } else { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - if (this.D && this.player.getRootVehicle().getRidingPassenger() == this.player) { - if (++this.E > 80) { - PlayerConnection.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getDisplayName().getString()); -- this.disconnect(new ChatMessage("multiplayer.disconnect.flying")); -+ this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message - return; - } - } else { diff --git a/Spigot-Server-Patches/Configurable-inter-world-teleportation-safety.patch b/Spigot-Server-Patches/Configurable-inter-world-teleportation-safety.patch deleted file mode 100644 index 0969946e5c..0000000000 --- a/Spigot-Server-Patches/Configurable-inter-world-teleportation-safety.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Thu, 3 Mar 2016 02:50:31 -0600 -Subject: [PATCH] Configurable inter-world teleportation safety - -People are able to abuse the way Bukkit handles teleportation across worlds since it provides a built in teleportation -safety check. - -To abuse the safety check, players are required to get into a location deemed unsafe by Bukkit e.g. be within a chest -or door block. While they are in this block, they accept a teleport request from a player within a different world. Once -the player teleports, Minecraft will recursively search upwards for a safe location, this could eventually land within a -player's skybase. - -Example setup to perform the glitch: http://puu.sh/ng3PC/cf072dcbdb.png -The wanted destination was on top of the emerald block however the player ended on top of the diamond block. -This only is the case if the player is teleporting between worlds. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - portalCreateRadius = getInt("portal-create-radius", 16); - portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); - } -+ -+ public boolean disableTeleportationSuffocationCheck; -+ private void disableTeleportationSuffocationCheck() { -+ disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (fromWorld == toWorld) { - entity.playerConnection.teleport(to); - } else { -- server.getHandle().moveToWorld(entity, toWorld, true, to, true); -+ server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper - } - return true; - } diff --git a/Spigot-Server-Patches/Configurable-max-leash-distance.patch b/Spigot-Server-Patches/Configurable-max-leash-distance.patch deleted file mode 100644 index a5880f394f..0000000000 --- a/Spigot-Server-Patches/Configurable-max-leash-distance.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 3 Jan 2021 21:04:03 -0800 -Subject: [PATCH] Configurable max leash distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - } - } - -+ public float maxLeashDistance = 10f; -+ private void maxLeashDistance() { -+ maxLeashDistance = getFloat("max-leash-distance", maxLeashDistance); -+ log("Max leash distance: " + maxLeashDistance); -+ } -+ - public boolean disableEndCredits; - private void disableEndCredits() { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -0,0 +0,0 @@ public abstract class EntityCreature extends EntityInsentient { - float f = this.g(entity); - - if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { -- if (f > 10.0F) { -+ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper - this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.unleash(true, true); - } -@@ -0,0 +0,0 @@ public abstract class EntityCreature extends EntityInsentient { - } - - this.x(f); -- if (f > 10.0F) { -+ if (f > entity.world.paperConfig.maxLeashDistance) { // Paper - this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit - this.unleash(true, true); - this.goalSelector.a(PathfinderGoal.Type.MOVE); diff --git a/Spigot-Server-Patches/Configurable-mob-spawner-tick-rate.patch b/Spigot-Server-Patches/Configurable-mob-spawner-tick-rate.patch deleted file mode 100644 index fe01a25206..0000000000 --- a/Spigot-Server-Patches/Configurable-mob-spawner-tick-rate.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 15:03:53 -0600 -Subject: [PATCH] Configurable mob spawner tick rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableIceAndSnow(){ - disableIceAndSnow = getBoolean("disable-ice-and-snow", false); - } -+ -+ public int mobSpawnerTickRate; -+ private void mobSpawnerTickRate() { -+ mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - public int maxNearbyEntities = 6; - public int requiredPlayerRange = 16; - public int spawnRange = 4; -+ private int tickDelay = 0; // Paper - - public MobSpawnerAbstract() {} - -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - } - - public void c() { -+ // Paper start - Configurable mob spawner tick rate -+ if (spawnDelay > 0 && --tickDelay > 0) return; -+ tickDelay = this.a().paperConfig.mobSpawnerTickRate; -+ // Paper end - if (!this.h()) { - this.f = this.e; - } else { -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - world.addParticle(Particles.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D); - world.addParticle(Particles.FLAME, d0, d1, d2, 0.0D, 0.0D, 0.0D); - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - } - - this.f = this.e; - this.e = (this.e + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; - } else { -- if (this.spawnDelay == -1) { -+ if (this.spawnDelay < -tickDelay) { // Paper - this.i(); - } - - if (this.spawnDelay > 0) { -- --this.spawnDelay; -+ this.spawnDelay -= tickDelay; // Paper - return; - } - diff --git a/Spigot-Server-Patches/Configurable-packet-in-spam-threshold.patch b/Spigot-Server-Patches/Configurable-packet-in-spam-threshold.patch deleted file mode 100644 index d2d7766003..0000000000 --- a/Spigot-Server-Patches/Configurable-packet-in-spam-threshold.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sun, 11 Sep 2016 14:30:57 -0500 -Subject: [PATCH] Configurable packet in spam threshold - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - public static boolean isProxyOnlineMode() { - return Bukkit.getOnlineMode() || (SpigotConfig.bungee && bungeeOnlineMode); - } -+ -+ public static int packetInSpamThreshold = 300; -+ private static void packetInSpamThreshold() { -+ if (version < 11) { -+ int oldValue = getInt("settings.play-in-use-item-spam-threshold", 300); -+ set("settings.incoming-packet-spam-threshold", oldValue); -+ } -+ packetInSpamThreshold = getInt("settings.incoming-packet-spam-threshold", 300); -+ } - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // Spigot start - limit place/interactions - private int limitedPackets; - private long lastLimitedPacket = -1; -+ private static final int THRESHOLD = com.destroystokyo.paper.PaperConfig.packetInSpamThreshold; // Paper - Configurable threshold - - private boolean checkLimit(long timestamp) { -- if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < 30 && limitedPackets++ >= 4) { -+ if (lastLimitedPacket != -1 && timestamp - lastLimitedPacket < THRESHOLD && limitedPackets++ >= 8) { // Paper - Use threshold, raise packet limit to 8 - return false; - } - -- if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= 30) { -+ if (lastLimitedPacket == -1 || timestamp - lastLimitedPacket >= THRESHOLD) { // Paper - lastLimitedPacket = timestamp; - limitedPackets = 0; - return true; diff --git a/Spigot-Server-Patches/Configurable-projectile-relative-velocity.patch b/Spigot-Server-Patches/Configurable-projectile-relative-velocity.patch deleted file mode 100644 index 0e58198579..0000000000 --- a/Spigot-Server-Patches/Configurable-projectile-relative-velocity.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lucavon -Date: Tue, 23 Jul 2019 20:29:20 -0500 -Subject: [PATCH] Configurable projectile relative velocity - -This patch adds an option "disable relative projectile velocity", which, when -nabled, will cause projectiles to ignore the shooter's current velocity, -like they did in Minecraft 1.8 and prior. -If a player is falling, for example, their shooting range will be drastically -reduced, as a downwards velocity is applied to the projectile. This prevents -players from saving themselves from falling off floating islands, for example, -as a thrown ender pearl will not make it back to the island, while it would -have in 1.8. - -While this could easily be done with plugins, too, there are multiple problems: -P1) If multiple plugins cancel the velocity by subtracting the shooter's velocity -from the projectile's velocity, the projectile's velocity would be different. -As there's no way to detect whether the projectile's velocity has already been -adjusted to ignore the player's velocity, plugins can't not do it if it's not -necessary. -P2) I've noticed some inconsistencies, e.g. weird velocity when shooting while -using an elytra. Checking for those inconsistencies is possible, but not as -efficient as just not applying the velocity in the first place. -P3) Solutions for 1) and especially 2) might not be future-proof, while this -server-internal fix makes this change future-proof. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); - } - } -+ -+ public boolean disableRelativeProjectileVelocity; -+ private void disableRelativeProjectileVelocity() { -+ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -0,0 +0,0 @@ public abstract class IProjectile extends Entity { - this.shoot((double) f5, (double) f6, (double) f7, f3, f4); - Vec3D vec3d = entity.getMot(); - -- this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); -+ if (!entity.world.paperConfig.disableRelativeProjectileVelocity) this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity - } - - // CraftBukkit start - call projectile hit event diff --git a/Spigot-Server-Patches/Configurable-spawn-chances-for-skeleton-horses.patch b/Spigot-Server-Patches/Configurable-spawn-chances-for-skeleton-horses.patch deleted file mode 100644 index 6e3e87a434..0000000000 --- a/Spigot-Server-Patches/Configurable-spawn-chances-for-skeleton-horses.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 22 Mar 2016 12:04:28 -0500 -Subject: [PATCH] Configurable spawn chances for skeleton horses - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); - log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); - } -+ -+ public double skeleHorseSpawnChance; -+ private void skeleHorseSpawnChance() { -+ skeleHorseSpawnChance = getDouble("skeleton-horse-thunder-spawn-chance", 0.01D); -+ if (skeleHorseSpawnChance < 0) { -+ skeleHorseSpawnChance = 0.01D; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - blockposition = this.a(this.a(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); -- boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * 0.01D; -+ boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper - - if (flag1) { - EntityHorseSkeleton entityhorseskeleton = (EntityHorseSkeleton) EntityTypes.SKELETON_HORSE.a((World) this); diff --git a/Spigot-Server-Patches/Configurable-speed-for-water-flowing-over-lava.patch b/Spigot-Server-Patches/Configurable-speed-for-water-flowing-over-lava.patch deleted file mode 100644 index 288cc82aa0..0000000000 --- a/Spigot-Server-Patches/Configurable-speed-for-water-flowing-over-lava.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 8 Aug 2018 16:33:21 -0600 -Subject: [PATCH] Configurable speed for water flowing over lava - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); - log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); - } -+ -+ public int waterOverLavaFlowSpeed; -+ private void waterOverLavaFlowSpeed() { -+ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); -+ log("Water over lava flow speed: " + waterOverLavaFlowSpeed); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFluids.java b/src/main/java/net/minecraft/world/level/block/BlockFluids.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFluids.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFluids.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.material.FluidType; - import net.minecraft.world.level.material.FluidTypeFlowing; - import net.minecraft.world.level.material.FluidTypes; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.level.pathfinder.PathMode; - import net.minecraft.world.level.storage.loot.LootTableInfo; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -0,0 +0,0 @@ public class BlockFluids extends Block implements IFluidSource { - @Override - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (this.a(world, blockposition, iblockdata)) { -- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); -+ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } - -+ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava -+ public int getFlowSpeed(World world, BlockPosition blockposition) { -+ if (this.material == Material.WATER) { -+ if ( -+ world.getMaterialIfLoaded(blockposition.north(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.south(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.west(1)) == Material.LAVA || -+ world.getMaterialIfLoaded(blockposition.east(1)) == Material.LAVA -+ ) { -+ return world.paperConfig.waterOverLavaFlowSpeed; -+ } -+ } -+ return this.b.a(world); -+ } -+ // Paper end -+ -+ - @Override - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - if (iblockdata.getFluid().isSource() || iblockdata1.getFluid().isSource()) { -@@ -0,0 +0,0 @@ public class BlockFluids extends Block implements IFluidSource { - @Override - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (this.a(world, blockposition, iblockdata)) { -- world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.b.a((IWorldReader) world)); -+ world.getFluidTickList().a(blockposition, iblockdata.getFluid().getType(), this.getFlowSpeed(world, blockposition)); // Paper - } - - } diff --git a/Spigot-Server-Patches/Configurable-sprint-interruption-on-attack.patch b/Spigot-Server-Patches/Configurable-sprint-interruption-on-attack.patch deleted file mode 100644 index 3120f02ae9..0000000000 --- a/Spigot-Server-Patches/Configurable-sprint-interruption-on-attack.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Sat, 14 Apr 2018 20:20:46 +0200 -Subject: [PATCH] Configurable sprint interruption on attack - -If the sprint interruption is disabled players continue sprinting when they attack entities. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void squidMaxSpawnHeight() { - squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); - } -+ -+ public boolean disableSprintInterruptionOnAttack; -+ private void disableSprintInterruptionOnAttack() { -+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - } - - this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); -- this.setSprinting(false); -+ // Paper start - Configuration option to disable automatic sprint interruption -+ if (!world.paperConfig.disableSprintInterruptionOnAttack) { -+ this.setSprinting(false); -+ } -+ // Paper end - } - - if (flag3) { diff --git a/Spigot-Server-Patches/Configurable-top-of-nether-void-damage.patch b/Spigot-Server-Patches/Configurable-top-of-nether-void-damage.patch deleted file mode 100644 index 1853b80edc..0000000000 --- a/Spigot-Server-Patches/Configurable-top-of-nether-void-damage.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 1 Mar 2016 23:58:50 -0600 -Subject: [PATCH] Configurable top of nether void damage - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); - if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); - } -+ -+ public int netherVoidTopDamageHeight; -+ public boolean doNetherTopVoidDamage() { return netherVoidTopDamageHeight > 0; } -+ private void netherVoidTopDamageHeight() { -+ netherVoidTopDamageHeight = getInt("nether-ceiling-void-damage-height", 0); -+ log("Top of the nether void damage height: " + netherVoidTopDamageHeight); -+ -+ if (PaperConfig.version < 18) { -+ boolean legacy = getBoolean("nether-ceiling-void-damage", false); -+ if (legacy) { -+ netherVoidTopDamageHeight = 128; -+ set("nether-ceiling-void-damage-height", netherVoidTopDamageHeight); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.fallDistance *= 0.5F; - } - -+ // Paper start - Configurable nether ceiling damage -+ -+ // Extracted to own function -+ /* - if (this.locY() < -64.0D) { - this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - if (!this.world.isClientSide) { - this.setFlag(0, this.fireTicks > 0); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.setFireTicks(0); - } - -+ // Paper start -+ protected void performVoidDamage() { -+ if (this.locY() < -64.0D || (this.world.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER -+ && world.paperConfig.doNetherTopVoidDamage() -+ && this.locY() >= world.paperConfig.netherVoidTopDamageHeight)) { -+ this.doVoidDamage(); -+ } -+ } -+ // Paper end -+ -+ protected final void doVoidDamage() { this.an(); } // Paper - OBFHELPER - protected void an() { - this.die(); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityMinecartAbstract extends Entity { - this.setDamage(this.getDamage() - 1.0F); - } - -+ // Paper start - Configurable nether ceiling damage -+ // Extracted to own function -+ /* - if (this.locY() < -64.0D) { - this.an(); - } -+ */ -+ this.performVoidDamage(); -+ // Paper end - - // this.doPortalTick(); // CraftBukkit - handled in postTick - if (this.world.isClientSide) { diff --git a/Spigot-Server-Patches/Convert-legacy-attributes-in-Item-Meta.patch b/Spigot-Server-Patches/Convert-legacy-attributes-in-Item-Meta.patch deleted file mode 100644 index 759f24dd73..0000000000 --- a/Spigot-Server-Patches/Convert-legacy-attributes-in-Item-Meta.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jul 2020 04:50:22 -0400 -Subject: [PATCH] Convert legacy attributes in Item Meta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - public class CraftAttributeMap implements Attributable { - - private final AttributeMapBase handle; -+ // Paper start - convert legacy attributes -+ private static final com.google.common.collect.ImmutableMap legacyNMS = com.google.common.collect.ImmutableMap.builder().put("generic.maxHealth", "generic.max_health").put("Max Health", "generic.max_health").put("zombie.spawnReinforcements", "zombie.spawn_reinforcements").put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements").put("horse.jumpStrength", "horse.jump_strength").put("Jump Strength", "horse.jump_strength").put("generic.followRange", "generic.follow_range").put("Follow Range", "generic.follow_range").put("generic.knockbackResistance", "generic.knockback_resistance").put("Knockback Resistance", "generic.knockback_resistance").put("generic.movementSpeed", "generic.movement_speed").put("Movement Speed", "generic.movement_speed").put("generic.flyingSpeed", "generic.flying_speed").put("Flying Speed", "generic.flying_speed").put("generic.attackDamage", "generic.attack_damage").put("generic.attackKnockback", "generic.attack_knockback").put("generic.attackSpeed", "generic.attack_speed").put("generic.armorToughness", "generic.armor_toughness").build(); -+ -+ public static String convertIfNeeded(String nms) { -+ if (nms == null) { -+ return null; -+ } -+ nms = legacyNMS.getOrDefault(nms, nms); -+ if (!nms.toLowerCase().equals(nms) || nms.indexOf(' ') != -1) { -+ return null; -+ } -+ return nms; -+ } -+ // Paper end - - public CraftAttributeMap(AttributeMapBase handle) { - this.handle = handle; -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); - -- String attributeName = entry.getString(ATTRIBUTES_IDENTIFIER.NBT); -+ String attributeName = CraftAttributeMap.convertIfNeeded(entry.getString(ATTRIBUTES_IDENTIFIER.NBT)); // Paper - if (attributeName == null || attributeName.isEmpty()) { - continue; - } diff --git a/Spigot-Server-Patches/Create-HoverEvent-from-ItemStack-Entity.patch b/Spigot-Server-Patches/Create-HoverEvent-from-ItemStack-Entity.patch deleted file mode 100644 index 2b896e95c9..0000000000 --- a/Spigot-Server-Patches/Create-HoverEvent-from-ItemStack-Entity.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 6 Jul 2020 22:18:04 +0200 -Subject: [PATCH] Create HoverEvent from ItemStack Entity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory { - - return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; - } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(ItemStack itemStack) { -+ net.md_5.bungee.api.chat.ItemTag itemTag = net.md_5.bungee.api.chat.ItemTag.ofNbt(CraftItemStack.asNMSCopy(itemStack).getOrCreateTag().toString()); -+ return new net.md_5.bungee.api.chat.hover.content.Item( -+ itemStack.getType().getKey().toString(), -+ itemStack.getAmount(), -+ itemTag); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(entity.getCustomName()) ? null : new net.md_5.bungee.api.chat.TextComponent(entity.getCustomName())); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, String customName) { -+ return hoverContentOf(entity, org.apache.commons.lang3.StringUtils.isBlank(customName) ? null : new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ customName); -+ } -+ -+ @Override -+ public net.md_5.bungee.api.chat.hover.content.Content hoverContentOf(org.bukkit.entity.Entity entity, net.md_5.bungee.api.chat.BaseComponent[] customName) { -+ return new net.md_5.bungee.api.chat.hover.content.Entity( -+ entity.getType().getKey().toString(), -+ entity.getUniqueId().toString(), -+ new net.md_5.bungee.api.chat.TextComponent(customName)); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Custom-replacement-for-eaten-items.patch b/Spigot-Server-Patches/Custom-replacement-for-eaten-items.patch deleted file mode 100644 index add86c6525..0000000000 --- a/Spigot-Server-Patches/Custom-replacement-for-eaten-items.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sun, 21 Jun 2015 15:07:20 -0400 -Subject: [PATCH] Custom replacement for eaten items - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.b(this.activeItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -+ PlayerItemConsumeEvent event = null; // Paper - if (this instanceof EntityPlayer) { - org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.activeItem); -- PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); -+ event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper - world.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } else { - itemstack = this.activeItem.a(this.world, this); - } -+ -+ // Paper start - save the default replacement item and change it if necessary -+ final ItemStack defaultReplacement = itemstack; -+ if (event != null && event.getReplacement() != null) { -+ itemstack = CraftItemStack.asNMSCopy(event.getReplacement()); -+ } -+ // Paper end - // CraftBukkit end - - if (itemstack != this.activeItem) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - this.clearActiveItem(); -+ // Paper start - if the replacement is anything but the default, update the client inventory -+ if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ ((EntityPlayer) this).getBukkitEntity().updateInventory(); -+ } -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/Dead-Player-s-shouldn-t-be-able-to-move.patch b/Spigot-Server-Patches/Dead-Player-s-shouldn-t-be-able-to-move.patch deleted file mode 100644 index a696558333..0000000000 --- a/Spigot-Server-Patches/Dead-Player-s-shouldn-t-be-able-to-move.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 19:31:16 -0400 -Subject: [PATCH] Dead Player's shouldn't be able to move - -This fixes a lot of game state issues where packets were delayed for processing -due to 1.15's new queue but processed while dead. - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - - @Override - protected boolean isFrozen() { -- return super.isFrozen() || this.isSleeping(); -+ return super.isFrozen() || this.isSleeping() || dead || !valid; // Paper - player's who are dead or not in a world shouldn't move... - } - - @Override diff --git a/Spigot-Server-Patches/Default-loading-permissions.yml-before-plugins.patch b/Spigot-Server-Patches/Default-loading-permissions.yml-before-plugins.patch deleted file mode 100644 index d10d717f03..0000000000 --- a/Spigot-Server-Patches/Default-loading-permissions.yml-before-plugins.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:17:38 -0400 -Subject: [PATCH] Default loading permissions.yml before plugins - -Under previous behavior, plugins were not able to check if a player had a permission -if it was defined in permissions.yml. there is no clean way for a plugin to fix that either. - -This will change the order so that by default, permissions.yml loads BEFORE plugins instead of after. - -This gives plugins expected permission checks. - -It also helps improve the expected logic, as servers should set the initial defaults, and then let plugins -modify that. Under the previous logic, plugins were unable (cleanly) override permissions.yml. - -A config option has been added for those who depend on the previous behavior, but I don't expect that. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void useDisplayNameInQuit() { - useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit); - } -+ -+ public static boolean loadPermsBeforePlugins = true; -+ private static void loadPermsBeforePlugins() { -+ loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); - helpMap.initializeGeneralTopics(); -+ if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - } - - Plugin[] plugins = pluginManager.getPlugins(); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); - DefaultPermissions.registerCorePermissions(); - CraftDefaultPermissions.registerCorePermissions(); -- loadCustomPermissions(); -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - helpMap.initializeCommands(); - syncCommands(); - } diff --git a/Spigot-Server-Patches/Delay-Chunk-Unloads-based-on-Player-Movement.patch b/Spigot-Server-Patches/Delay-Chunk-Unloads-based-on-Player-Movement.patch deleted file mode 100644 index 80a820eff0..0000000000 --- a/Spigot-Server-Patches/Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Jun 2016 23:22:12 -0400 -Subject: [PATCH] Delay Chunk Unloads based on Player Movement - -When players are moving in the world, doing things such as building or exploring, -they will commonly go back and forth in a small area. This causes a ton of chunk load -and unload activity on the edge chunks of their view distance. - -A simple back and forth movement in 6 blocks could spam a chunk to thrash a -loading and unload cycle over and over again. - -This is very wasteful. This system introduces a delay of inactivity on a chunk -before it actually unloads, which will be handled by the ticket expiry process. - -This allows servers with smaller worlds who do less long distance exploring to stop -wasting cpu cycles on saving/unloading/reloading chunks repeatedly. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void viewDistance() { - this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); - } -+ -+ public long delayChunkUnloadsBy; -+ private void delayChunkUnloadsBy() { -+ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s")); -+ if (delayChunkUnloadsBy > 0) { -+ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds"); -+ delayChunkUnloadsBy *= 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { - removed = true; // CraftBukkit -+ // Paper start - delay chunk unloads for player tickets -+ long delayChunkUnloadsBy = chunkMap.world.paperConfig.delayChunkUnloadsBy; -+ if (ticket.getTicketType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { -+ boolean hasPlayer = false; -+ for (Ticket ticket1 : arraysetsorted) { -+ if (ticket1.getTicketType() == TicketType.PLAYER) { -+ hasPlayer = true; -+ break; -+ } -+ } -+ PlayerChunk playerChunk = chunkMap.getUpdatingChunk(i); -+ if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { -+ Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); -+ delayUnload.delayUnloadBy = delayChunkUnloadsBy; -+ delayUnload.setCurrentTick(this.currentTick); -+ arraysetsorted.remove(delayUnload); -+ // refresh ticket -+ arraysetsorted.add(delayUnload); -+ } -+ } -+ // Paper end - } - - if (arraysetsorted.isEmpty()) { -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -0,0 +0,0 @@ public final class Ticket implements Comparable> { - public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER - private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER - public int priority = 0; // Paper -+ public long delayUnloadBy; // Paper - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; - this.b = i; - this.identifier = t0; -+ this.delayUnloadBy = tickettype.loadPeriod; // Paper - } - - public int compareTo(Ticket ticket) { -@@ -0,0 +0,0 @@ public final class Ticket implements Comparable> { - } - - protected boolean b(long i) { -- long j = this.a.b(); -+ long j = delayUnloadBy; // Paper - - return j != 0L && i - this.d > j; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -0,0 +0,0 @@ public class TicketType { - public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper - public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper - public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper -+ public static final TicketType DELAY_UNLOAD = a("delay_unload", Long::compareTo, 300); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); diff --git a/Spigot-Server-Patches/Delay-unsafe-actions-until-after-entity-ticking-is-d.patch b/Spigot-Server-Patches/Delay-unsafe-actions-until-after-entity-ticking-is-d.patch deleted file mode 100644 index fe26bb9687..0000000000 --- a/Spigot-Server-Patches/Delay-unsafe-actions-until-after-entity-ticking-is-d.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 21:23:42 -0400 -Subject: [PATCH] Delay unsafe actions until after entity ticking is done - -This will help prevent many cases of unregistering entities during entity ticking - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; -+ // Paper start -+ List afterEntityTickingTasks = Lists.newArrayList(); -+ public void doIfNotEntityTicking(java.lang.Runnable run) { -+ if (tickingEntities) { -+ afterEntityTickingTasks.add(run); -+ } else { -+ run.run(); -+ } -+ } -+ // Paper end - private final MinecraftServer server; - public final WorldDataServer worldDataServer; // CraftBukkit - type - public boolean savingDisabled; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ // Paper start -+ for (java.lang.Runnable run : this.afterEntityTickingTasks) { -+ try { -+ run.run(); -+ } catch (Exception e) { -+ LOGGER.error("Error in After Entity Ticking Task", e); -+ } -+ } -+ this.afterEntityTickingTasks.clear(); -+ // Paper end - this.getMinecraftServer().midTickLoadChunks(); // Paper - - Entity entity2; diff --git a/Spigot-Server-Patches/Disable-Explicit-Network-Manager-Flushing.patch b/Spigot-Server-Patches/Disable-Explicit-Network-Manager-Flushing.patch deleted file mode 100644 index f5b7a8d008..0000000000 --- a/Spigot-Server-Patches/Disable-Explicit-Network-Manager-Flushing.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 11 Mar 2018 14:13:33 -0400 -Subject: [PATCH] Disable Explicit Network Manager Flushing - -This seems completely pointless, as packet dispatch uses .writeAndFlush. - -Things seem to work fine without explicit flushing, but incase issues arise, -provide a System property to re-enable it using improved logic of doing the -flushing on the netty event loop, so it won't do the flush on the main thread. - -Renable flushing by passing -Dpaper.explicit-flush=true - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - // Paper start - NetworkClient implementation - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; -+ private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); - // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - if (this.channel != null) { -- this.channel.flush(); -+ if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version - } - - if (this.t++ % 20 == 0) { diff --git a/Spigot-Server-Patches/Disable-Scoreboards-for-non-players-by-default.patch b/Spigot-Server-Patches/Disable-Scoreboards-for-non-players-by-default.patch deleted file mode 100644 index 6f972cc9b2..0000000000 --- a/Spigot-Server-Patches/Disable-Scoreboards-for-non-players-by-default.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 8 Mar 2016 23:25:45 -0500 -Subject: [PATCH] Disable Scoreboards for non players by default - -Entities collision is checking for scoreboards setting. -This is very heavy to do map lookups for every collision to check -this setting. - -So avoid looking up scoreboards and short circuit to the "not on a team" -logic which is most likely to be true. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableTeleportationSuffocationCheck() { - disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); - } -+ -+ public boolean nonPlayerEntitiesOnScoreboards = false; -+ private void nonPlayerEntitiesOnScoreboards() { -+ nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - @Nullable - public ScoreboardTeamBase getScoreboardTeam() { -+ if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper - return this.world.getScoreboard().getPlayerTeam(this.getName()); - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - if (nbttagcompound.hasKeyOfType("Team", 8)) { - String s = nbttagcompound.getString("Team"); - ScoreboardTeam scoreboardteam = this.world.getScoreboard().getTeam(s); -+ if (!world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { scoreboardteam = null; } // Paper - boolean flag = scoreboardteam != null && this.world.getScoreboard().addPlayerToTeam(this.getUniqueIDString(), scoreboardteam); - - if (!flag) { diff --git a/Spigot-Server-Patches/Disable-explosion-knockback.patch b/Spigot-Server-Patches/Disable-explosion-knockback.patch deleted file mode 100644 index 00137e7b4f..0000000000 --- a/Spigot-Server-Patches/Disable-explosion-knockback.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:48:03 -0600 -Subject: [PATCH] Disable explosion knockback - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - optimizeExplosions = getBoolean("optimize-explosions", false); - log("Optimize explosions: " + optimizeExplosions); - } -+ -+ public boolean disableExplosionKnockback; -+ private void disableExplosionKnockback(){ -+ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - } - -+ boolean knockbackCancelled = world.paperConfig.disableExplosionKnockback && damagesource.isExplosion() && this instanceof EntityHuman; // Paper - Disable explosion knockback - if (flag1) { - if (flag) { - this.world.broadcastEntityEffect(this, (byte) 29); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - b0 = 2; - } - -+ if (!knockbackCancelled) // Paper - Disable explosion knockback - this.world.broadcastEntityEffect(this, b0); - } - -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - } - -+ if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback - if (this.dl()) { - if (!this.f(damagesource)) { - SoundEffect soundeffect = this.getSoundDeath(); -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -0,0 +0,0 @@ public class Explosion { - double d14 = d13; - - if (entity instanceof EntityLiving) { -- d14 = EnchantmentProtection.a((EntityLiving) entity, d13); -+ d14 = entity instanceof EntityHuman && world.paperConfig.disableExplosionKnockback ? 0 : EnchantmentProtection.a((EntityLiving) entity, d13); // Paper - Disable explosion knockback - } - - entity.setMot(entity.getMot().add(d8 * d14, d9 * d14, d10 * d14)); - if (entity instanceof EntityHuman) { - EntityHuman entityhuman = (EntityHuman) entity; - -- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying)) { -+ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.abilities.isFlying) && !world.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback - this.n.put(entityhuman, new Vec3D(d8 * d13, d9 * d13, d10 * d13)); - } - } diff --git a/Spigot-Server-Patches/Disable-ice-and-snow.patch b/Spigot-Server-Patches/Disable-ice-and-snow.patch deleted file mode 100644 index 60ab67faa2..0000000000 --- a/Spigot-Server-Patches/Disable-ice-and-snow.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:57:24 -0600 -Subject: [PATCH] Disable ice and snow - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableThunder() { - disableThunder = getBoolean("disable-thunder", false); - } -+ -+ public boolean disableIceAndSnow; -+ private void disableIceAndSnow(){ -+ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("iceandsnow"); -- if (this.random.nextInt(16) == 0) { -+ if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow - blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); - BlockPosition blockposition1 = blockposition.down(); - BiomeBase biomebase = this.getBiome(blockposition); diff --git a/Spigot-Server-Patches/Disable-spigot-tick-limiters.patch b/Spigot-Server-Patches/Disable-spigot-tick-limiters.patch deleted file mode 100644 index 61b8226545..0000000000 --- a/Spigot-Server-Patches/Disable-spigot-tick-limiters.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Wed, 2 Mar 2016 23:45:17 -0600 -Subject: [PATCH] Disable spigot tick limiters - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // Spigot start - // Iterator iterator = this.tileEntityListTick.iterator(); - int tilesThisCycle = 0; -- for (tileLimiter.initTick(); -- tilesThisCycle < tileEntityListTick.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue()); -- tileTickPosition++, tilesThisCycle++) { -+ for (tileTickPosition = 0; tileTickPosition < tileEntityListTick.size(); tileTickPosition++) { // Paper - Disable tick limiters - tileTickPosition = (tileTickPosition < tileEntityListTick.size()) ? tileTickPosition : 0; - TileEntity tileentity = (TileEntity) this.tileEntityListTick.get(tileTickPosition); - // Spigot start diff --git a/Spigot-Server-Patches/Disable-thunder.patch b/Spigot-Server-Patches/Disable-thunder.patch deleted file mode 100644 index e68a19d729..0000000000 --- a/Spigot-Server-Patches/Disable-thunder.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sudzzy -Date: Wed, 2 Mar 2016 14:52:43 -0600 -Subject: [PATCH] Disable thunder - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableExplosionKnockback(){ - disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); - } -+ -+ public boolean disableThunder; -+ private void disableThunder() { -+ disableThunder = getBoolean("disable-thunder", false); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - gameprofilerfiller.enter("thunder"); - BlockPosition blockposition; - -- if (flag && this.W() && this.random.nextInt(100000) == 0) { -+ if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder - blockposition = this.a(this.a(j, 0, k, 15)); - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); diff --git a/Spigot-Server-Patches/Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/Spigot-Server-Patches/Do-less-work-if-we-have-a-custom-Bukkit-generator.patch deleted file mode 100644 index db0d833966..0000000000 --- a/Spigot-Server-Patches/Do-less-work-if-we-have-a-custom-Bukkit-generator.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paul Sauve -Date: Sun, 14 Jul 2019 21:05:03 -0500 -Subject: [PATCH] Do less work if we have a custom Bukkit generator - -If the Bukkit generator already has a spawn, use it immediately instead -of spending time generating one that we won't use - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return biomebase.b().b(); -- }, random); -- ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); -+ // Paper start - moved down - // CraftBukkit start - if (worldserver.generator != null) { - Random rand = new Random(worldserver.getSeed()); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ return biomebase.b().b(); -+ }, random); -+ ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); -+ // Paper end - - if (blockposition == null) { - MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/Spigot-Server-Patches/Do-not-allow-bees-to-load-chunks-for-beehives.patch b/Spigot-Server-Patches/Do-not-allow-bees-to-load-chunks-for-beehives.patch deleted file mode 100644 index 9de794cc9b..0000000000 --- a/Spigot-Server-Patches/Do-not-allow-bees-to-load-chunks-for-beehives.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 17 Mar 2020 14:18:50 -0500 -Subject: [PATCH] Do not allow bees to load chunks for beehives - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - if (this.hivePos == null) { - return false; - } else { -+ if (!this.world.isLoadedAndInBounds(hivePos)) return false; // Paper - TileEntity tileentity = this.world.getTileEntity(this.hivePos); - - return tileentity instanceof TileEntityBeehive && ((TileEntityBeehive) tileentity).d(); -@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - } - - private boolean i(BlockPosition blockposition) { -+ if (!this.world.isLoadedAndInBounds(blockposition)) return false; // Paper - TileEntity tileentity = this.world.getTileEntity(blockposition); - - return tileentity instanceof TileEntityBeehive ? !((TileEntityBeehive) tileentity).isFull() : false; -@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - @Override - public boolean g() { - if (EntityBee.this.hasHivePos() && EntityBee.this.fd() && EntityBee.this.hivePos.a((IPosition) EntityBee.this.getPositionVector(), 2.0D)) { -+ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return false; // Paper - TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); - - if (tileentity instanceof TileEntityBeehive) { -@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - - @Override - public void c() { -+ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return; // Paper - TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); - - if (tileentity instanceof TileEntityBeehive) { diff --git a/Spigot-Server-Patches/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/Spigot-Server-Patches/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch deleted file mode 100644 index c256938f1d..0000000000 --- a/Spigot-Server-Patches/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 27 Dec 2020 11:31:06 +0000 -Subject: [PATCH] Do not crash from invalid ingredient lists in - VillagerAcquireTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - Bukkit.getPluginManager().callEvent(event); - } - if (!event.isCancelled()) { -- merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); -+ // Paper start -+ final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); -+ if (craftMerchantRecipe.getIngredients().isEmpty()) return; -+ merchantrecipelist.add(craftMerchantRecipe.toMinecraft()); -+ // Paper end - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/Do-not-let-armorstands-drown.patch b/Spigot-Server-Patches/Do-not-let-armorstands-drown.patch deleted file mode 100644 index 78f6d24636..0000000000 --- a/Spigot-Server-Patches/Do-not-let-armorstands-drown.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sat, 18 Feb 2017 19:29:58 -0600 -Subject: [PATCH] Do not let armorstands drown - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - super.a(d0, flag, iblockdata, blockposition); - } - -+ public boolean canBreatheUnderwater() { return this.cM(); } // Paper - OBFHELPER - public boolean cM() { - return this.getMonsterType() == EnumMonsterType.UNDEAD; - } -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - if (this.isAlive()) { - if (this.a((Tag) TagsFluid.WATER) && !this.world.getType(new BlockPosition(this.locX(), this.getHeadY(), this.locZ())).a(Blocks.BUBBLE_COLUMN)) { -- if (!this.cM() && !MobEffectUtil.c(this) && !flag1) { -+ if (!this.canBreatheUnderwater() && !MobEffectUtil.c(this) && !flag1) { // Paper - use OBFHELPER so it can be overridden - this.setAirTicks(this.l(this.getAirTicks())); - if (this.getAirTicks() == -20) { - this.setAirTicks(0); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - super.move(moveType, vec3d); - } - } -+ -+ @Override -+ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization -+ return true; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Do-not-let-the-server-load-chunks-from-newer-version.patch b/Spigot-Server-Patches/Do-not-let-the-server-load-chunks-from-newer-version.patch deleted file mode 100644 index c6b153248f..0000000000 --- a/Spigot-Server-Patches/Do-not-let-the-server-load-chunks-from-newer-version.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 23 Jul 2019 20:44:47 -0500 -Subject: [PATCH] Do not let the server load chunks from newer versions - -If the server attempts to load a chunk generated by a newer version of -the game, immediately stop the server to prevent data corruption. - -You can override this functionality at your own peril. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - return holder.protoChunk; - } - -+ // Paper start -+ private static final int CURRENT_DATA_VERSION = SharedConstants.getGameVersion().getWorldVersion(); -+ private static final boolean JUST_CORRUPT_IT = Boolean.getBoolean("Paper.ignoreWorldDataVersion"); -+ // Paper end -+ - public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { - ArrayDeque tasksToExecuteOnMain = new ArrayDeque<>(); - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); -+ // Paper start - Do NOT attempt to load chunks saved with newer versions -+ if (nbttagcompound.hasKeyOfType("DataVersion", 99)) { -+ int dataVersion = nbttagcompound.getInt("DataVersion"); -+ if (!JUST_CORRUPT_IT && dataVersion > CURRENT_DATA_VERSION) { -+ new RuntimeException("Server attempted to load chunk saved with newer version of minecraft! " + dataVersion + " > " + CURRENT_DATA_VERSION).printStackTrace(); -+ System.exit(1); -+ } -+ } -+ // Paper end - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate diff --git a/Spigot-Server-Patches/Do-not-load-chunks-for-Pathfinding.patch b/Spigot-Server-Patches/Do-not-load-chunks-for-Pathfinding.patch deleted file mode 100644 index 758bdef853..0000000000 --- a/Spigot-Server-Patches/Do-not-load-chunks-for-Pathfinding.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 31 Mar 2016 19:17:58 -0400 -Subject: [PATCH] Do not load chunks for Pathfinding - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - private BlockPosition p; - private int q; - private float r; -- private final Pathfinder s; -+ private final Pathfinder s; public Pathfinder getPathfinder() { return this.s; } // Paper - OBFHELPER - private boolean t; - - public NavigationAbstract(EntityInsentient entityinsentient, World world) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -@@ -0,0 +0,0 @@ public class Pathfinder { - - private final PathPoint[] a = new PathPoint[32]; - private final int b; -- private final PathfinderAbstract c; -+ private final PathfinderAbstract c; public PathfinderAbstract getPathfinder() { return this.c; } // Paper - OBFHELPER - private final Path d = new Path(); - - public Pathfinder(PathfinderAbstract pathfinderabstract, int i) { -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -@@ -0,0 +0,0 @@ public class PathfinderNormal extends PathfinderAbstract { - for (int j1 = -1; j1 <= 1; ++j1) { - if (l != 0 || j1 != 0) { - blockposition_mutableblockposition.d(i + l, j + i1, k + j1); -- IBlockData iblockdata = iblockaccess.getType(blockposition_mutableblockposition); -+ // Paper start -+ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (iblockdata == null) { -+ pathtype = PathType.BLOCKED; -+ } else { -+ // Paper end - - if (iblockdata.a(Blocks.CACTUS)) { - return PathType.DANGER_CACTUS; -@@ -0,0 +0,0 @@ public class PathfinderNormal extends PathfinderAbstract { - if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { - return PathType.WATER_BORDER; - } -+ } // Paper - } - } - } -@@ -0,0 +0,0 @@ public class PathfinderNormal extends PathfinderAbstract { - } - - protected static PathType b(IBlockAccess iblockaccess, BlockPosition blockposition) { -- IBlockData iblockdata = iblockaccess.getType(blockposition); -+ IBlockData iblockdata = iblockaccess.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return PathType.BLOCKED; // Paper - Block block = iblockdata.getBlock(); - Material material = iblockdata.getMaterial(); - diff --git a/Spigot-Server-Patches/Don-t-allow-digging-into-unloaded-chunks.patch b/Spigot-Server-Patches/Don-t-allow-digging-into-unloaded-chunks.patch deleted file mode 100644 index bfb94fc217..0000000000 --- a/Spigot-Server-Patches/Don-t-allow-digging-into-unloaded-chunks.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Nov 2018 21:01:09 +0000 -Subject: [PATCH] Don't allow digging into unloaded chunks - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - IBlockData iblockdata; - - if (this.j) { -- iblockdata = this.world.getType(this.k); -- if (iblockdata.isAir()) { -+ iblockdata = this.world.getTypeIfLoaded(this.k); // Paper -+ if (iblockdata == null || iblockdata.isAir()) { // Paper - this.j = false; - } else { - float f = this.a(iblockdata, this.k, this.l); -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - } - } - } else if (this.f) { -- iblockdata = this.world.getType(this.h); -+ // Paper start - don't want to do same logic as above, return instead -+ iblockdata = this.world.getTypeIfLoaded(this.h); -+ if (iblockdata == null) { -+ this.f = false; -+ return; -+ } -+ // Paper end - if (iblockdata.isAir()) { - this.world.a(this.player.getId(), this.h, -1); - this.m = -1; -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(blockposition, this.world.getType(blockposition), packetplayinblockdig_enumplayerdigtype, true, "stopped destroying")); - } else if (packetplayinblockdig_enumplayerdigtype == PacketPlayInBlockDig.EnumPlayerDigType.ABORT_DESTROY_BLOCK) { - this.f = false; -- if (!Objects.equals(this.h, blockposition)) { -+ if (!Objects.equals(this.h, blockposition) && !BlockPosition.ZERO.equals(this.h)) { - PlayerInteractManager.LOGGER.debug("Mismatch in destroy block pos: " + this.h + " " + blockposition); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled -- this.world.a(this.player.getId(), this.h, -1); -- this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, this.world.getType(this.h), packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); -+ IBlockData type = this.world.getTypeIfLoaded(this.h); // Paper - don't load unloaded chunks for stale records here -+ if (type != null) this.world.a(this.player.getId(), this.h, -1); // Paper -+ if (type != null) this.player.playerConnection.sendPacket(new PacketPlayOutBlockBreak(this.h, type, packetplayinblockdig_enumplayerdigtype, true, "aborted mismatched destroying")); // Paper -+ this.h = BlockPosition.ZERO; // Paper - } - - this.world.a(this.player.getId(), blockposition, -1); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - case START_DESTROY_BLOCK: - case ABORT_DESTROY_BLOCK: - case STOP_DESTROY_BLOCK: -+ // Paper start - Don't allow digging in unloaded chunks -+ if (this.player.world.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { -+ return; -+ } -+ // Paper end - Don't allow digging in unloaded chunks - this.player.playerInteractManager.a(blockposition, packetplayinblockdig_enumplayerdigtype, packetplayinblockdig.c(), this.minecraftServer.getMaxBuildHeight()); - return; - default: diff --git a/Spigot-Server-Patches/Don-t-allow-entities-to-ride-themselves-572.patch b/Spigot-Server-Patches/Don-t-allow-entities-to-ride-themselves-572.patch deleted file mode 100644 index 932c57cd1c..0000000000 --- a/Spigot-Server-Patches/Don-t-allow-entities-to-ride-themselves-572.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Sun, 8 Jan 2017 04:31:36 +0000 -Subject: [PATCH] Don't allow entities to ride themselves - #572 - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - protected boolean addPassenger(Entity entity) { // CraftBukkit -+ if (entity == this) throw new IllegalArgumentException("Entities cannot become a passenger of themselves"); // Paper - issue 572 - if (entity.getVehicle() != this) { - throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); - } else { diff --git a/Spigot-Server-Patches/Don-t-allow-null-UUID-s-for-chat.patch b/Spigot-Server-Patches/Don-t-allow-null-UUID-s-for-chat.patch deleted file mode 100644 index 920dbfc4bc..0000000000 --- a/Spigot-Server-Patches/Don-t-allow-null-UUID-s-for-chat.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:36:55 -0400 -Subject: [PATCH] Don't allow null UUID's for chat - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -0,0 +0,0 @@ package net.minecraft.network.protocol.game; - - import java.io.IOException; - import java.util.UUID; -+import net.minecraft.SystemUtils; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatMessageType; - import net.minecraft.network.chat.IChatBaseComponent; -@@ -0,0 +0,0 @@ public class PacketPlayOutChat implements Packet { - public PacketPlayOutChat(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype, UUID uuid) { - this.a = ichatbasecomponent; - this.b = chatmessagetype; -- this.c = uuid; -+ this.c = uuid != null ? uuid : SystemUtils.getNullUUID(); // Paper - } - - @Override diff --git a/Spigot-Server-Patches/Don-t-call-getItemMeta-on-hasItemMeta.patch b/Spigot-Server-Patches/Don-t-call-getItemMeta-on-hasItemMeta.patch deleted file mode 100644 index 79420ffc6a..0000000000 --- a/Spigot-Server-Patches/Don-t-call-getItemMeta-on-hasItemMeta.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Thu, 26 Jul 2018 14:10:23 +0200 -Subject: [PATCH] Don't call getItemMeta on hasItemMeta - -Spigot 1.13 checks if any field (which are manually copied from the ItemStack's "tag" NBT tag) on the ItemMeta class of an ItemStack is set. - -We could just check if the "tag" NBT tag is empty, albeit that would break some plugins. The only general tag added on 1.13 is "Damage", and we can just check if the "tag" NBT tag contains any other tag that's not "Damage" (https://minecraft.gamepedia.com/Player.dat_format#Item_structure) making the `hasItemStack` method behave as before. - -Returns true if getDamage() == 0 or has damage tag or other tag is set. -Check the `ItemMetaTest#testTaggedButNotMeta` method to see how this method behaves. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean hasItemMeta() { -- return hasItemMeta(handle) && !CraftItemFactory.instance().equals(getItemMeta(), null); -+ return hasItemMeta(handle) && (handle.getDamage() != 0 || (handle.getTag() != null && handle.getTag().map.size() >= (handle.getTag().hasKey(CraftMetaItem.DAMAGE.NBT) ? 2 : 1))); // Paper - keep 1.12 CraftBukkit behavior without calling getItemMeta - } - - static boolean hasItemMeta(net.minecraft.world.item.ItemStack item) { -diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java -@@ -0,0 +0,0 @@ public class ItemMetaTest extends AbstractTestingBase { - assertThat(itemMeta.hasConflictingEnchant(null), is(false)); - } - -+ // Paper start -+ private void testItemMeta(ItemStack stack) { -+ assertThat("Should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with zero durability should not have ItemMeta", stack.hasItemMeta(), is(false)); -+ -+ stack.setDurability((short) 2); -+ assertThat("ItemStack with non-zero durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(java.util.Collections.singletonList("Lore")); -+ assertThat("ItemStack with lore and durability should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setDurability((short) 0); -+ assertThat("ItemStack with lore should have ItemMeta", stack.hasItemMeta(), is(true)); -+ -+ stack.setLore(null); -+ } -+ -+ @Test -+ public void testHasItemMeta() { -+ ItemStack itemStack = new ItemStack(Material.SHEARS); -+ -+ testItemMeta(itemStack); -+ testItemMeta(CraftItemStack.asCraftCopy(itemStack)); -+ } -+ // Paper end -+ - @Test - public void testConflictingStoredEnchantment() { - EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) Bukkit.getItemFactory().getItemMeta(Material.ENCHANTED_BOOK); diff --git a/Spigot-Server-Patches/Don-t-change-the-Entity-Random-seed-for-squids.patch b/Spigot-Server-Patches/Don-t-change-the-Entity-Random-seed-for-squids.patch deleted file mode 100644 index 9c244aeb03..0000000000 --- a/Spigot-Server-Patches/Don-t-change-the-Entity-Random-seed-for-squids.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:05:00 -0400 -Subject: [PATCH] Don't change the Entity Random seed for squids - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -0,0 +0,0 @@ public class EntitySquid extends EntityWaterAnimal { - - public EntitySquid(EntityTypes entitytypes, World world) { - super(entitytypes, world); -- this.random.setSeed((long) this.getId()); -+ //this.random.setSeed((long) this.getId()); // Paper - this.bu = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; - } - diff --git a/Spigot-Server-Patches/Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/Spigot-Server-Patches/Don-t-check-ConvertSigns-boolean-every-sign-save.patch deleted file mode 100644 index a97e02ff99..0000000000 --- a/Spigot-Server-Patches/Don-t-check-ConvertSigns-boolean-every-sign-save.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 11:11:29 -0500 -Subject: [PATCH] Don't check ConvertSigns boolean every sign save - -property lookups arent super cheap. they synchronize, validate -and check security managers. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - private final FormattedString[] g; - private EnumColor color; - public java.util.UUID signEditor; // Paper -+ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper - - public TileEntitySign() { - super(TileEntityTypes.SIGN); -@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - // CraftBukkit start -- if (Boolean.getBoolean("convertLegacySigns")) { -+ if (CONVERT_LEGACY_SIGNS) { // Paper - nbttagcompound.setBoolean("Bukkit.isConverted", true); - } - // CraftBukkit end diff --git a/Spigot-Server-Patches/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/Spigot-Server-Patches/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch deleted file mode 100644 index 322f2263d8..0000000000 --- a/Spigot-Server-Patches/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Jul 2020 14:59:31 -0400 -Subject: [PATCH] Don't check chunk for portal on world gen entity add - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - Entity entity = this.getVehicle(); - - super.stopRiding(suppressCancellation); // Paper - suppress -- if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { -+ if (entity != null && entity != this.getVehicle() && !this.world.isClientSide && entity.valid) { // Paper - don't process on world gen - this.a(entity); - } - diff --git a/Spigot-Server-Patches/Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/Spigot-Server-Patches/Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch deleted file mode 100644 index 637f8d6877..0000000000 --- a/Spigot-Server-Patches/Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 15:59:41 -0400 -Subject: [PATCH] Don't crash if player is attempted to be removed from - untracked chunk. - -I suspect it deals with teleporting as it uses players current x/y/z - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - ObjectSet objectset = (ObjectSet) this.c.get(i); - if (objectset == null) return; // CraftBukkit - SPIGOT-6208 - -- objectset.remove(entityplayer); -- if (objectset.isEmpty()) { -+ if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. -+ if (objectset == null || objectset.isEmpty()) { // Paper - this.c.remove(i); - this.f.update(i, Integer.MAX_VALUE, false); - this.g.update(i, Integer.MAX_VALUE, false); diff --git a/Spigot-Server-Patches/Don-t-fire-BlockFade-on-worldgen-threads.patch b/Spigot-Server-Patches/Don-t-fire-BlockFade-on-worldgen-threads.patch deleted file mode 100644 index 84adb23237..0000000000 --- a/Spigot-Server-Patches/Don-t-fire-BlockFade-on-worldgen-threads.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 23 Apr 2020 01:36:39 -0400 -Subject: [PATCH] Don't fire BlockFade on worldgen threads - -Caused a deadlock - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - @Override - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - // CraftBukkit start -+ if (!(generatoraccess instanceof WorldServer)) return this.canPlace(iblockdata, generatoraccess, blockposition) ? (IBlockData) this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)) : Blocks.AIR.getBlockData(); // Paper - don't fire events in world generation - if (!this.canPlace(iblockdata, generatoraccess, blockposition)) { - // Suppress during worldgen - if (!(generatoraccess instanceof World)) { -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - return blockState.getHandle(); - } - } -- return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); -+ return this.a(generatoraccess, blockposition, (Integer) iblockdata.get(BlockFire.AGE)); // Paper - diff on change, see "don't fire events in world generation" - // CraftBukkit end - } - diff --git a/Spigot-Server-Patches/Don-t-ignore-result-of-PlayerEditBookEvent.patch b/Spigot-Server-Patches/Don-t-ignore-result-of-PlayerEditBookEvent.patch deleted file mode 100644 index d7ceb2f270..0000000000 --- a/Spigot-Server-Patches/Don-t-ignore-result-of-PlayerEditBookEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Mon, 5 Apr 2021 18:35:15 -0700 -Subject: [PATCH] Don't ignore result of PlayerEditBookEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - list.stream().map(NBTTagString::a).forEach(nbttaglist::add); - ItemStack old = itemstack.cloneItemStack(); // CraftBukkit - itemstack.a("pages", (NBTBase) nbttaglist); -- CraftEventFactory.handleEditBookEvent(player, i, old, itemstack); // CraftBukkit -+ this.player.inventory.setItem(i, CraftEventFactory.handleEditBookEvent(player, i, old, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) - } - } - diff --git a/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch b/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch deleted file mode 100644 index c03d023707..0000000000 --- a/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Fri, 16 Dec 2016 16:03:19 -0600 -Subject: [PATCH] Don't let fishinghooks use portals - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile { - - this.setMot(this.getMot().a(0.92D)); - this.af(); -+ // Paper start - These shouldn't be going through portals -+ if (this.inPortal) { -+ this.die(); -+ } -+ // Paper end - } - } - diff --git a/Spigot-Server-Patches/Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/Spigot-Server-Patches/Don-t-load-Chunks-from-Hoppers-and-other-things.patch deleted file mode 100644 index 7fa77b15d2..0000000000 --- a/Spigot-Server-Patches/Don-t-load-Chunks-from-Hoppers-and-other-things.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Nov 2016 20:28:12 -0400 -Subject: [PATCH] Don't load Chunks from Hoppers and other things - -Hoppers call this to I guess "get the primary side" of a double sided chest. - -If the double sided chest crosses chunk lines, it causes the chunk to load. -This will end up causing sync chunk loads, which will unload with Chunk GC, -only to be reloaded again the next tick. - -This of course is undesirable, so just return the loaded side as "primary" -and treat it as a single chest if the other sides are unloaded - -diff --git a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -+++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockFinder.java -@@ -0,0 +0,0 @@ public class DoubleBlockFinder { - return new DoubleBlockFinder.Result.Single<>(s0); - } else { - BlockPosition blockposition1 = blockposition.shift((EnumDirection) function1.apply(iblockdata)); -- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); -+ // Paper start -+ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); -+ if (iblockdata1 == null) { -+ return new DoubleBlockFinder.Result.Single<>(s0); -+ } -+ // Paper end - - if (iblockdata1.a(iblockdata.getBlock())) { - DoubleBlockFinder.BlockType doubleblockfinder_blocktype1 = (DoubleBlockFinder.BlockType) function.apply(iblockdata1); diff --git a/Spigot-Server-Patches/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/Spigot-Server-Patches/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch deleted file mode 100644 index cb8f6d67f2..0000000000 --- a/Spigot-Server-Patches/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sat, 16 Jul 2016 19:11:17 -0500 -Subject: [PATCH] Don't lookup game profiles that have no UUID and no name - - -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -0,0 +0,0 @@ public class UserCache { - gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); - GameProfile gameprofile = (GameProfile) atomicreference.get(); - -- if (!c() && gameprofile == null) { -+ if (!c() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(s)) { // Paper - Don't lookup a profile with a blank name - UUID uuid = EntityHuman.a(new GameProfile((UUID) null, s)); - - gameprofile = new GameProfile(uuid, s); diff --git a/Spigot-Server-Patches/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/Spigot-Server-Patches/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch deleted file mode 100644 index bed15a3ab0..0000000000 --- a/Spigot-Server-Patches/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 27 Sep 2020 16:25:24 +0200 -Subject: [PATCH] Don't mark dirty in invalid locations (SPIGOT-6086) - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - - public void a(BlockPosition blockposition) { -+ if (!blockposition.isValidLocation()) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks - Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { diff --git a/Spigot-Server-Patches/Don-t-mark-null-chunk-sections-for-block-updates.patch b/Spigot-Server-Patches/Don-t-mark-null-chunk-sections-for-block-updates.patch deleted file mode 100644 index 80b20211fe..0000000000 --- a/Spigot-Server-Patches/Don-t-mark-null-chunk-sections-for-block-updates.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:41:19 +0200 -Subject: [PATCH] Don't mark null chunk sections for block updates - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - this.a(world, blockposition, iblockdata); - } else { - ChunkSection chunksection = chunk.getSections()[sectionposition.getY()]; -+ if (chunksection == null) chunksection = new ChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found - PacketPlayOutMultiBlockChange packetplayoutmultiblockchange = new PacketPlayOutMultiBlockChange(sectionposition, shortset, chunksection, this.x); - - this.a(packetplayoutmultiblockchange, false); diff --git a/Spigot-Server-Patches/Don-t-move-existing-players-to-world-spawn.patch b/Spigot-Server-Patches/Don-t-move-existing-players-to-world-spawn.patch deleted file mode 100644 index d660d400fa..0000000000 --- a/Spigot-Server-Patches/Don-t-move-existing-players-to-world-spawn.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 9 Apr 2020 21:20:33 -0400 -Subject: [PATCH] Don't move existing players to world spawn - -This can cause a nasty server lag the spawn chunks are not kept loaded -or they aren't finished loading yet, or if the world spawn radius is -larger than the keep loaded range. - -By skipping this, we avoid potential for a large spike on server start. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.serverStatisticManager = minecraftserver.getPlayerList().getStatisticManager(this); - this.advancementDataPlayer = minecraftserver.getPlayerList().f(this); - this.G = 1.0F; -- this.c(worldserver); -+ //this.c(worldserver); // Paper - don't move to spawn on login, only first join - this.co = minecraftserver.a(this); - - this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // CraftBukkit end - -+ public final void moveToSpawn(WorldServer worldserver) { c(worldserver); } // Paper - OBFHELPER - private void c(WorldServer worldserver) { - BlockPosition blockposition = worldserver.getSpawn(); - -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - position = Vec3D.a(((WorldServer) world).getSpawn()); - } - this.world = world; -- this.setPosition(position.getX(), position.getY(), position.getZ()); -+ this.setPositionRaw(position.getX(), position.getY(), position.getZ()); // Paper - don't register to chunks yet - } - this.playerInteractManager.a((WorldServer) world); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - worldserver1 = worldserver; - } - -+ if (nbttagcompound == null) entityplayer.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... -+ - entityplayer.spawnIn(worldserver1); - entityplayer.playerInteractManager.a((WorldServer) entityplayer.world); - String s1 = "local"; diff --git a/Spigot-Server-Patches/Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/Spigot-Server-Patches/Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch deleted file mode 100644 index 2a519f1c65..0000000000 --- a/Spigot-Server-Patches/Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Tue, 8 Mar 2016 18:28:43 -0800 -Subject: [PATCH] Don't nest if we don't need to when cerealising text - components - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -0,0 +0,0 @@ public class PacketPlayOutChat implements Packet { - // Paper end - // Spigot start - if (components != null) { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); -+ //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below -+ // Paper start - don't nest if we don't need to so that we can preserve formatting -+ if (this.components.length == 1) { -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ } else { -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ } -+ // Paper end - } else { - packetdataserializer.a(this.a); - } diff --git a/Spigot-Server-Patches/Don-t-require-FACING-data.patch b/Spigot-Server-Patches/Don-t-require-FACING-data.patch deleted file mode 100644 index e2b2af0870..0000000000 --- a/Spigot-Server-Patches/Don-t-require-FACING-data.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 23 Aug 2020 19:01:04 +0200 -Subject: [PATCH] Don't require FACING data - - -diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -+++ b/src/main/java/net/minecraft/core/dispenser/DispenseBehaviorItem.java -@@ -0,0 +0,0 @@ import org.bukkit.event.block.BlockDispenseEvent; - // CraftBukkit end - - public class DispenseBehaviorItem implements IDispenseBehavior { -+ private EnumDirection enumdirection; // Paper - - public DispenseBehaviorItem() {} - - @Override - public final ItemStack dispense(ISourceBlock isourceblock, ItemStack itemstack) { -+ enumdirection = isourceblock.getBlockData().get(BlockDispenser.FACING); // Paper - cache facing direction - ItemStack itemstack1 = this.a(isourceblock, itemstack); - - this.a(isourceblock); -- this.a(isourceblock, (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING)); -+ this.a(isourceblock, enumdirection); // Paper - cache facing direction - return itemstack1; - } - - protected ItemStack a(ISourceBlock isourceblock, ItemStack itemstack) { -- EnumDirection enumdirection = (EnumDirection) isourceblock.getBlockData().get(BlockDispenser.FACING); -+ // Paper - cached enum direction - IPosition iposition = BlockDispenser.a(isourceblock); - ItemStack itemstack1 = itemstack.cloneAndSubtract(1); - diff --git a/Spigot-Server-Patches/Don-t-run-entity-collision-code-if-not-needed.patch b/Spigot-Server-Patches/Don-t-run-entity-collision-code-if-not-needed.patch deleted file mode 100644 index 8d22fb3c5d..0000000000 --- a/Spigot-Server-Patches/Don-t-run-entity-collision-code-if-not-needed.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 17:56:07 -0700 -Subject: [PATCH] Don't run entity collision code if not needed - -Will not run if max entity craming is disabled and -the max collisions per entity is less than or equal to 0 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - protected void doTick() {} - - protected void collideNearby() { -+ // Paper - start don't run getEntities if we're not going to use its result -+ int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); -+ if (i <= 0 && world.paperConfig.maxCollisionsPerEntity <= 0) { -+ return; -+ } -+ // Paper - end don't run getEntities if we're not going to use its result - List list = this.world.getEntities(this, this.getBoundingBox(), IEntitySelector.a(this)); - - if (!list.isEmpty()) { -- int i = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); -+ // Paper - move up - int j; - - if (i > 0 && list.size() > i - 1 && this.random.nextInt(4) == 0) { diff --git a/Spigot-Server-Patches/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/Spigot-Server-Patches/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch deleted file mode 100644 index 240c806b19..0000000000 --- a/Spigot-Server-Patches/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 May 2016 23:33:08 -0400 -Subject: [PATCH] Don't save empty scoreboard teams to scoreboard.dat - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void enablePlayerCollisions() { - enablePlayerCollisions = getBoolean("settings.enable-player-collisions", true); - } -+ -+ public static boolean saveEmptyScoreboardTeams = false; -+ private static void saveEmptyScoreboardTeams() { -+ saveEmptyScoreboardTeams = getBoolean("settings.save-empty-scoreboard-teams", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -+++ b/src/main/java/net/minecraft/world/scores/PersistentScoreboard.java -@@ -0,0 +0,0 @@ public class PersistentScoreboard extends PersistentBase { - - while (iterator.hasNext()) { - ScoreboardTeam scoreboardteam = (ScoreboardTeam) iterator.next(); -+ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && scoreboardteam.getPlayerNameSet().isEmpty()) continue; // Paper - NBTTagCompound nbttagcompound = new NBTTagCompound(); - - nbttagcompound.setString("Name", scoreboardteam.getName()); diff --git a/Spigot-Server-Patches/Don-t-sleep-after-profile-lookups-if-not-needed.patch b/Spigot-Server-Patches/Don-t-sleep-after-profile-lookups-if-not-needed.patch deleted file mode 100644 index 28a28f9160..0000000000 --- a/Spigot-Server-Patches/Don-t-sleep-after-profile-lookups-if-not-needed.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 20:25:05 -0400 -Subject: [PATCH] Don't sleep after profile lookups if not needed - -Mojang was sleeping even if we had no more requests to go after -the current one finished, resulting in 100ms lost per profile lookup - -diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -+++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java -@@ -0,0 +0,0 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - } - - final int page = 0; -+ boolean hasRequested = false; // Paper - - for (final List request : Iterables.partition(criteria, ENTRIES_PER_PAGE)) { - int failCount = 0; -@@ -0,0 +0,0 @@ public class YggdrasilGameProfileRepository implements GameProfileRepository { - LOGGER.debug("Couldn't find profile {}", name); - callback.onProfileLookupFailed(new GameProfile(null, name), new ProfileNotFoundException("Server did not find the requested profile")); - } -+ // Paper start -+ if (!hasRequested) { -+ hasRequested = true; -+ continue; -+ } -+ // Paper end - - try { - Thread.sleep(DELAY_BETWEEN_PAGES); diff --git a/Spigot-Server-Patches/Don-t-tick-Skulls-unused-code.patch b/Spigot-Server-Patches/Don-t-tick-Skulls-unused-code.patch deleted file mode 100644 index deb2a4be9b..0000000000 --- a/Spigot-Server-Patches/Don-t-tick-Skulls-unused-code.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:30:10 -0400 -Subject: [PATCH] Don't tick Skulls - unused code - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.world.entity.player.EntityHuman; - // Spigot end - --public class TileEntitySkull extends TileEntity implements ITickable { -+public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Paper - remove tickable - - @Nullable - private static UserCache userCache; -@@ -0,0 +0,0 @@ public class TileEntitySkull extends TileEntity implements ITickable { - - } - -- @Override -+ // Paper - remove override - public void tick() { - IBlockData iblockdata = this.getBlock(); - diff --git a/Spigot-Server-Patches/Don-t-tick-dead-players.patch b/Spigot-Server-Patches/Don-t-tick-dead-players.patch deleted file mode 100644 index 1080a57a49..0000000000 --- a/Spigot-Server-Patches/Don-t-tick-dead-players.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 17:16:48 -0400 -Subject: [PATCH] Don't tick dead players - -Causes sync chunk loads and who knows what all else. -This is safe because Spectators are skipped in unloaded chunks too in vanilla. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - public void playerTick() { - try { -- if (!this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { -+ if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } - diff --git a/Spigot-Server-Patches/Drop-carried-item-when-player-has-disconnected.patch b/Spigot-Server-Patches/Drop-carried-item-when-player-has-disconnected.patch deleted file mode 100644 index c0a265425d..0000000000 --- a/Spigot-Server-Patches/Drop-carried-item-when-player-has-disconnected.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Dmitry Sidorov -Date: Thu, 4 Feb 2021 20:32:01 +0300 -Subject: [PATCH] Drop carried item when player has disconnected - -Fixes disappearance of held items, when a player gets disconnected and PlayerDropItemEvent is cancelled. -Closes #5036 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.npc.EntityVillagerAbstract; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.item.ItemStack; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - // Paper end - -+ // Paper - Drop carried item when player has disconnected -+ if (!entityplayer.inventory.getCarried().isEmpty()) { -+ ItemStack carried = entityplayer.inventory.getCarried(); -+ entityplayer.inventory.setCarried(ItemStack.NULL_ITEM); -+ entityplayer.drop(carried, false); -+ } -+ // Paper end -+ - this.savePlayerFile(entityplayer); - if (entityplayer.isPassenger()) { - Entity entity = entityplayer.getRootVehicle(); diff --git a/Spigot-Server-Patches/Drop-falling-block-and-tnt-entities-at-the-specified.patch b/Spigot-Server-Patches/Drop-falling-block-and-tnt-entities-at-the-specified.patch deleted file mode 100644 index 3ae8b46d78..0000000000 --- a/Spigot-Server-Patches/Drop-falling-block-and-tnt-entities-at-the-specified.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 14:14:15 -0600 -Subject: [PATCH] Drop falling block and tnt entities at the specified height - -* Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); - log("Keep spawn chunk loaded: " + keepSpawnInMemory); - } -+ -+ public int fallingBlockHeightNerf; -+ public int entityTNTHeightNerf; -+ private void heightNerfs() { -+ fallingBlockHeightNerf = getInt("falling-block-height-nerf", 0); -+ entityTNTHeightNerf = getInt("tnt-entity-height-nerf", 0); -+ -+ if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); -+ if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.a(itemstack, 0.0F); - } - -+ @Nullable public final EntityItem dropItem(ItemStack itemstack, float offset) { return this.a(itemstack, offset); } // Paper - OBFHELPER - @Nullable - public EntityItem a(ItemStack itemstack, float f) { - if (itemstack.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { - } - - this.move(EnumMoveType.SELF, this.getMot()); -+ -+ // Paper start - Configurable EntityFallingBlock height nerf -+ if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { -+ if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { -+ this.a(block); -+ } -+ -+ this.die(); -+ return; -+ } -+ // Paper end - if (!this.world.isClientSide) { - blockposition = this.getChunkCoordinates(); - boolean flag = this.block.getBlock() instanceof BlockConcretePowder; -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -0,0 +0,0 @@ public class EntityTNTPrimed extends Entity { - } - - this.move(EnumMoveType.SELF, this.getMot()); -+ // Paper start - Configurable TNT entity height nerf -+ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { -+ this.die(); -+ return; -+ } -+ // Paper end - this.setMot(this.getMot().a(0.98D)); - if (this.onGround) { - this.setMot(this.getMot().d(0.7D, -0.5D, 0.7D)); -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartTNT.java -@@ -0,0 +0,0 @@ public class EntityMinecartTNT extends EntityMinecartAbstract { - public void tick() { - super.tick(); - if (this.b > 0) { -+ // Paper start - Configurable TNT entity height nerf -+ if (this.world.paperConfig.entityTNTHeightNerf != 0 && this.locY() > this.world.paperConfig.entityTNTHeightNerf) { -+ this.die(); -+ return; -+ } -+ // Paper end - --this.b; - this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); - } else if (this.b == 0) { diff --git a/Spigot-Server-Patches/Duplicate-UUID-Resolve-Option.patch b/Spigot-Server-Patches/Duplicate-UUID-Resolve-Option.patch deleted file mode 100644 index 935a07d801..0000000000 --- a/Spigot-Server-Patches/Duplicate-UUID-Resolve-Option.patch +++ /dev/null @@ -1,249 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 21 Jul 2018 14:27:34 -0400 -Subject: [PATCH] Duplicate UUID Resolve Option - -Due to a bug in https://github.com/PaperMC/Paper/commit/2e29af3df05ec0a383f48be549d1c03200756d24 -which was added all the way back in March of 2016, it was unknown (potentially not at the time) -that an entity might actually change the seed of the random object. - -At some point, EntitySquid did start setting the seed. Due to this shared random, this caused -every entity to use a Random object with a predictable seed. - -This has caused entities to potentially generate with the same UUID.... - -Over the years, servers have had entities disappear, but no sign of trouble -because CraftBukkit removed the log lines indicating that something was wrong. - -We have fixed the root issue causing duplicate UUID's, however we now have chunk -files full of entities that have the same UUID as another entity! - -When these chunks load, the 2nd entity will not be added to the world correctly. - -If that chunk loads in a different order in the future, then it will reverse and the -missing one is now the one added to the world and not the other. This results in very -inconsistent entity behavior. - -This change allows you to recover any duplicate entity by generating a new UUID for it. -This also lets you delete them instead if you don't want to risk having new entities added to -the world that you previously did not see. - -But for those who are ok with leaving this inconsistent behavior, you may use WARN or NOTHING options. - -It is recommended you regenerate the entities, as these were legit entities, and deserve your love. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void preventMovingIntoUnloadedChunks() { - preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); - } -+ -+ public enum DuplicateUUIDMode { -+ SAFE_REGEN, DELETE, NOTHING, WARN -+ } -+ public DuplicateUUIDMode duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ public int duplicateUUIDDeleteRange = 32; -+ private void repairDuplicateUUID() { -+ String desiredMode = getString("duplicate-uuid-resolver", "saferegen").toLowerCase().trim(); -+ duplicateUUIDDeleteRange = getInt("duplicate-uuid-saferegen-delete-range", duplicateUUIDDeleteRange); -+ switch (desiredMode.toLowerCase()) { -+ case "regen": -+ case "regenerate": -+ case "saferegen": -+ case "saferegenerate": -+ duplicateUUIDMode = DuplicateUUIDMode.SAFE_REGEN; -+ log("Duplicate UUID Resolve: Regenerate New UUID if distant (Delete likely duplicates within " + duplicateUUIDDeleteRange + " blocks)"); -+ break; -+ case "remove": -+ case "delete": -+ duplicateUUIDMode = DuplicateUUIDMode.DELETE; -+ log("Duplicate UUID Resolve: Delete Entity"); -+ break; -+ case "silent": -+ case "nothing": -+ duplicateUUIDMode = DuplicateUUIDMode.NOTHING; -+ logError("Duplicate UUID Resolve: Do Nothing (no logs) - Warning, may lose indication of bad things happening"); -+ break; -+ case "log": -+ case "warn": -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ default: -+ duplicateUUIDMode = DuplicateUUIDMode.WARN; -+ logError("Warning: Invalid duplicate-uuid-resolver config " + desiredMode + " - must be one of: regen, delete, nothing, warn"); -+ log("Duplicate UUID Resolve: Warn (do nothing but log it happened, may be spammy)"); -+ break; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.level; - - import co.aikar.timings.Timing; // Paper -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; - import com.google.common.collect.ComparisonChain; // Paper -@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.io.File; - import java.io.IOException; - import java.io.Writer; -+import java.util.HashMap; // Paper - import java.util.Collection; - import java.util.Iterator; - import java.util.List; -+import java.util.Map; // Paper - import java.util.Objects; - import java.util.Optional; - import java.util.Queue; - import java.util.Set; - import java.util.concurrent.CancellationException; -+import java.util.UUID; // Paper - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.CompletionException; - import java.util.concurrent.Executor; -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.GameRules; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkConverter; - import net.minecraft.world.level.chunk.ChunkGenerator; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (chunk.needsDecoration) { - net.minecraft.server.dedicated.DedicatedServer server = this.world.getServer().getServer(); - if (!server.getSpawnNPCs() && entity instanceof net.minecraft.world.entity.npc.NPC) { -- entity.die(); -+ entity.dead = true; // Paper - needsRemoval = true; - } - - if (!server.getSpawnAnimals() && (entity instanceof net.minecraft.world.entity.animal.EntityAnimal || entity instanceof net.minecraft.world.entity.animal.EntityWaterAnimal)) { -- entity.die(); -+ entity.dead = true; // Paper - needsRemoval = true; - } - } -- -- if (!(entity instanceof EntityHuman) && (needsRemoval || !this.world.addEntityChunk(entity))) { -- // CraftBukkit end -+ // CraftBukkit end -+ checkDupeUUID(entity); // Paper -+ if (!(entity instanceof EntityHuman) && (entity.dead || !this.world.addEntityChunk(entity))) { // Paper - if (list == null) { - list = Lists.newArrayList(new Entity[]{entity}); - } else { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - } - -+ // Paper start -+ private void checkDupeUUID(Entity entity) { -+ PaperWorldConfig.DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode; -+ if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN -+ && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE -+ && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { -+ return; -+ } -+ Entity other = world.getEntity(entity.getUniqueID()); -+ -+ if (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.dead -+ && Objects.equals(other.getSaveID(), entity.getSaveID()) -+ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < world.paperConfig.duplicateUUIDDeleteRange -+ ) { -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + " because it was near the duplicate and likely an actual duplicate. See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.dead = true; -+ return; -+ } -+ if (other != null && !other.dead) { -+ switch (mode) { -+ case SAFE_REGEN: { -+ entity.setUUID(UUID.randomUUID()); -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", regenerated UUID for " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ case DELETE: { -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", deleted entity " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ entity.dead = true; -+ break; -+ } -+ default: -+ if (World.DEBUG_ENTITIES) LOGGER.warn("[DUPE-UUID] Duplicate UUID found used by " + other + ", doing nothing to " + entity + ". See https://github.com/PaperMC/Paper/issues/1223 for discussion on what this is about."); -+ break; -+ } -+ } -+ } -+ // Paper end -+ - public CompletableFuture> a(PlayerChunk playerchunk) { - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - CompletableFuture, PlayerChunk.Failure>> completablefuture = this.a(chunkcoordintpair, 1, (i) -> { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; - import co.aikar.timings.TimingHistory; // Paper - import co.aikar.timings.Timings; // Paper -+ -+import com.destroystokyo.paper.PaperWorldConfig; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity1 == null) { - return false; - } else { -+ // Paper start -+ if (entity1.dead) { -+ unregisterEntity(entity1); // remove the existing entity -+ return false; -+ } -+ // Paper end - WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper -+ // Paper start -+ if (DEBUG_ENTITIES && entity.world.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { -+ if (entity1.addedToWorldStack != null) { -+ entity1.addedToWorldStack.printStackTrace(); -+ } -+ -+ getAddToWorldStackTrace(entity).printStackTrace(); -+ } -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - }); - } - -+ public final void setUUID(UUID uuid) { a_(uuid); } // Paper - OBFHELPER - public void a_(UUID uuid) { - this.uniqueID = uuid; - this.ae = this.uniqueID.toString(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - if (i != this.loc.x || j != this.loc.z) { - Chunk.LOGGER.warn("Wrong location! ({}, {}) should be ({}, {}), {}", i, j, this.loc.x, this.loc.z, entity); - entity.dead = true; -+ return; // Paper - } - - int k = MathHelper.floor(entity.locY() / 16.0D); diff --git a/Spigot-Server-Patches/Empty-commands-shall-not-be-dispatched.patch b/Spigot-Server-Patches/Empty-commands-shall-not-be-dispatched.patch deleted file mode 100644 index 6d12505db1..0000000000 --- a/Spigot-Server-Patches/Empty-commands-shall-not-be-dispatched.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 6 Jan 2021 23:38:43 +0100 -Subject: [PATCH] Empty commands shall not be dispatched - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -0,0 +0,0 @@ public class CommandDispatcher { - command = event.getCommand(); - - String[] args = command.split(" "); -+ if (args.length == 0) return 0; // Paper - empty commands shall not be dispatched - - String cmd = args[0]; - if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length()); diff --git a/Spigot-Server-Patches/EnderDragon-Events.patch b/Spigot-Server-Patches/EnderDragon-Events.patch deleted file mode 100644 index 0d80801733..0000000000 --- a/Spigot-Server-Patches/EnderDragon-Events.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:51:27 -0500 -Subject: [PATCH] EnderDragon Events - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -@@ -0,0 +0,0 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - this.d.setDuration(200); - this.d.setParticle(Particles.DRAGON_BREATH); - this.d.addEffect(new MobEffect(MobEffects.HARM)); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.a.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.d.getBukkitEntity()).callEvent()) { // Paper - this.a.world.addEntity(this.d); -+ } else { -+ this.removeAreaEffect(); -+ } - } - - } -@@ -0,0 +0,0 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - ++this.c; - } - -- @Override -- public void e() { -+ public final void removeAreaEffect() { this.e(); } // Paper - OBFHELPER -+ @Override public void e() { - if (this.d != null) { - this.d.die(); - this.d = null; -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerStrafe.java -@@ -0,0 +0,0 @@ public class DragonControllerStrafe extends AbstractDragonController { - EntityDragonFireball entitydragonfireball = new EntityDragonFireball(this.a.world, this.a, d9, d10, d11); - - entitydragonfireball.setPositionRotation(d6, d7, d8, 0.0F, 0.0F); -+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) a.getBukkitEntity(), (org.bukkit.entity.DragonFireball) entitydragonfireball.getBukkitEntity()).callEvent()) // Paper - this.a.world.addEntity(entitydragonfireball); -+ else entitydragonfireball.die(); // Paper - this.c = 0; - if (this.d != null) { - while (!this.d.c()) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityDragonFireball.java -@@ -0,0 +0,0 @@ public class EntityDragonFireball extends EntityFireball { - } - } - -+ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(EntityLiving::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) entityareaeffectcloud.getBukkitEntity()).callEvent()) { // Paper - this.world.triggerEffect(2006, this.getChunkCoordinates(), this.isSilent() ? -1 : 1); - this.world.addEntity(entityareaeffectcloud); -+ } else entityareaeffectcloud.die(); // Paper - this.die(); - } - diff --git a/Spigot-Server-Patches/Enderman.teleportRandomly.patch b/Spigot-Server-Patches/Enderman.teleportRandomly.patch deleted file mode 100644 index a23005b1f7..0000000000 --- a/Spigot-Server-Patches/Enderman.teleportRandomly.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:29:44 -0400 -Subject: [PATCH] Enderman.teleportRandomly() - -Ability to trigger the vanilla "teleport randomly" mechanic of an enderman. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - super.mobTick(); - } - -+ public final boolean teleportRandomly() { return this.eL(); } // Paper - OBFHELPER - protected boolean eL() { - if (!this.world.s_() && this.isAlive()) { - double d0 = this.locX() + (this.random.nextDouble() - 0.5D) * 64.0D; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -@@ -0,0 +0,0 @@ public class CraftEnderman extends CraftMonster implements Enderman { - super(server, entity); - } - -+ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper - @Override - public MaterialData getCarriedMaterial() { - IBlockData blockData = getHandle().getCarried(); diff --git a/Spigot-Server-Patches/EndermanAttackPlayerEvent.patch b/Spigot-Server-Patches/EndermanAttackPlayerEvent.patch deleted file mode 100644 index de2055282d..0000000000 --- a/Spigot-Server-Patches/EndermanAttackPlayerEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 May 2018 20:18:54 -0400 -Subject: [PATCH] EndermanAttackPlayerEvent - -Allow control over whether or not an enderman aggros a player. - -This allows you to override/extend the pumpkin/stare logic. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - this.a((WorldServer) this.world, nbttagcompound); - } - -+ // Paper start - OBFHELPER - ok not really, but verify this on updates - private boolean g(EntityHuman entityhuman) { -+ boolean shouldAttack = g_real(entityhuman); -+ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) entityhuman.getBukkitEntity()); -+ event.setCancelled(!shouldAttack); -+ return event.callEvent(); -+ } -+ private boolean g_real(EntityHuman entityhuman) { -+ // Paper end - ItemStack itemstack = (ItemStack) entityhuman.inventory.armor.get(3); - - if (itemstack.getItem() == Blocks.CARVED_PUMPKIN.getItem()) { diff --git a/Spigot-Server-Patches/EndermanEscapeEvent.patch b/Spigot-Server-Patches/EndermanEscapeEvent.patch deleted file mode 100644 index 7f469747c7..0000000000 --- a/Spigot-Server-Patches/EndermanEscapeEvent.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 30 Apr 2018 13:15:55 -0400 -Subject: [PATCH] EndermanEscapeEvent - -Fires an event anytime an enderman intends to teleport away from the player - -You may cancel this, enabling ranged attacks to damage the enderman for example. - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -0,0 +0,0 @@ package net.minecraft.world.entity.monster; - - import java.util.EnumSet; - import java.util.Optional; -+import com.destroystokyo.paper.event.entity.EndermanEscapeEvent; // Paper - import java.util.Random; - import java.util.UUID; - import java.util.function.Predicate; -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - setGoalTarget(entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); - } - -+ // Paper start -+ private boolean tryEscape(EndermanEscapeEvent.Reason reason) { -+ return new EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); -+ } -+ // Paper end -+ - @Override - public boolean setGoalTarget(EntityLiving entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { - if (!super.setGoalTarget(entityliving, reason, fireEvent)) { -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - if (this.world.isDay() && this.ticksLived >= this.bs + 600) { - float f = this.aR(); - -- if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { -+ if (f > 0.5F && this.world.e(this.getChunkCoordinates()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper - this.setGoalTarget((EntityLiving) null); - this.eL(); - } -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - if (this.isInvulnerable(damagesource)) { - return false; - } else if (damagesource instanceof EntityDamageSourceIndirect) { -+ if (this.tryEscape(EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start - for (int i = 0; i < 64; ++i) { - if (this.eL()) { - return true; - } - } -+ } // Paper end - - return false; - } else { - boolean flag = super.damageEntity(damagesource, f); - -- if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0) { -+ if (!this.world.s_() && !(damagesource.getEntity() instanceof EntityLiving) && this.random.nextInt(10) != 0 && this.tryEscape(damagesource == DamageSource.DROWN ? EndermanEscapeEvent.Reason.DROWN : EndermanEscapeEvent.Reason.INDIRECT)) { // Paper - use to be critical hits as else, but mojang removed critical hits in 1.16.2 due to MC-185684 - this.eL(); - } - -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - - static class PathfinderGoalPlayerWhoLookedAtTarget extends PathfinderGoalNearestAttackableTarget { - -- private final EntityEnderman i; -+ private final EntityEnderman i; public final EntityEnderman getEnderman() { return this.i; } // Paper - OBFHELPER - private EntityHuman j; - private int k; - private int l; -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - } else { - if (this.c != null && !this.i.isPassenger()) { - if (this.i.g((EntityHuman) this.c)) { -- if (this.c.h((Entity) this.i) < 16.0D) { -+ if (this.c.h((Entity) this.i) < 16.0D && this.getEnderman().tryEscape(EndermanEscapeEvent.Reason.STARE)) { // Paper - this.i.eL(); - } - diff --git a/Spigot-Server-Patches/Enforce-Sync-Player-Saves.patch b/Spigot-Server-Patches/Enforce-Sync-Player-Saves.patch deleted file mode 100644 index e17331a33e..0000000000 --- a/Spigot-Server-Patches/Enforce-Sync-Player-Saves.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:41:58 -0500 -Subject: [PATCH] Enforce Sync Player Saves - -Saving players async is extremely dangerous. This will force it to main -the same way we handle async chunk loads. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.savePlayerFile((EntityPlayer) this.players.get(i)); - } - MinecraftTimings.savePlayers.stopTiming(); // Paper -+ return null; }); // Paper - ensure main - } - - public WhiteList getWhitelist() { diff --git a/Spigot-Server-Patches/Enhance-console-tab-completions-for-brigadier-comman.patch b/Spigot-Server-Patches/Enhance-console-tab-completions-for-brigadier-comman.patch deleted file mode 100644 index 80071ff2d5..0000000000 --- a/Spigot-Server-Patches/Enhance-console-tab-completions-for-brigadier-comman.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Tue, 30 Mar 2021 16:06:08 -0700 -Subject: [PATCH] Enhance console tab completions for brigadier commands - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void fixEntityPositionDesync() { - fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); - } -+ -+ public static boolean enableBrigadierConsoleHighlighting = true; -+ public static boolean enableBrigadierConsoleCompletions = true; -+ private static void consoleSettings() { -+ enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); -+ enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper.console; - -+import com.destroystokyo.paper.PaperConfig; -+import io.papermc.paper.console.BrigadierCommandHighlighter; - import net.minecraft.server.dedicated.DedicatedServer; - import net.minecrell.terminalconsole.SimpleTerminalConsole; - import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -@@ -0,0 +0,0 @@ public final class PaperConsole extends SimpleTerminalConsole { - - @Override - protected LineReader buildReader(LineReaderBuilder builder) { -- return super.buildReader(builder -+ builder - .appName("Paper") - .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) - .completer(new ConsoleCommandCompleter(this.server)) -- ); -+ .option(LineReader.Option.COMPLETE_IN_WORD, true); -+ if (PaperConfig.enableBrigadierConsoleHighlighting) { -+ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.getServerCommandListener())); -+ } -+ return super.buildReader(builder); - } - - @Override -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandCompleter.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.console; -+ -+import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion; -+import com.mojang.brigadier.CommandDispatcher; -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.StringReader; -+import com.mojang.brigadier.suggestion.Suggestion; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.minecraft.commands.CommandListenerWrapper; -+import net.minecraft.network.chat.ChatComponentUtils; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Candidate; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+ -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+ -+import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; -+ -+public final class BrigadierCommandCompleter { -+ private final CommandListenerWrapper commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ public void complete(final @NonNull LineReader reader, final @NonNull ParsedLine line, final @NonNull List candidates, final @NonNull List existing) { -+ if (!com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleCompletions) { -+ this.addCandidates(candidates, Collections.emptyList(), existing); -+ return; -+ } -+ final CommandDispatcher dispatcher = this.server.getCommandDispatcher().dispatcher(); -+ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); -+ this.addCandidates( -+ candidates, -+ dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), -+ existing -+ ); -+ } -+ -+ private void addCandidates( -+ final @NonNull List candidates, -+ final @NonNull List brigSuggestions, -+ final @NonNull List existing -+ ) { -+ final List completions = new ArrayList<>(); -+ brigSuggestions.forEach(it -> completions.add(toCompletion(it))); -+ for (final Completion completion : existing) { -+ if (completion.suggestion().isEmpty() || brigSuggestions.stream().anyMatch(it -> it.getText().equals(completion.suggestion()))) { -+ continue; -+ } -+ completions.add(completion); -+ } -+ for (final Completion completion : completions) { -+ if (completion.suggestion().isEmpty()) { -+ continue; -+ } -+ candidates.add(toCandidate(completion)); -+ } -+ } -+ -+ private static @NonNull Candidate toCandidate(final @NonNull Completion completion) { -+ final String suggestionText = completion.suggestion(); -+ final String suggestionTooltip = PaperAdventure.PLAIN.serializeOr(completion.tooltip(), null); -+ return new Candidate( -+ suggestionText, -+ suggestionText, -+ null, -+ suggestionTooltip, -+ null, -+ null, -+ false -+ ); -+ } -+ -+ private static @NonNull Completion toCompletion(final @NonNull Suggestion suggestion) { -+ if (suggestion.getTooltip() == null) { -+ return completion(suggestion.getText()); -+ } -+ return completion(suggestion.getText(), PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(suggestion.getTooltip()))); -+ } -+ -+ static @NonNull StringReader prepareStringReader(final @NonNull String line) { -+ final StringReader stringReader = new StringReader(line); -+ if (stringReader.canRead() && stringReader.peek() == '/') { -+ stringReader.skip(); -+ } -+ return stringReader; -+ } -+} -diff --git a/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/console/BrigadierCommandHighlighter.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.console; -+ -+import com.mojang.brigadier.ParseResults; -+import com.mojang.brigadier.context.ParsedCommandNode; -+import com.mojang.brigadier.tree.LiteralCommandNode; -+import net.minecraft.commands.CommandListenerWrapper; -+import net.minecraft.server.dedicated.DedicatedServer; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.jline.reader.Highlighter; -+import org.jline.reader.LineReader; -+import org.jline.utils.AttributedString; -+import org.jline.utils.AttributedStringBuilder; -+import org.jline.utils.AttributedStyle; -+ -+public final class BrigadierCommandHighlighter implements Highlighter { -+ private static final int[] COLORS = {AttributedStyle.CYAN, AttributedStyle.YELLOW, AttributedStyle.GREEN, AttributedStyle.MAGENTA, /* Client uses GOLD here, not BLUE, however there is no GOLD AttributedStyle. */ AttributedStyle.BLUE}; -+ private final CommandListenerWrapper commandSourceStack; -+ private final DedicatedServer server; -+ -+ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { -+ this.server = server; -+ this.commandSourceStack = commandSourceStack; -+ } -+ -+ @Override -+ public AttributedString highlight(final @NonNull LineReader reader, final @NonNull String buffer) { -+ final AttributedStringBuilder builder = new AttributedStringBuilder(); -+ final ParseResults results = this.server.getCommandDispatcher().dispatcher().parse(BrigadierCommandCompleter.prepareStringReader(buffer), this.commandSourceStack); -+ int pos = 0; -+ if (buffer.startsWith("/")) { -+ builder.append("/", AttributedStyle.DEFAULT); -+ pos = 1; -+ } -+ int component = -1; -+ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { -+ if (node.getRange().getStart() >= buffer.length()) { -+ break; -+ } -+ final int start = node.getRange().getStart(); -+ final int end = Math.min(node.getRange().getEnd(), buffer.length()); -+ builder.append(buffer.substring(pos, start), AttributedStyle.DEFAULT); -+ if (node.getNode() instanceof LiteralCommandNode) { -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT); -+ } else { -+ if (++component >= COLORS.length) { -+ component = 0; -+ } -+ builder.append(buffer.substring(start, end), AttributedStyle.DEFAULT.foreground(COLORS[component])); -+ } -+ pos = end; -+ } -+ if (pos < buffer.length()) { -+ builder.append((buffer.substring(pos)), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); -+ } -+ return builder.toAttributedString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -0,0 +0,0 @@ public class CommandDispatcher { - }; - } - -- public com.mojang.brigadier.CommandDispatcher a() { -+ public com.mojang.brigadier.CommandDispatcher a() { return this.dispatcher(); } public com.mojang.brigadier.CommandDispatcher dispatcher() { // Paper - OBFHELPER - return this.b; - } - -diff --git a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -+++ b/src/main/java/net/minecraft/network/chat/ChatComponentUtils.java -@@ -0,0 +0,0 @@ public class ChatComponentUtils { - ChatComponentText chatcomponenttext = new ChatComponentText(""); - boolean flag = true; - -- for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { -+ for (Iterator iterator = collection.iterator(); iterator.hasNext(); flag = false) { // Paper - decompile fix - T t0 = iterator.next(); - - if (!flag) { -@@ -0,0 +0,0 @@ public class ChatComponentUtils { - return new ChatMessage("chat.square_brackets", new Object[]{ichatbasecomponent}); - } - -- public static IChatBaseComponent a(Message message) { -+ public static IChatBaseComponent a(Message message) { return fromMessage(message); } public static IChatBaseComponent fromMessage(final @org.checkerframework.checker.nullness.qual.NonNull Message message) { // Paper - OBFHELPER - return (IChatBaseComponent) (message instanceof IChatBaseComponent ? (IChatBaseComponent) message : new ChatComponentText(message.getString())); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -0,0 +0,0 @@ import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { - private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer -+ private final io.papermc.paper.console.BrigadierCommandCompleter brigadierCompleter; // Paper - - public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; -+ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.getServerCommandListener()); // Paper - } - - // Paper start - Change method signature for JLine update -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - } - } - -- if (!completions.isEmpty()) { -+ if (false && !completions.isEmpty()) { - for (final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion completion : completions) { - if (completion.suggestion().isEmpty()) { - continue; -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - )); - } - } -+ this.addCompletions(reader, line, candidates, completions); - return; - } - -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - try { - List offers = waitable.get(); - if (offers == null) { -+ this.addCompletions(reader, line, candidates, Collections.emptyList()); // Paper - return; // Paper - Method returns void - } - - // Paper start - JLine update -+ /* - for (String completion : offers) { - if (completion.isEmpty()) { - continue; -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - - candidates.add(new Candidate(completion)); - } -+ */ -+ this.addCompletions(reader, line, candidates, offers.stream().map(com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion::completion).collect(java.util.stream.Collectors.toList())); - // Paper end - - // Paper start - JLine handles cursor now -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - } - return false; - } -+ -+ private void addCompletions(final LineReader reader, final ParsedLine line, final List candidates, final List existing) { -+ this.brigadierCompleter.complete(reader, line, candidates, existing); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Ensure-Entity-AABB-s-are-never-invalid.patch b/Spigot-Server-Patches/Ensure-Entity-AABB-s-are-never-invalid.patch deleted file mode 100644 index ccd8e7ef53..0000000000 --- a/Spigot-Server-Patches/Ensure-Entity-AABB-s-are-never-invalid.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:12:46 -0400 -Subject: [PATCH] Ensure Entity AABB's are never invalid - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.animal.EntityAnimal; - import net.minecraft.world.entity.animal.EntityFish; -+import net.minecraft.world.entity.decoration.EntityHanging; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - public void setPosition(double d0, double d1, double d2) { - this.setPositionRaw(d0, d1, d2); -- this.a(this.size.a(d0, d1, d2)); -+ //this.a(this.size.a(d0, d1, d2)); // Paper - move into setPositionRaw - if (valid) ((WorldServer) world).chunkCheck(this); // CraftBukkit - } - -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return new AxisAlignedBB(vec3d, vec3d1); - } - -+ public final void setBoundingBox(AxisAlignedBB axisalignedbb) { a(axisalignedbb); } // Paper - OBFHELPER - public void a(AxisAlignedBB axisalignedbb) { - // CraftBukkit start - block invalid bounding boxes - double minX = axisalignedbb.minX, -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void setPositionRaw(double d0, double d1, double d2) { -+ // Paper start - never allow AABB to become desynced from position -+ // hanging has its own special logic -+ if (!(this instanceof EntityHanging) && (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2)) { -+ this.setBoundingBox(this.size.a(d0, d1, d2)); -+ } -+ // Paper end - if (this.loc.x != d0 || this.loc.y != d1 || this.loc.z != d2) { - this.loc = new Vec3D(d0, d1, d2); - int i = MathHelper.floor(d0); diff --git a/Spigot-Server-Patches/Ensure-Entity-is-never-double-registered.patch b/Spigot-Server-Patches/Ensure-Entity-is-never-double-registered.patch deleted file mode 100644 index f17b592600..0000000000 --- a/Spigot-Server-Patches/Ensure-Entity-is-never-double-registered.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 29 Mar 2020 18:26:14 -0400 -Subject: [PATCH] Ensure Entity is never double registered - -If something calls register twice, and the world is ticking, it could be -enqueued to add twice. - -Vs behavior of non ticking of just overwriting state. - -We will now simply log a warning when this happens instead of crashing the server. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - Entity entity2; - - while ((entity2 = (Entity) this.entitiesToAdd.poll()) != null) { -+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers - this.registerEntity(entity2); - } - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - public void unregisterEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot -+ // Paper start - fix entity registration issues -+ if (entity instanceof EntityComplexPart) { -+ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways -+ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. -+ this.entitiesById.remove(entity.getId(), entity); -+ return; -+ } -+ if (!entity.valid) { -+ // Someone called remove before we ever got added, cancel the add. -+ entity.isQueuedForRegister = false; -+ return; -+ } -+ // Paper end - // Spigot start - if ( entity instanceof EntityHuman ) - { -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void registerEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot -+ // Paper start - don't double enqueue entity registration -+ //noinspection ObjectEquality -+ if (this.entitiesById.get(entity.getId()) == entity) { -+ LOGGER.error(entity + " was already registered!"); -+ new Throwable().printStackTrace(); -+ return; -+ } -+ // Paper end - if (this.tickingEntities) { -- this.entitiesToAdd.add(entity); -+ if (!entity.isQueuedForRegister) { // Paper -+ this.entitiesToAdd.add(entity); -+ entity.isQueuedForRegister = true; // Paper -+ } - } else { -+ entity.isQueuedForRegister = false; // Paper - this.entitiesById.put(entity.getId(), entity); - if (entity instanceof EntityEnderDragon) { - EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ(); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - // Paper start -+ public boolean isQueuedForRegister = false; - public static Random SHARED_RANDOM = new Random() { - private boolean locked = false; - @Override diff --git a/Spigot-Server-Patches/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/Spigot-Server-Patches/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch deleted file mode 100644 index c105af6116..0000000000 --- a/Spigot-Server-Patches/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 9 May 2020 02:01:48 -0400 -Subject: [PATCH] Ensure EntityRaider respects game and entity rules for - picking up items - - -diff --git a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -+++ b/src/main/java/net/minecraft/world/entity/raid/EntityRaider.java -@@ -0,0 +0,0 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { - - public class b extends PathfinderGoal { - -- private final T b; -+ private final T b; private T getRaider() { return b; } // Paper - obfhelper - - public b(T entityraider) { // CraftBukkit - decompile error - this.b = entityraider; -@@ -0,0 +0,0 @@ public abstract class EntityRaider extends EntityMonsterPatrolling { - - @Override - public boolean a() { -+ if (!getRaider().world.getGameRules().getBoolean(GameRules.MOB_GRIEFING) || !getRaider().canPickupLoot()) return false; // Paper - respect game and entity rules for picking up items - Raid raid = this.b.fa(); - - if (this.b.fb() && !this.b.fa().a() && this.b.eN() && !ItemStack.matches(this.b.getEquipment(EnumItemSlot.HEAD), Raid.s())) { diff --git a/Spigot-Server-Patches/Ensure-commands-are-not-ran-async.patch b/Spigot-Server-Patches/Ensure-commands-are-not-ran-async.patch deleted file mode 100644 index 3c2d0809c3..0000000000 --- a/Spigot-Server-Patches/Ensure-commands-are-not-ran-async.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 01:17:12 -0600 -Subject: [PATCH] Ensure commands are not ran async - -Plugins calling Player.chat("/foo") or Server.dispatchCommand() could -trigger the server to execute a command while on another thread. - -These commands would then process EXPECTING to be on the main thread, leaving to -very hard to trace concurrency issues. - -This change will synchronize the command execution back to the main thread, causing a -big slowdown in execution but throwing an exception at same time to raise awareness -that it is happening so that plugin authors can fix their code to stop executing commands async. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (!async && s.startsWith("/")) { -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !org.bukkit.Bukkit.isPrimaryThread()) { -+ final String fCommandLine = s; -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine); -+ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ Waitable wait = new Waitable() { -+ @Override -+ protected Object evaluate() { -+ chat(fCommandLine, false); -+ return null; -+ } -+ }; -+ minecraftServer.processQueue.add(wait); -+ try { -+ wait.get(); -+ return; -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing chat command", e.getCause()); -+ } -+ } -+ // Paper End - this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { - // Do nothing, this is coming from a plugin -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - Validate.notNull(commandLine, "CommandLine cannot be null"); - org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot - -+ // Paper Start -+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !Bukkit.isPrimaryThread()) { -+ final CommandSender fSender = sender; -+ final String fCommandLine = commandLine; -+ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine); -+ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable()); -+ org.bukkit.craftbukkit.util.Waitable wait = new org.bukkit.craftbukkit.util.Waitable() { -+ @Override -+ protected Boolean evaluate() { -+ return dispatchCommand(fSender, fCommandLine); -+ } -+ }; -+ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on! -+ } catch (Exception e) { -+ throw new RuntimeException("Exception processing dispatch command", e.getCause()); -+ } -+ } -+ // Paper End -+ - if (commandMap.dispatch(sender, commandLine)) { - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -0,0 +0,0 @@ public class ServerShutdownThread extends Thread { - public void run() { - try { - org.spigotmc.AsyncCatcher.enabled = false; // Spigot -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - server.close(); - } finally { - try { -diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/AsyncCatcher.java -+++ b/src/main/java/org/spigotmc/AsyncCatcher.java -@@ -0,0 +0,0 @@ public class AsyncCatcher - { - - public static boolean enabled = true; -+ public static boolean shuttingDown = false; // Paper - - public static void catchOp(String reason) - { -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -0,0 +0,0 @@ public class RestartCommand extends Command - private static void restart(final String restartScript) - { - AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - try - { - String[] split = restartScript.split( " " ); diff --git a/Spigot-Server-Patches/Ensure-inv-drag-is-in-bounds.patch b/Spigot-Server-Patches/Ensure-inv-drag-is-in-bounds.patch deleted file mode 100644 index 4b3dbbdee9..0000000000 --- a/Spigot-Server-Patches/Ensure-inv-drag-is-in-bounds.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Joseph Hirschfeld -Date: Thu, 3 Mar 2016 02:33:53 -0600 -Subject: [PATCH] Ensure inv drag is in bounds - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -0,0 +0,0 @@ public abstract class Container { - this.d(); - } - } else if (this.h == 1) { -- Slot slot = (Slot) this.slots.get(i); -+ Slot slot = i < this.slots.size() ? this.slots.get(i) : null; // Paper - Ensure drag in bounds - - itemstack1 = playerinventory.getCarried(); - if (slot != null && a(slot, itemstack1, true) && slot.isAllowed(itemstack1) && (this.dragType == 2 || itemstack1.getCount() > this.i.size()) && this.b(slot)) { diff --git a/Spigot-Server-Patches/Ensure-safe-gateway-teleport.patch b/Spigot-Server-Patches/Ensure-safe-gateway-teleport.patch deleted file mode 100644 index 195a92603b..0000000000 --- a/Spigot-Server-Patches/Ensure-safe-gateway-teleport.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 15 May 2020 01:10:03 -0400 -Subject: [PATCH] Ensure safe gateway teleport - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -0,0 +0,0 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - } else if (!this.world.isClientSide) { - List list = this.world.a(Entity.class, new AxisAlignedBB(this.getPosition()), TileEntityEndGateway::a); - -- if (!list.isEmpty()) { -- this.b((Entity) list.get(this.world.random.nextInt(list.size()))); -+ // Paper start -+ for (Entity entity : list) { -+ if (entity.canPortal()) { -+ this.b(entity); -+ break; -+ } - } -+ // Paper end - - if (this.age % 2400L == 0L) { - this.h(); diff --git a/Spigot-Server-Patches/Entity-Activation-Range-2.0.patch b/Spigot-Server-Patches/Entity-Activation-Range-2.0.patch deleted file mode 100644 index ae6c74636f..0000000000 --- a/Spigot-Server-Patches/Entity-Activation-Range-2.0.patch +++ /dev/null @@ -1,869 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 13 May 2016 01:38:06 -0400 -Subject: [PATCH] Entity Activation Range 2.0 - -Optimizes performance of Activation Range - -Adds many new configurations and a new wake up inactive system - -Fixes and adds new Immunities to improve gameplay behavior - -Adds water Mobs to activation range config and nerfs fish -Adds flying monsters to control ghast and phantoms -Adds villagers as separate config - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - ++TimingHistory.entityTicks; // Paper - timings - // Spigot start - co.aikar.timings.Timing timer; // Paper -- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { -+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below - entity.ticksLived++; - timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); - } finally { timer.stopTiming(); } // Paper - return; -- } -+ }*/ // Paper - comment out EAR 2 - // Spigot end - // Paper start- timings -- TimingHistory.activatedEntityTicks++; -- timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -+ timer = isActive ? entity.getEntityType().tickTimer.startTiming() : entity.getEntityType().inactiveTickTimer.startTiming(); // Paper - try { - // Paper end - timings - entity.g(entity.locX(), entity.locY(), entity.locZ()); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return IRegistry.ENTITY_TYPE.getKey(entity.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickNonPassenger"); -+ if (isActive) { // Paper - EAR 2 -+ TimingHistory.activatedEntityTicks++; // Paper - entity.tick(); - entity.postTick(); // CraftBukkit -+ } else { entity.inactiveTick(); } // Paper - EAR 2 - gameprofilerfiller.exit(); - } - - this.chunkCheck(entity); -+ } finally { timer.stopTiming(); } // Paper - timings - if (entity.inChunk) { - Iterator iterator = entity.getPassengers().iterator(); - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.a(entity, entity1); - } - } -- } finally { timer.stopTiming(); } // Paper - timings -+ //} finally { timer.stopTiming(); } // Paper - timings - move up - - } - } -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public void a(Entity entity, Entity entity1) { - if (!entity1.dead && entity1.getVehicle() == entity) { - if (entity1 instanceof EntityHuman || this.getChunkProvider().a(entity1)) { -+ // Paper - EAR 2 -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity1); -+ co.aikar.timings.Timing timer = isActive ? entity1.getEntityType().passengerTickTimer.startTiming() : entity1.getEntityType().passengerInactiveTickTimer.startTiming(); // Paper -+ try { -+ // Paper end - entity1.g(entity1.locX(), entity1.locY(), entity1.locZ()); - entity1.lastYaw = entity1.yaw; - entity1.lastPitch = entity1.pitch; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return IRegistry.ENTITY_TYPE.getKey(entity1.getEntityType()).toString(); - }); - gameprofilerfiller.c("tickPassenger"); -+ // Paper start - EAR 2 -+ if (isActive) { - entity1.passengerTick(); - entity1.postTick(); // CraftBukkit -+ } else { -+ entity1.setMot(Vec3D.ORIGIN); -+ entity1.inactiveTick(); -+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary -+ entity.syncPositionOf(entity1); -+ } -+ // Paper end - EAR 2 - gameprofilerfiller.exit(); - } - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - this.a(entity1, entity2); - } -- } -+ } } finally { timer.stopTiming(); } // Paper - EAR2 timings - - } - } else { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.animal.EntityFish; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -+import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.EnchantmentProtection; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public boolean Y; - public boolean impulse; - public int portalCooldown; -- protected boolean inPortal; -+ public boolean inPortal; // Paper - public - protected int portalTicks; - protected BlockPosition ac; - private boolean invulnerable; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean isTemporarilyActive = false; // Paper - public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.recalcPosition(); - } else { - if (enummovetype == EnumMoveType.PISTON) { -+ this.activatedTick = MinecraftServer.currentTick + 20; // Paper - vec3d = this.b(vec3d); - if (vec3d.equals(Vec3D.ORIGIN)) { - return; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.x = Vec3D.ORIGIN; - this.setMot(Vec3D.ORIGIN); - } -+ // Paper start - ignore movement changes while inactive. -+ if (isTemporarilyActive && !(this instanceof EntityItem || this instanceof EntityMinecartAbstract) && vec3d == getMot() && enummovetype == EnumMoveType.SELF) { -+ setMot(Vec3D.ORIGIN); -+ this.world.getMethodProfiler().exit(); -+ return; -+ } -+ // Paper end - - vec3d = this.a(vec3d, enummovetype); - Vec3D vec3d1 = this.g(vec3d); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - } - -+ public void syncPositionOf(Entity entity) { k(entity); } // Paper - OBFHELPER - public void k(Entity entity) { - this.a(entity, Entity::setPosition); - } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return this.ae; - } - -+ public final boolean isPushedByWater() { return this.bV(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! - public boolean bV() { - // Paper start - return this.pushedByWater(); -diff --git a/src/main/java/net/minecraft/world/entity/EntityCreature.java b/src/main/java/net/minecraft/world/entity/EntityCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityCreature.java -+++ b/src/main/java/net/minecraft/world/entity/EntityCreature.java -@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityUnleashEvent; - public abstract class EntityCreature extends EntityInsentient { - - public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper -+ public BlockPosition movingTarget = null; public BlockPosition getMovingTarget() { return movingTarget; } // Paper - - protected EntityCreature(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - public MinecraftKey lootTableKey; - public long lootTableSeed; - @Nullable -- private Entity leashHolder; -+ public Entity leashHolder; // Paper - private -> public - private int bx; - @Nullable - private NBTTagCompound by; -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - return this.lookController; - } - -+ // Paper start -+ @Override -+ public void inactiveTick() { -+ super.inactiveTick(); -+ if (this.goalSelector.inactiveTick()) { -+ this.goalSelector.doTick(); -+ } -+ if (this.targetSelector.inactiveTick()) { -+ this.targetSelector.doTick(); -+ } -+ } -+ // Paper end -+ - public ControllerMove getControllerMove() { - if (this.isPassenger() && this.getVehicle() instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) this.getVehicle(); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - protected float aN; - protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER - public float lastDamage; -- protected boolean jumping; -+ public boolean jumping; // Paper protected -> public - public float aR; - public float aS; - public float aT; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -0,0 +0,0 @@ public abstract class PathfinderGoal { - - public void c() {} - -- public void d() {} -+ public void d() { -+ onTaskReset(); // Paper -+ } -+ public void onTaskReset() {} // Paper - - public void e() {} - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.IWorldReader; - - public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - -- protected final EntityCreature a; -+ protected final EntityCreature a;public EntityCreature getEntity() { return a; } // Paper - OBFHELPER - public final double b; - protected int c; - protected int d; - private int g; -- protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER -+ protected BlockPosition e; public final BlockPosition getTargetPosition() { return this.e; } public void setTargetPosition(BlockPosition pos) { this.e = pos; getEntity().movingTarget = pos != BlockPosition.ZERO ? pos : null; } // Paper - OBFHELPER - private boolean h; - private final int i; - private final int j; -@@ -0,0 +0,0 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i) { - this(entitycreature, d0, i, 1); - } -+ // Paper start - activation range improvements -+ @Override -+ public void onTaskReset() { -+ super.onTaskReset(); -+ setTargetPosition(BlockPosition.ZERO); -+ } -+ // Paper end - - public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i, int j) { - this.e = BlockPosition.ZERO; -@@ -0,0 +0,0 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, i1, k - 1, j1); - if (this.a.a((BlockPosition) blockposition_mutableblockposition) && this.a(this.a.world, blockposition_mutableblockposition)) { - this.e = blockposition_mutableblockposition; -+ setTargetPosition(blockposition_mutableblockposition.immutableCopy()); // Paper - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - } - }; - private final Map c = new EnumMap(PathfinderGoal.Type.class); -- private final Set d = Sets.newLinkedHashSet(); -+ private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER - private final Supplier e; - private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); -- private int g = 3; -+ private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER -+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - - public PathfinderGoalSelector(Supplier supplier) { - this.e = supplier; -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); - } - -+ // Paper start -+ public boolean inactiveTick() { -+ incRate(); -+ return getCurRate() % getTickRate() == 0; -+ } -+ public boolean hasTasks() { -+ for (PathfinderGoalWrapped task : getTasks()) { -+ if (task.isRunning()) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end -+ - public void a(PathfinderGoal pathfindergoal) { - this.d.stream().filter((pathfindergoalwrapped) -> { - return pathfindergoalwrapped.j() == pathfindergoal; -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -0,0 +0,0 @@ public class PathfinderGoalWrapped extends PathfinderGoal { - return this.a.i(); - } - -+ public boolean isRunning() { return this.g(); } // Paper - OBFHELPER - public boolean g() { - return this.c; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityLlama.java -@@ -0,0 +0,0 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn - return this.bC != null; - } - -+ public final boolean inCaravan() { return this.fC(); } // Paper - OBFHELPER - public boolean fC() { - return this.bB != null; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - @Override - public void inactiveTick() { - // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( -- if (world.spigotConfig.tickInactiveVillagers && this.doAITick()) { -- this.mobTick(); -+ // Paper start -+ if (this.getUnhappy() > 0) { -+ this.setUnhappy(this.getUnhappy() - 1); - } -+ if (this.doAITick()) { -+ if (world.spigotConfig.tickInactiveVillagers) { -+ this.mobTick(); -+ } else { -+ this.mobTick(true); -+ } -+ } -+ doReputationTick(); -+ // Paper end -+ - super.inactiveTick(); - } - // Spigot End - - @Override -- protected void mobTick() { -+ protected void mobTick() { mobTick(false); } -+ protected void mobTick(boolean inactive) { - this.world.getMethodProfiler().enter("villagerBrain"); -- this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error -+ if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper - this.world.getMethodProfiler().exit(); - if (this.bF) { - this.bF = false; -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - this.bv = null; - } - -- if (!this.isNoAI() && this.random.nextInt(100) == 0) { -+ if (!inactive && !this.isNoAI() && this.random.nextInt(100) == 0) { // Paper - Raid raid = ((WorldServer) this.world).b_(this.getChunkCoordinates()); - - if (raid != null && raid.v() && !raid.a()) { -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.eN()) { - this.eT(); - } -+ if (inactive) return; // Paper - - super.mobTick(); - } -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - } - -+ private void doReputationTick() { fw(); } // Paper - OBFHELPER - private void fw() { - long i = this.world.getTime(); - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return super.prepare(worldaccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound); - } - -+ public final int getUnhappy() { return eK(); } // Paper - OBFHELPER - public int eK() { - return (Integer) this.datawatcher.get(EntityVillagerAbstract.bp); - } - -+ public final void setUnhappy(int i) { s(i); } // Paper - OBFHELPER - public void s(int i) { - this.datawatcher.set(EntityVillagerAbstract.bp, i); - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public long ticksPerWaterSpawns; - public long ticksPerWaterAmbientSpawns; - public long ticksPerAmbientSpawns; -+ // Paper start -+ public int wakeupInactiveRemainingAnimals; -+ public int wakeupInactiveRemainingFlying; -+ public int wakeupInactiveRemainingMonsters; -+ public int wakeupInactiveRemainingVillagers; -+ // Paper end - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.phys.AxisAlignedBB; - import co.aikar.timings.MinecraftTimings; - -+// Paper start -+import net.minecraft.core.BlockPosition; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.world.entity.EntityFlying; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.BehaviorController; -+import net.minecraft.world.entity.animal.EntityBee; -+import net.minecraft.world.entity.animal.EntityWaterAnimal; -+import net.minecraft.world.entity.animal.horse.EntityLlama; -+import net.minecraft.world.entity.monster.EntityPillager; -+import net.minecraft.world.entity.monster.IMonster; -+import net.minecraft.world.entity.schedule.Activity; -+import net.minecraft.world.entity.item.EntityFallingBlock; -+import net.minecraft.world.entity.projectile.EntityEnderSignal; -+// Paper end -+ - public class ActivationRange - { - - public enum ActivationType - { -+ WATER, // Paper -+ FLYING_MONSTER, // Paper -+ VILLAGER, // Paper - MONSTER, - ANIMAL, - RAIDER, -@@ -0,0 +0,0 @@ public class ActivationRange - - AxisAlignedBB boundingBox = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); - } -+ // Paper start -+ -+ static Activity[] VILLAGER_PANIC_IMMUNITIES = { -+ Activity.HIDE, -+ Activity.PRE_RAID, -+ Activity.RAID, -+ Activity.PANIC -+ }; -+ -+ private static int checkInactiveWakeup(Entity entity) { -+ World world = entity.world; -+ SpigotWorldConfig config = world.spigotConfig; -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ if (entity.activationType == ActivationType.VILLAGER) { -+ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { -+ world.wakeupInactiveRemainingVillagers--; -+ return config.wakeUpInactiveVillagersFor; -+ } -+ } else if (entity.activationType == ActivationType.ANIMAL) { -+ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { -+ world.wakeupInactiveRemainingAnimals--; -+ return config.wakeUpInactiveAnimalsFor; -+ } -+ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { -+ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { -+ world.wakeupInactiveRemainingFlying--; -+ return config.wakeUpInactiveFlyingFor; -+ } -+ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { -+ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { -+ world.wakeupInactiveRemainingMonsters--; -+ return config.wakeUpInactiveMonstersFor; -+ } -+ } -+ return -1; -+ } -+ // Paper end - - static AxisAlignedBB maxBB = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); - -@@ -0,0 +0,0 @@ public class ActivationRange - */ - public static ActivationType initializeEntityActivationType(Entity entity) - { -+ if (entity instanceof EntityWaterAnimal) { return ActivationType.WATER; } // Paper -+ else if (entity instanceof EntityVillager) { return ActivationType.VILLAGER; } // Paper -+ else if (entity instanceof EntityFlying && entity instanceof IMonster) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future - if ( entity instanceof EntityRaider ) - { - return ActivationType.RAIDER; -- } else if ( entity instanceof EntityMonster || entity instanceof EntitySlime ) -+ } else if ( entity instanceof IMonster ) // Paper - correct monster check - { - return ActivationType.MONSTER; - } else if ( entity instanceof EntityCreature || entity instanceof EntityAmbient ) -@@ -0,0 +0,0 @@ public class ActivationRange - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) - { -- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) -- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) -- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) -- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) -+ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) -+ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper -+ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper -+ || entity instanceof EntityEnderSignal // Paper - || entity instanceof EntityHuman - || entity instanceof EntityProjectile - || entity instanceof EntityEnderDragon -@@ -0,0 +0,0 @@ public class ActivationRange - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; - final int monsterActivationRange = world.spigotConfig.monsterActivationRange; -+ // Paper start -+ final int waterActivationRange = world.spigotConfig.waterActivationRange; -+ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; -+ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; -+ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); -+ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); -+ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); -+ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); -+ final ChunkProviderServer chunkProvider = (ChunkProviderServer) world.getChunkProvider(); -+ // Paper end - - int maxRange = Math.max( monsterActivationRange, animalActivationRange ); - maxRange = Math.max( maxRange, raiderActivationRange ); - maxRange = Math.max( maxRange, miscActivationRange ); -+ // Paper start -+ maxRange = Math.max( maxRange, flyingActivationRange ); -+ maxRange = Math.max( maxRange, waterActivationRange ); -+ maxRange = Math.max( maxRange, villagerActivationRange ); -+ // Paper end - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); - - for ( EntityHuman player : world.getPlayers() ) -@@ -0,0 +0,0 @@ public class ActivationRange - ActivationType.RAIDER.boundingBox = player.getBoundingBox().grow( raiderActivationRange, 256, raiderActivationRange ); - ActivationType.ANIMAL.boundingBox = player.getBoundingBox().grow( animalActivationRange, 256, animalActivationRange ); - ActivationType.MONSTER.boundingBox = player.getBoundingBox().grow( monsterActivationRange, 256, monsterActivationRange ); -+ // Paper start -+ ActivationType.WATER.boundingBox = player.getBoundingBox().grow( waterActivationRange, 256, waterActivationRange ); -+ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().grow( flyingActivationRange, 256, flyingActivationRange ); -+ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().grow( villagerActivationRange, 256, waterActivationRange ); -+ // Paper end - - int i = MathHelper.floor( maxBB.minX / 16.0D ); - int j = MathHelper.floor( maxBB.maxX / 16.0D ); -@@ -0,0 +0,0 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper - if ( chunk != null ) - { - activateChunkEntities( chunk ); -@@ -0,0 +0,0 @@ public class ActivationRange - */ - private static void activateChunkEntities(Chunk chunk) - { -- for ( java.util.List slice : chunk.entitySlices ) -- { -- for ( Entity entity : (Collection) slice ) -+ // Paper start -+ Entity[] rawData = chunk.entities.getRawData(); -+ for (int i = 0; i < chunk.entities.size(); i++) { -+ Entity entity = rawData[i]; -+ //for ( Entity entity : (Collection) slice ) -+ // Paper end - { -- if ( MinecraftServer.currentTick > entity.activatedTick ) -- { -- if ( entity.defaultActivationState ) -- { -- entity.activatedTick = MinecraftServer.currentTick; -- continue; -- } -- if ( entity.activationType.boundingBox.c( entity.getBoundingBox() ) ) -- { -+ if (MinecraftServer.currentTick > entity.activatedTick) { -+ if (entity.defaultActivationState || entity.activationType.boundingBox.c(entity.getBoundingBox())) { // Paper - entity.activatedTick = MinecraftServer.currentTick; - } - } -@@ -0,0 +0,0 @@ public class ActivationRange - * @param entity - * @return - */ -- public static boolean checkEntityImmunities(Entity entity) -+ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity - { -+ // Paper start -+ SpigotWorldConfig config = entity.world.spigotConfig; -+ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); -+ if (inactiveWakeUpImmunity > -1) { -+ return inactiveWakeUpImmunity; -+ } -+ if (entity.fireTicks > 0) { -+ return 2; -+ } -+ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; -+ // Paper end - // quick checks. -- if ( entity.inWater || entity.fireTicks > 0 ) -+ if ( (entity.activationType != ActivationType.WATER && entity.inWater && entity.isPushedByWater()) ) // Paper - { -- return true; -+ return 100; // Paper - } - if ( !( entity instanceof EntityArrow ) ) - { -- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) -+ if ( (!entity.isOnGround() && !(entity instanceof EntityFlying)) ) // Paper - remove passengers logic - { -- return true; -+ return 10; // Paper - } - } else if ( !( (EntityArrow) entity ).inGround ) - { -- return true; -+ return 1; // Paper - } - // special cases. - if ( entity instanceof EntityLiving ) - { - EntityLiving living = (EntityLiving) entity; -- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) -+ if ( living.isClimbing() || living.jumping || living.hurtTicks > 0 || living.effects.size() > 0 ) // Paper - { -- return true; -+ return 1; // Paper - } -- if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).getGoalTarget() != null ) -+ if ( entity instanceof EntityInsentient && ((EntityInsentient) entity ).getGoalTarget() != null) // Paper - { -- return true; -+ return 20; // Paper - } -- if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).canBreed() ) -+ // Paper start -+ if (entity instanceof EntityBee) { -+ EntityBee bee = (EntityBee)entity; -+ BlockPosition movingTarget = bee.getMovingTarget(); -+ if (bee.isAngry() || -+ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || -+ (bee.getFlowerPos() != null && bee.getFlowerPos().equals(movingTarget)) -+ ) { -+ return 20; -+ } -+ } -+ if ( entity instanceof EntityVillager ) { -+ BehaviorController behaviorController = ((EntityVillager) entity).getBehaviorController(); -+ -+ if (config.villagersActiveForPanic) { -+ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { -+ if (behaviorController.c(activity)) { -+ return 20*5; -+ } -+ } -+ } -+ -+ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { -+ if (behaviorController.c(Activity.WORK)) { -+ return config.villagersWorkImmunityFor; -+ } -+ } -+ } -+ if ( entity instanceof EntityLlama && ( (EntityLlama) entity ).inCaravan() ) - { -- return true; -+ return 1; - } -+ // Paper end - if ( entity instanceof EntityAnimal ) - { - EntityAnimal animal = (EntityAnimal) entity; - if ( animal.isBaby() || animal.isInLove() ) - { -- return true; -+ return 5; // Paper - } - if ( entity instanceof EntitySheep && ( (EntitySheep) entity ).isSheared() ) - { -- return true; -+ return 1; // Paper - } - } - if (entity instanceof EntityCreeper && ((EntityCreeper) entity).isIgnited()) { // isExplosive -- return true; -+ return 20; // Paper - } -+ // Paper start -+ if (entity instanceof EntityInsentient && ((EntityInsentient) entity).targetSelector.hasTasks() ) { -+ return 0; -+ } -+ if (entity instanceof EntityPillager) { -+ EntityPillager pillager = (EntityPillager) entity; -+ // TODO:? -+ } -+ // Paper end - } -- return false; -+ return -1; // Paper - } - - /** -@@ -0,0 +0,0 @@ public class ActivationRange - if ( !entity.inChunk || entity instanceof EntityFireworks ) { - return true; - } -+ // Paper start - special case always immunities -+ // immunize brand new entities, dead entities, and portal scenarios -+ if (entity.defaultActivationState || entity.ticksLived < 20*10 || !entity.isAlive() || entity.inPortal || entity.portalCooldown > 0) { -+ return true; -+ } -+ // immunize leashed entities -+ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).leashHolder instanceof EntityHuman) { -+ return true; -+ } -+ // Paper end - -- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; -+ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; -+ entity.isTemporarilyActive = false; // Paper - - // Should this entity tick? - if ( !isActive ) -@@ -0,0 +0,0 @@ public class ActivationRange - if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) - { - // Check immunities every 20 ticks. -- if ( checkEntityImmunities( entity ) ) -- { -- // Triggered some sort of immunity, give 20 full ticks before we check again. -- entity.activatedTick = MinecraftServer.currentTick + 20; -+ // Paper start -+ int immunity = checkEntityImmunities(entity); -+ if (immunity >= 0) { -+ entity.activatedTick = MinecraftServer.currentTick + immunity; -+ } else { -+ entity.isTemporarilyActive = true; - } -+ // Paper end - isActive = true; -+ - } - // Add a little performance juice to active entities. Skip 1/4 if not immune. -- } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) -+ } else if (entity.ticksLived % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper - { - isActive = false; - } -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -0,0 +0,0 @@ public class SpigotWorldConfig - public int monsterActivationRange = 32; - public int raiderActivationRange = 48; - public int miscActivationRange = 16; -+ // Paper start -+ public int flyingMonsterActivationRange = 32; -+ public int waterActivationRange = 16; -+ public int villagerActivationRange = 32; -+ public int wakeUpInactiveAnimals = 4; -+ public int wakeUpInactiveAnimalsEvery = 60*20; -+ public int wakeUpInactiveAnimalsFor = 5*20; -+ public int wakeUpInactiveMonsters = 8; -+ public int wakeUpInactiveMonstersEvery = 20*20; -+ public int wakeUpInactiveMonstersFor = 5*20; -+ public int wakeUpInactiveVillagers = 4; -+ public int wakeUpInactiveVillagersEvery = 30*20; -+ public int wakeUpInactiveVillagersFor = 5*20; -+ public int wakeUpInactiveFlying = 8; -+ public int wakeUpInactiveFlyingEvery = 10*20; -+ public int wakeUpInactiveFlyingFor = 5*20; -+ public int villagersWorkImmunityAfter = 5*20; -+ public int villagersWorkImmunityFor = 20; -+ public boolean villagersActiveForPanic = true; -+ // Paper end - public boolean tickInactiveVillagers = true; - private void activationRange() - { -+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper - animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); - monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); - raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); - miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); -+ // Paper start -+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); -+ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); -+ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); -+ -+ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); -+ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); -+ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); -+ -+ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); -+ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); -+ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); -+ -+ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); -+ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); -+ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); -+ -+ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); -+ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); -+ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); -+ -+ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); -+ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); -+ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); -+ // Paper end - tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); - log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); - } diff --git a/Spigot-Server-Patches/Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-Server-Patches/Entity-AddTo-RemoveFrom-World-Events.patch deleted file mode 100644 index 12926adffd..0000000000 --- a/Spigot-Server-Patches/Entity-AddTo-RemoveFrom-World-Events.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:32:58 -0400 -Subject: [PATCH] Entity AddTo/RemoveFrom World Events - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity instanceof EntityInsentient) { - this.navigators.remove(((EntityInsentient) entity).getNavigation()); - } -- -+ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - entity.valid = false; // CraftBukkit - } - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - - } diff --git a/Spigot-Server-Patches/Entity-Jump-API.patch b/Spigot-Server-Patches/Entity-Jump-API.patch deleted file mode 100644 index cbec4f8ca4..0000000000 --- a/Spigot-Server-Patches/Entity-Jump-API.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 8 Feb 2020 23:26:11 -0600 -Subject: [PATCH] Entity Jump API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } else if (this.aQ() && (!this.onGround || d7 > d8)) { - this.c((Tag) TagsFluid.LAVA); - } else if ((this.onGround || flag && d7 <= d8) && this.jumpTicks == 0) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - this.jump(); - this.jumpTicks = 10; -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } else { - this.jumpTicks = 0; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPanda.java -@@ -0,0 +0,0 @@ public class EntityPanda extends EntityAnimal { - EntityPanda entitypanda = (EntityPanda) iterator.next(); - - if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.fh()) { -+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - entitypanda.jump(); -+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop - } - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public org.bukkit.inventory.EquipmentSlot getHandRaised() { - return getHandle().getRaisedHand() == net.minecraft.world.EnumHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; - } -+ -+ @Override -+ public boolean isJumping() { -+ return getHandle().jumping; -+ } -+ -+ @Override -+ public void setJumping(boolean jumping) { -+ getHandle().setJumping(jumping); -+ if (jumping && getHandle() instanceof EntityInsentient) { -+ // this is needed to actually make a mob jump -+ ((EntityInsentient) getHandle()).getControllerJump().jump(); -+ } -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Entity-Origin-API.patch b/Spigot-Server-Patches/Entity-Origin-API.patch deleted file mode 100644 index ffe6fb21c7..0000000000 --- a/Spigot-Server-Patches/Entity-Origin-API.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 23:45:08 -0600 -Subject: [PATCH] Entity Origin API - - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagList.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagList.java -@@ -0,0 +0,0 @@ public class NBTTagList extends NBTList { - return new int[0]; - } - -+ public final double getDoubleAt(int i) { return this.h(i); } // Paper - OBFHELPER - public double h(int i) { - if (i >= 0 && i < this.list.size()) { - NBTBase nbtbase = (NBTBase) this.list.get(i); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.navigators.add(((EntityInsentient) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ // Paper start - Set origin location when the entity is being added to the world -+ if (entity.origin == null) { -+ entity.origin = entity.getBukkitEntity().getLocation(); -+ } -+ // Paper end - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -+ public org.bukkit.Location origin; // Paper - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.bukkitEntity.storeBukkitValues(nbttagcompound); - } - // CraftBukkit end -+ // Paper start - Save the entity's origin location -+ if (this.origin != null) { -+ nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); -+ nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); -+ } -+ // Paper end - return nbttagcompound; - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Saving entity NBT"); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ // Paper start - Restore the entity's origin location -+ NBTTagList originTag = nbttagcompound.getList("Paper.Origin", 6); -+ if (!originTag.isEmpty()) { -+ org.bukkit.World originWorld = world.getWorld(); -+ if (nbttagcompound.hasKey("Paper.OriginWorld")) { -+ originWorld = Bukkit.getWorld(nbttagcompound.getUUID("Paper.OriginWorld")); -+ } -+ origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); -+ } -+ // Paper end -+ - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded"); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - protected abstract void saveData(NBTTagCompound nbttagcompound); - -+ protected final NBTTagList createList(double... adouble) { return a(adouble); } // Paper - OBFHELPER - protected NBTTagList a(double... adouble) { - NBTTagList nbttaglist = new NBTTagList(); - double[] adouble1 = adouble; -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { - this.block = Blocks.SAND.getBlockData(); - } - -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (nbttagcompound.hasKey("SourceLoc_x")) { -+ int srcX = nbttagcompound.getInt("SourceLoc_x"); -+ int srcY = nbttagcompound.getInt("SourceLoc_y"); -+ int srcZ = nbttagcompound.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - public void a(boolean flag) { -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -0,0 +0,0 @@ public class EntityTNTPrimed extends Entity { - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - this.setFuseTicks(nbttagcompound.getShort("Fuse")); -+ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility -+ if (nbttagcompound.hasKey("SourceLoc_x")) { -+ int srcX = nbttagcompound.getInt("SourceLoc_x"); -+ int srcY = nbttagcompound.getInt("SourceLoc_y"); -+ int srcZ = nbttagcompound.getInt("SourceLoc_z"); -+ origin = new org.bukkit.Location(world.getWorld(), srcX, srcY, srcZ); -+ } -+ // Paper end - } - - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public Location getOrigin() { -+ Location origin = getHandle().origin; -+ return origin == null ? null : origin.clone(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Entity-fromMobSpawner.patch b/Spigot-Server-Patches/Entity-fromMobSpawner.patch deleted file mode 100644 index 72a76c566a..0000000000 --- a/Spigot-Server-Patches/Entity-fromMobSpawner.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 18 Jun 2017 18:17:05 -0500 -Subject: [PATCH] Entity#fromMobSpawner() - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; - public long activatedTick = Integer.MIN_VALUE; -+ public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ // Save entity's from mob spawner status -+ if (spawnedViaMobSpawner) { -+ nbttagcompound.setBoolean("Paper.FromMobSpawner", true); -+ } - // Paper end - return nbttagcompound; - } catch (Throwable throwable) { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - origin = new org.bukkit.Location(originWorld, originTag.getDoubleAt(0), originTag.getDoubleAt(1), originTag.getDoubleAt(2)); - } -+ -+ spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - } - // Spigot End - } -+ entity.spawnedViaMobSpawner = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - Location origin = getHandle().origin; - return origin == null ? null : origin.clone(); - } -+ -+ @Override -+ public boolean fromMobSpawner() { -+ return getHandle().spawnedViaMobSpawner; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch b/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch deleted file mode 100644 index b469bc0a8c..0000000000 --- a/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 00:24:52 -0400 -Subject: [PATCH] Entity#getEntitySpawnReason - -Allows you to return the SpawnReason for why an Entity Spawned - -Pre existing entities will return NATURAL if it was a non -persistenting Living Entity, SPAWNER for spawners, -or DEFAULT since data was not stored. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper - // Paper start - if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // CraftBukkit start - WorldServer finalWorldServer = worldserver1; - Entity entity = EntityTypes.a(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { -- return !finalWorldServer.addEntitySerialized(entity1) ? null : entity1; -+ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper - // CraftBukkit end - }); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.INamableTileEntity; - import net.minecraft.world.damagesource.DamageSource; -+import net.minecraft.world.entity.animal.EntityAnimal; -+import net.minecraft.world.entity.animal.EntityFish; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.vehicle.EntityBoat; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - }; - public List entitySlice = null; -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; - // Paper end - - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - nbttagcompound.setUUID("Paper.OriginWorld", origin.getWorld().getUID()); - nbttagcompound.set("Paper.Origin", this.createList(origin.getX(), origin.getY(), origin.getZ())); - } -+ if (spawnReason != null) { -+ nbttagcompound.setString("Paper.SpawnReason", spawnReason.name()); -+ } - // Save entity's from mob spawner status - if (spawnedViaMobSpawner) { - nbttagcompound.setBoolean("Paper.FromMobSpawner", true); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ if (nbttagcompound.hasKey("Paper.SpawnReason")) { -+ String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); -+ try { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); -+ } catch (Exception ignored) { -+ LogManager.getLogger().error("Unknown SpawnReason " + spawnReasonName + " for " + this); -+ } -+ } -+ if (spawnReason == null) { -+ if (spawnedViaMobSpawner) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; -+ } else if (this instanceof EntityInsentient && (this instanceof EntityAnimal || this instanceof EntityFish) && !((EntityInsentient) this).isTypeNotPersistent(0.0)) { -+ if (!nbttagcompound.getBoolean("PersistenceRequired")) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; -+ } -+ } -+ } -+ if (spawnReason == null) { -+ spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; -+ } - // Paper end - - } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper - flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean fromMobSpawner() { - return getHandle().spawnedViaMobSpawner; - } -+ -+ @Override -+ public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { -+ return getHandle().spawnReason; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Entity-isTicking.patch b/Spigot-Server-Patches/Entity-isTicking.patch deleted file mode 100644 index 85834c6b36..0000000000 --- a/Spigot-Server-Patches/Entity-isTicking.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 21:39:16 -0500 -Subject: [PATCH] Entity#isTicking - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.TicketType; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public static int nextEntityId() { - return entityCount.incrementAndGet(); - } -+ -+ public boolean isTicking() { -+ return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - public boolean isInLava() { - return getHandle().isInLava(); - } -+ -+ public boolean isTicking() { -+ return getHandle().isTicking(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Entity-load-save-limit-per-chunk.patch b/Spigot-Server-Patches/Entity-load-save-limit-per-chunk.patch deleted file mode 100644 index 8692fa5174..0000000000 --- a/Spigot-Server-Patches/Entity-load-save-limit-per-chunk.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Wed, 18 Nov 2020 20:52:25 -0800 -Subject: [PATCH] Entity load/save limit per chunk - -Adds a config option to limit the number of entities saved and loaded -to a chunk. The default values of -1 disable the limit. Although -defaults are only included for certain entites, this allows setting -limits for any entity type. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ import java.util.stream.Collectors; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import net.minecraft.world.EnumDifficulty; -+import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.monster.EntityVindicator; - import net.minecraft.world.entity.monster.EntityZombie; - import org.bukkit.Bukkit; -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - EnumDifficulty.class - ); - } -+ -+ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); -+ private void entityPerChunkSaveLimits() { -+ getInt("entity-per-chunk-save-limit.experience_orb", -1); -+ getInt("entity-per-chunk-save-limit.snowball", -1); -+ getInt("entity-per-chunk-save-limit.ender_pearl", -1); -+ getInt("entity-per-chunk-save-limit.arrow", -1); -+ EntityTypes.getEntityNameList().forEach(name -> { -+ final EntityTypes type = EntityTypes.getByName(name.getKey()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); -+ final String path = ".entity-per-chunk-save-limit." + name.getKey(); -+ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults -+ if (value != -1) entityPerChunkSaveLimits.put(type, value); -+ }); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - - chunk.d(false); - -+ // Paper start -+ final Map, Integer> savedEntityCounts = Maps.newHashMap(); - for (int j = 0; j < chunk.getEntitySlices().length; ++j) { - Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); - - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); -+ final EntityTypes entityType = entity.getEntityType(); -+ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ continue; -+ } -+ savedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); - // Paper start - if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); - World world = chunk.getWorld(); - -+ // Paper start -+ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); - - EntityTypes.a(nbttagcompound1, world, (entity) -> { -+ final EntityTypes entityType = entity.getEntityType(); -+ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); -+ if (saveLimit > -1) { -+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { -+ return null; -+ } -+ loadedEntityCounts.merge(entityType, 1, Integer::sum); -+ } -+ // Paper end - chunk.a(entity); - return entity; - }); diff --git a/Spigot-Server-Patches/EntityMoveEvent.patch b/Spigot-Server-Patches/EntityMoveEvent.patch deleted file mode 100644 index 6453240840..0000000000 --- a/Spigot-Server-Patches/EntityMoveEvent.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Tue, 11 Feb 2020 21:56:48 -0600 -Subject: [PATCH] EntityMoveEvent - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper -+import io.papermc.paper.event.entity.EntityMoveEvent; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper -+ worldserver.hasEntityMoveEvent = EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Convertable.ConversionSession convertable; - public final UUID uuid; - public boolean hasPhysicsEvent = true; // Paper -+ public boolean hasEntityMoveEvent = false; // Paper - private static Throwable getAddToWorldStackTrace(Entity entity) { - return new Throwable(entity + " Added to world at " + new java.util.Date()); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ import com.mojang.datafixers.util.Pair; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; -+import io.papermc.paper.event.entity.EntityMoveEvent; - import java.util.Collection; - import java.util.ConcurrentModificationException; - import java.util.Iterator; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - this.collideNearby(); - this.world.getMethodProfiler().exit(); -+ // Paper start -+ if (((WorldServer) world).hasEntityMoveEvent) { -+ if (lastX != locX() || lastY != locY() || lastZ != locZ() || lastYaw != yaw || lastPitch != pitch) { -+ Location from = new Location(world.getWorld(), lastX, lastY, lastZ, lastYaw, lastPitch); -+ Location to = new Location (world.getWorld(), locX(), locY(), locZ(), yaw, pitch); -+ EntityMoveEvent event = new EntityMoveEvent(getBukkitLivingEntity(), from, to.clone()); -+ if (!event.callEvent()) { -+ setLocation(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); -+ } else if (!to.equals(event.getTo())) { -+ setLocation(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); -+ } -+ } -+ } -+ // Paper end - if (!this.world.isClientSide && this.dO() && this.aG()) { - this.damageEntity(DamageSource.DROWN, 1.0F); - } diff --git a/Spigot-Server-Patches/EntityPathfindEvent.patch b/Spigot-Server-Patches/EntityPathfindEvent.patch deleted file mode 100644 index 977943725e..0000000000 --- a/Spigot-Server-Patches/EntityPathfindEvent.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 21:22:26 -0400 -Subject: [PATCH] EntityPathfindEvent - -Fires when an Entity decides to start moving to a location. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/Navigation.java -@@ -0,0 +0,0 @@ public class Navigation extends NavigationAbstract { - - @Override - public PathEntity a(Entity entity, int i) { -- return this.a(entity.getChunkCoordinates(), i); -+ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity - } - - private int u() { -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IPosition; - import net.minecraft.network.protocol.game.PacketDebug; -+import net.minecraft.server.MCUtil; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.Vec3D; - - public abstract class NavigationAbstract { - -- protected final EntityInsentient a; -+ protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER - protected final World b; - @Nullable - protected PathEntity c; -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - - @Nullable - public PathEntity a(BlockPosition blockposition, int i) { -- return this.a(ImmutableSet.of(blockposition), 8, false, i); -+ // Paper start - add target parameter -+ return this.a(blockposition, null, i); -+ } -+ @Nullable public PathEntity a(BlockPosition blockposition, Entity target, int i) { -+ return this.a(ImmutableSet.of(blockposition), target, 8, false, i); -+ // Paper end - } - - @Nullable - public PathEntity a(Entity entity, int i) { -- return this.a(ImmutableSet.of(entity.getChunkCoordinates()), 16, true, i); -+ return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper - } - - @Nullable -+ // Paper start - Add target - protected PathEntity a(Set set, int i, boolean flag, int j) { -+ return this.a(set, null, i, flag, j); -+ } -+ @Nullable protected PathEntity a(Set set, Entity target, int i, boolean flag, int j) { -+ // Paper end - if (set.isEmpty()) { - return null; - } else if (this.a.locY() < 0.0D) { -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - } else if (this.c != null && !this.c.c() && set.contains(this.p)) { - return this.c; - } else { -+ // Paper start - Pathfind event -+ boolean copiedSet = false; -+ for (BlockPosition possibleTarget : set) { -+ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { -+ if (!copiedSet) { -+ copiedSet = true; -+ set = new java.util.HashSet<>(set); -+ } -+ // note: since we copy the set this remove call is safe, since we're iterating over the old copy -+ set.remove(possibleTarget); -+ if (set.isEmpty()) { -+ return null; -+ } -+ } -+ } -+ // Paper end - this.b.getMethodProfiler().enter("pathfind"); - float f = (float) this.a.b(GenericAttributes.FOLLOW_RANGE); - BlockPosition blockposition = flag ? this.a.getChunkCoordinates().up() : this.a.getChunkCoordinates(); -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationFlying.java -@@ -0,0 +0,0 @@ public class NavigationFlying extends NavigationAbstract { - - @Override - public PathEntity a(Entity entity, int i) { -- return this.a(entity.getChunkCoordinates(), i); -+ return this.a(entity.getChunkCoordinates(), entity, i); // Paper - Forward target entity - } - - @Override diff --git a/Spigot-Server-Patches/EntityRegainHealthEvent-isFastRegen-API.patch b/Spigot-Server-Patches/EntityRegainHealthEvent-isFastRegen-API.patch deleted file mode 100644 index 29e28198c1..0000000000 --- a/Spigot-Server-Patches/EntityRegainHealthEvent-isFastRegen-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Fri, 22 Apr 2016 01:43:11 -0500 -Subject: [PATCH] EntityRegainHealthEvent isFastRegen API - -Don't even get me started - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { -+ // Paper start - Forward -+ heal(f, regainReason, false); -+ } -+ -+ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason, boolean isFastRegen) { -+ // Paper end - float f1 = this.getHealth(); - - if (f1 > 0.0F) { -- EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); -+ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason, isFastRegen); // Paper - // Suppress during worldgen - if (this.valid) { - this.world.getServer().getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/world/food/FoodMetaData.java b/src/main/java/net/minecraft/world/food/FoodMetaData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/food/FoodMetaData.java -+++ b/src/main/java/net/minecraft/world/food/FoodMetaData.java -@@ -0,0 +0,0 @@ public class FoodMetaData { - if (this.foodTickTimer >= this.saturatedRegenRate) { // CraftBukkit - float f = Math.min(this.saturationLevel, 6.0F); - -- entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason -+ entityhuman.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED, true); // CraftBukkit - added RegainReason // Paper - This is fast regen - // this.a(f); CraftBukkit - EntityExhaustionEvent - entityhuman.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent - this.foodTickTimer = 0; diff --git a/Spigot-Server-Patches/Expand-Explosions-API.patch b/Spigot-Server-Patches/Expand-Explosions-API.patch deleted file mode 100644 index 7da769e18b..0000000000 --- a/Spigot-Server-Patches/Expand-Explosions-API.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 20 Jun 2018 23:17:24 -0400 -Subject: [PATCH] Expand Explosions API - -Add Entity as a Source capability, and add more API choices, and on Location. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { - return !world.createExplosion(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; - } -+ // Paper start -+ public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { -+ return !world.createExplosion(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.Effect.BREAK : Explosion.Effect.NONE).wasCanceled; -+ } -+ // Paper end - - @Override - public boolean createExplosion(Location loc, float power) { diff --git a/Spigot-Server-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch b/Spigot-Server-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch deleted file mode 100644 index 93cc71f053..0000000000 --- a/Spigot-Server-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 15 Aug 2017 22:29:12 -0400 -Subject: [PATCH] Expand World.spawnParticle API and add Builder - -Adds ability to control who receives it and who is the source/sender (vanish API) -the standard API is to send the packet to everyone in the world, which is ineffecient. -Adds an option to control the force mode of the particle. - -This adds a new Builder API which is much friendlier to use. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - public final Int2ObjectMap entitiesById = new Int2ObjectLinkedOpenHashMap(); - private final Map entitiesByUUID = Maps.newHashMap(); - private final Queue entitiesToAdd = Queues.newArrayDeque(); -- private final List players = Lists.newArrayList(); -+ public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - public int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper start - Particle API Expansion -+ return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); -+ } -+ public int sendParticles(List receivers, EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { -+ // Paper end - PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); - // CraftBukkit end - int j = 0; - -- for (int k = 0; k < this.players.size(); ++k) { -- EntityPlayer entityplayer = (EntityPlayer) this.players.get(k); -+ for (EntityHuman entityhuman : receivers) { // Paper - Particle API Expansion -+ EntityPlayer entityplayer = (EntityPlayer) entityhuman; // Paper - Particle API Expansion - if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit - - if (this.a(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { -+ // Paper start - Particle API Expansion -+ spawnParticle(particle, null, null, x, y, z, count, offsetX, offsetY, offsetZ, extra, data, force); -+ } -+ public void spawnParticle(Particle particle, List receivers, Player sender, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { -+ // Paper end - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } - getHandle().sendParticles( -- null, // Sender -+ receivers == null ? getHandle().players : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API Expansion -+ sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API Expansion - CraftParticle.toNMS(particle, data), // Particle - x, y, z, // Position - count, // Count diff --git a/Spigot-Server-Patches/ExperienceOrbMergeEvent.patch b/Spigot-Server-Patches/ExperienceOrbMergeEvent.patch deleted file mode 100644 index a577862204..0000000000 --- a/Spigot-Server-Patches/ExperienceOrbMergeEvent.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:57:26 -0500 -Subject: [PATCH] ExperienceOrbMergeEvent - -Fired when the server is about to merge 2 experience orbs -Plugins can cancel this if they want to ensure experience orbs do not lose important -metadata such as spawn reason, or conditionally move data from source to target. - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - if (e instanceof EntityExperienceOrb) { - EntityExperienceOrb loopItem = (EntityExperienceOrb) e; - // Paper start -- if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue) && new com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent((org.bukkit.entity.ExperienceOrb) entity.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) loopItem.getBukkitEntity()).callEvent()) { // Paper - long newTotal = (long)xp.value + (long)loopItem.value; - if ((int) newTotal < 0) continue; // Overflow - if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/Spigot-Server-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Spigot-Server-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch deleted file mode 100644 index 82c926aa01..0000000000 --- a/Spigot-Server-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 16:31:46 -0500 -Subject: [PATCH] ExperienceOrbs API for Reason/Source/Triggering player - -Adds lots of information about why this orb exists. - -Replaces isFromBottle() with logic that persists entity reloads too. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - - // Drop event experience - if (flag && event != null) { -- iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop()); -+ iblockdata.getBlock().dropExperience(this.world, blockposition, event.getExpToDrop(), this.player); // Paper - } - - return true; -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - public int value; - private EntityHuman targetPlayer; - private int targetTime; -+ // Paper start -+ public java.util.UUID sourceEntityId; -+ public java.util.UUID triggerEntityId; -+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ -+ private void loadPaperNBT(NBTTagCompound nbttagcompound) { -+ if (!nbttagcompound.hasKeyOfType("Paper.ExpData", 10)) { // 10 = compound -+ return; -+ } -+ NBTTagCompound comp = nbttagcompound.getCompound("Paper.ExpData"); -+ if (comp.hasUUID("source")) { -+ this.sourceEntityId = comp.getUUID("source"); -+ } -+ if (comp.hasUUID("trigger")) { -+ this.triggerEntityId = comp.getUUID("trigger"); -+ } -+ if (comp.hasKey("reason")) { -+ String reason = comp.getString("reason"); -+ try { -+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); -+ } catch (Exception e) { -+ this.world.getServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); -+ } -+ } -+ } -+ private void savePaperNBT(NBTTagCompound nbttagcompound) { -+ NBTTagCompound comp = new NBTTagCompound(); -+ if (this.sourceEntityId != null) { -+ comp.setUUID("source", this.sourceEntityId); -+ } -+ if (this.triggerEntityId != null) { -+ comp.setUUID("trigger", triggerEntityId); -+ } -+ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { -+ comp.setString("reason", this.spawnReason.name()); -+ } -+ nbttagcompound.set("Paper.ExpData", comp); -+ } - - public EntityExperienceOrb(World world, double d0, double d1, double d2, int i) { -+ this(world, d0, d1, d2, i, null, null); -+ } -+ -+ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { -+ this(world, d0, d1, d2, i, reason, triggerId, null); -+ } -+ -+ public EntityExperienceOrb(World world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { - this(EntityTypes.EXPERIENCE_ORB, world); -+ this.sourceEntityId = sourceId != null ? sourceId.getUniqueID() : null; -+ this.triggerEntityId = triggerId != null ? triggerId.getUniqueID() : null; -+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ // Paper end - this.setPosition(d0, d1, d2); - this.yaw = (float) (this.random.nextDouble() * 360.0D); - this.setMot((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - nbttagcompound.setShort("Health", (short) this.e); - nbttagcompound.setShort("Age", (short) this.c); - nbttagcompound.setShort("Value", (short) this.value); -+ this.savePaperNBT(nbttagcompound); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - this.e = nbttagcompound.getShort("Health"); - this.c = nbttagcompound.getShort("Age"); - this.value = nbttagcompound.getShort("Value"); -+ this.loadPaperNBT(nbttagcompound); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ EntityLiving attacker = killer != null ? killer : lastDamager; // Paper -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, this instanceof EntityPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this)); // Paper - } - this.expToDrop = 0; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityAnimal.java -@@ -0,0 +0,0 @@ public abstract class EntityAnimal extends EntityAgeable { - if (worldserver.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience)); -+ worldserver.addEntity(new EntityExperienceOrb(worldserver, this.locX(), this.locY(), this.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -0,0 +0,0 @@ public class EntityFox extends EntityAnimal { - if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { - // CraftBukkit start - use event experience - if (experience > 0) { -- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience)); -+ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper - } - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { - Random random = this.animal.getRandom(); - - if (this.b.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { -- this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1)); -+ this.b.addEntity(new EntityExperienceOrb(this.b, this.animal.locX(), this.animal.locY(), this.animal.locZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.killer, this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - if (merchantrecipe.isRewardExp()) { -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -0,0 +0,0 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - if (merchantrecipe.isRewardExp()) { - int i = 3 + this.random.nextInt(4); - -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY() + 0.5D, this.locZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTrader(), this)); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFishingHook.java -@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile { - this.world.addEntity(entityitem); - // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() - if (playerFishEvent.getExpToDrop() > 0) { -- entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop())); -+ entityhuman.world.addEntity(new EntityExperienceOrb(entityhuman.world, entityhuman.locX(), entityhuman.locY() + 0.5D, entityhuman.locZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getOwner(), this)); // Paper - } - // CraftBukkit end - if (itemstack1.getItem().a((Tag) TagsItem.FISHES)) { -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityThrownExpBottle.java -@@ -0,0 +0,0 @@ public class EntityThrownExpBottle extends EntityProjectileThrowable { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j)); -+ this.world.addEntity(new EntityExperienceOrb(this.world, this.locX(), this.locY(), this.locZ(), j, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, getShooter(), this)); // Paper - } - - this.die(); -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -0,0 +0,0 @@ public class ContainerGrindstone extends Container { - int k = EntityExperienceOrb.getOrbValue(j); - - j -= k; -- world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k)); -+ world.addEntity(new EntityExperienceOrb(world, (double) blockposition.getX(), (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, k, org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, entityhuman)); // Paper - } - - world.triggerEffect(1042, blockposition, 0); -diff --git a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -+++ b/src/main/java/net/minecraft/world/inventory/SlotFurnaceResult.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.entity.TileEntityFurnace; - - public class SlotFurnaceResult extends Slot { - -- private final EntityHuman a; -+ private final EntityHuman a; public final EntityHuman getPlayer() { return this.a; } // Paper OBFHELPER - private int b; - - public SlotFurnaceResult(EntityHuman entityhuman, IInventory iinventory, int i, int j, int k) { -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -0,0 +0,0 @@ public class Block extends BlockBase implements IMaterial { - } - } - -- public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i) { -+ public void dropExperience(WorldServer worldserver, BlockPosition blockposition, int i, net.minecraft.server.level.EntityPlayer player) { // Paper - if (worldserver.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) { - while (i > 0) { - int j = EntityExperienceOrb.getOrbValue(i); - - i -= j; -- worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j)); -+ worldserver.addEntity(new EntityExperienceOrb(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, j, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player)); // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - int k = EntityExperienceOrb.getOrbValue(j); - - j -= k; -- world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k)); -+ world.addEntity(new EntityExperienceOrb(world, vec3d.x, vec3d.y, vec3d.z, k, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman)); // Paper - } - - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - } else if (TNTPrimed.class.isAssignableFrom(clazz)) { - entity = new EntityTNTPrimed(world, x, y, z, null); - } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { -- entity = new EntityExperienceOrb(world, x, y, z, 0); -+ entity = new EntityExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper - } else if (LightningStrike.class.isAssignableFrom(clazz)) { - entity = EntityTypes.LIGHTNING_BOLT.a(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -@@ -0,0 +0,0 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { - getHandle().value = value; - } - -+ // Paper start -+ public java.util.UUID getTriggerEntityId() { -+ return getHandle().triggerEntityId; -+ } -+ public java.util.UUID getSourceEntityId() { -+ return getHandle().sourceEntityId; -+ } -+ public SpawnReason getSpawnReason() { -+ return getHandle().spawnReason; -+ } -+ // Paper end -+ - @Override - public EntityExperienceOrb getHandle() { - return (EntityExperienceOrb) entity; diff --git a/Spigot-Server-Patches/Expose-Arrow-getItemStack.patch b/Spigot-Server-Patches/Expose-Arrow-getItemStack.patch deleted file mode 100644 index 3fef098cb0..0000000000 --- a/Spigot-Server-Patches/Expose-Arrow-getItemStack.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nesaak <52047222+Nesaak@users.noreply.github.com> -Date: Sat, 23 May 2020 10:31:11 -0400 -Subject: [PATCH] Expose Arrow getItemStack - - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile { - } - } - -+ public final ItemStack getOriginalItemStack() { return getItemStack(); } // Paper - OBFHELPER - exists purely due to overrides all as protected and dont want to change them all - protected abstract ItemStack getItemStack(); - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -@@ -0,0 +0,0 @@ public class CraftArrow extends AbstractProjectile implements AbstractArrow { - getHandle().fromPlayer = EntityArrow.PickupStatus.a(status.ordinal()); - } - -+ // Paper start -+ @Override -+ public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); -+ } -+ //Paper end -+ - @Override - public void setTicksLived(int value) { - super.setTicksLived(value); diff --git a/Spigot-Server-Patches/Expose-LivingEntity-hurt-direction.patch b/Spigot-Server-Patches/Expose-LivingEntity-hurt-direction.patch deleted file mode 100644 index a7913458fc..0000000000 --- a/Spigot-Server-Patches/Expose-LivingEntity-hurt-direction.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 13 Dec 2020 05:32:05 +0200 -Subject: [PATCH] Expose LivingEntity hurt direction - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - public int am; - public int hurtTicks; - public int hurtDuration; -- public float ap; -+ public float ap; public final float getHurtDirection() { return ap; } public final void setHurtDirection(float hurtDirection) { this.ap = hurtDirection; } // Paper - OBFHELPER - public int deathTicks; - public float ar; - public float as; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { - getHandle().receive(((CraftItem) item).getHandle(), quantity); - } -+ -+ @Override -+ public float getHurtDirection() { -+ return getHandle().getHurtDirection(); -+ } -+ -+ @Override -+ public void setHurtDirection(float hurtDirection) { -+ getHandle().setHurtDirection(hurtDirection); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Expose-MinecraftServer-isRunning.patch b/Spigot-Server-Patches/Expose-MinecraftServer-isRunning.patch deleted file mode 100644 index 58cb2c3fe0..0000000000 --- a/Spigot-Server-Patches/Expose-MinecraftServer-isRunning.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Fri, 10 Apr 2020 21:24:12 -0400 -Subject: [PATCH] Expose MinecraftServer#isRunning - -This allows for plugins to detect if the server is actually turning off in onDisable rather than just plugins reloading. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - public int getCurrentTick() { - return net.minecraft.server.MinecraftServer.currentTick; - } -+ -+ @Override -+ public boolean isStopping() { -+ return net.minecraft.server.MinecraftServer.getServer().hasStopped(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Expose-Tracked-Players.patch b/Spigot-Server-Patches/Expose-Tracked-Players.patch deleted file mode 100644 index 54493beb19..0000000000 --- a/Spigot-Server-Patches/Expose-Tracked-Players.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tom -Date: Fri, 26 Feb 2021 16:24:25 -0600 -Subject: [PATCH] Expose Tracked Players - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - -- PlayerChunkMap.EntityTracker tracker; // Paper -+ public PlayerChunkMap.EntityTracker tracker; // Paper package private -> public - public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ import java.net.InetSocketAddress; - import java.net.SocketAddress; - import java.util.ArrayList; - import java.util.Collection; -+import java.util.Collections; // Paper - import java.util.HashMap; - import java.util.HashSet; - import java.util.LinkedHashMap; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - // Paper end - -+ // Paper start -+ @Override -+ public Set getTrackedPlayers() { -+ if (entity.tracker == null) { -+ return Collections.emptySet(); -+ } -+ -+ Set set = new HashSet<>(entity.tracker.trackedPlayers.size()); -+ for (EntityPlayer entityPlayer : entity.tracker.trackedPlayers) { -+ set.add(entityPlayer.getBukkitEntity().getPlayer()); -+ } -+ return set; -+ } -+ // Paper end -+ - // Spigot start - private final Player.Spigot spigot = new Player.Spigot() - { diff --git a/Spigot-Server-Patches/Expose-attack-cooldown-methods-for-Player.patch b/Spigot-Server-Patches/Expose-attack-cooldown-methods-for-Player.patch deleted file mode 100644 index 64e7c908fb..0000000000 --- a/Spigot-Server-Patches/Expose-attack-cooldown-methods-for-Player.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 4 Sep 2018 15:02:00 -0500 -Subject: [PATCH] Expose attack cooldown methods for Player - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - this.datawatcher.set(EntityHuman.bl, nbttagcompound); - } - -+ public float getCooldownPeriod() { return this.eR(); } // Paper - OBFHELPER - public float eR() { - return (float) (1.0D / this.b(GenericAttributes.ATTACK_SPEED) * 20.0D); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutOpenBook(net.minecraft.world.EnumHand.MAIN_HAND)); - connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutSetSlot(0, slot, inventory.getItemInHand())); - } -+ -+ public float getCooldownPeriod() { -+ return getHandle().getCooldownPeriod(); -+ } -+ -+ public float getCooledAttackStrength(float adjustTicks) { -+ return getHandle().getAttackCooldown(adjustTicks); -+ } -+ -+ public void resetCooldown() { -+ getHandle().resetAttackCooldown(); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/Expose-client-protocol-version-and-virtual-host.patch b/Spigot-Server-Patches/Expose-client-protocol-version-and-virtual-host.patch deleted file mode 100644 index 14d625af67..0000000000 --- a/Spigot-Server-Patches/Expose-client-protocol-version-and-virtual-host.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 10 Oct 2017 18:45:20 +0200 -Subject: [PATCH] Expose client protocol version and virtual host - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperNetworkClient.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.network; -+ -+import net.minecraft.network.NetworkManager; -+ -+import java.net.InetSocketAddress; -+ -+import javax.annotation.Nullable; -+ -+public class PaperNetworkClient implements NetworkClient { -+ -+ private final NetworkManager networkManager; -+ -+ PaperNetworkClient(NetworkManager networkManager) { -+ this.networkManager = networkManager; -+ } -+ -+ @Override -+ public InetSocketAddress getAddress() { -+ return (InetSocketAddress) this.networkManager.getSocketAddress(); -+ } -+ -+ @Override -+ public int getProtocolVersion() { -+ return this.networkManager.protocolVersion; -+ } -+ -+ @Nullable -+ @Override -+ public InetSocketAddress getVirtualHost() { -+ return this.networkManager.virtualHost; -+ } -+ -+ public static InetSocketAddress prepareVirtualHost(String host, int port) { -+ int len = host.length(); -+ -+ // FML appends a marker to the host to recognize FML clients (\0FML\0) -+ int pos = host.indexOf('\0'); -+ if (pos >= 0) { -+ len = pos; -+ } -+ -+ // When clients connect with a SRV record, their host contains a trailing '.' -+ if (len > 0 && host.charAt(len - 1) == '.') { -+ len--; -+ } -+ -+ return InetSocketAddress.createUnresolved(host.substring(0, len), port); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - private float s; - private int t; - private boolean u; -+ // Paper start - NetworkClient implementation -+ public int protocolVersion; -+ public java.net.InetSocketAddress virtualHost; -+ // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { - this.h = enumprotocoldirection; -diff --git a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -+++ b/src/main/java/net/minecraft/network/protocol/handshake/PacketHandshakingInSetProtocol.java -@@ -0,0 +0,0 @@ public class PacketHandshakingInSetProtocol implements Packet -Date: Fri, 1 May 2020 17:39:26 +0300 -Subject: [PATCH] Expose game version - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return bukkitVersion; - } - -+ // Paper start - expose game version -+ @Override -+ public String getMinecraftVersion() { -+ return console.getVersion(); -+ } -+ // Paper end -+ - @Override - public List getOnlinePlayers() { - return this.playerView; diff --git a/Spigot-Server-Patches/Expose-protocol-version.patch b/Spigot-Server-Patches/Expose-protocol-version.patch deleted file mode 100644 index dafc87e28d..0000000000 --- a/Spigot-Server-Patches/Expose-protocol-version.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -Date: Fri, 26 Mar 2021 11:23:17 +0100 -Subject: [PATCH] Expose protocol version - - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; - } -+ -+ @Override -+ public int getProtocolVersion() { -+ return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/Expose-server-CommandMap.patch b/Spigot-Server-Patches/Expose-server-CommandMap.patch deleted file mode 100644 index 2a0fe5f545..0000000000 --- a/Spigot-Server-Patches/Expose-server-CommandMap.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Thu, 3 Mar 2016 02:15:57 -0600 -Subject: [PATCH] Expose server CommandMap - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return helpMap; - } - -+ @Override // Paper - add override - public SimpleCommandMap getCommandMap() { - return commandMap; - } diff --git a/Spigot-Server-Patches/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Spigot-Server-Patches/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch deleted file mode 100644 index 04af79fdae..0000000000 --- a/Spigot-Server-Patches/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Fri, 28 Aug 2020 01:41:26 +0200 -Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and - non-conflicting Entity Ids - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - void accept(Entity entity, double d0, double d1, double d2); - } -+ -+ // Paper start -+ public static int nextEntityId() { -+ return entityCount.incrementAndGet(); -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); - return nmsItemStack.getItem().getDescriptionId(nmsItemStack); - } -+ -+ public int nextEntityId() { -+ return net.minecraft.world.entity.Entity.nextEntityId(); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/Expose-the-internal-current-tick.patch b/Spigot-Server-Patches/Expose-the-internal-current-tick.patch deleted file mode 100644 index 2b33037f5c..0000000000 --- a/Spigot-Server-Patches/Expose-the-internal-current-tick.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 20 Apr 2019 19:47:34 -0500 -Subject: [PATCH] Expose the internal current tick - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - return new com.destroystokyo.paper.profile.CraftPlayerProfile(uuid, name); - } -+ -+ @Override -+ public int getCurrentTick() { -+ return net.minecraft.server.MinecraftServer.currentTick; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Expose-world-spawn-angle.patch b/Spigot-Server-Patches/Expose-world-spawn-angle.patch deleted file mode 100644 index e4345c19f5..0000000000 --- a/Spigot-Server-Patches/Expose-world-spawn-angle.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Tue, 17 Nov 2020 19:13:09 +0200 -Subject: [PATCH] Expose world spawn angle - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - if (location == null) { - worldserver1 = this.server.getWorldServer(World.OVERWORLD); - blockposition = entityplayer1.getSpawnPoint(worldserver1); -- location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F)); -+ location = new Location(worldserver1.getWorld(), (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F), worldserver1.worldData.getSpawnAngle(), 0.0F); // Paper - use world spawn angle - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldData.java b/src/main/java/net/minecraft/world/level/storage/WorldData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldData.java -@@ -0,0 +0,0 @@ public interface WorldData { - - int c(); - -+ default float getSpawnAngle() { return d(); } // Paper - OBFHELPER - float d(); - - long getTime(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - @Override - public Location getSpawnLocation() { - BlockPosition spawn = world.getSpawn(); -- return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ()); -+ return new Location(this, spawn.getX(), spawn.getY(), spawn.getZ(), world.worldData.getSpawnAngle(), 0.0F); // Paper - expose world spawn angle - } - - @Override diff --git a/Spigot-Server-Patches/Extend-Player-Interact-cancellation.patch b/Spigot-Server-Patches/Extend-Player-Interact-cancellation.patch deleted file mode 100644 index d7d0d71cdd..0000000000 --- a/Spigot-Server-Patches/Extend-Player-Interact-cancellation.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Feb 2018 10:43:46 +0000 -Subject: [PATCH] Extend Player Interact cancellation - -GUIs are opened on the client, meaning that the server cannot block them from opening, -However, it is possible to close these GUIs from the server. - -Flower pots are also not updated on the client when interaction is cancelled, this patch -also resolves this. - -Update adjacent blocks of doors, double plants, pistons and beds -when cancelling interaction. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.network.protocol.game.PacketPlayInBlockDig; - import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak; -+import net.minecraft.network.protocol.game.PacketPlayOutCloseWindow; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockCommand; -+import net.minecraft.world.level.block.BlockFlowerPot; - import net.minecraft.world.level.block.BlockJigsaw; - import net.minecraft.world.level.block.BlockStructure; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockposition, enumdirection, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); - if (event.isCancelled()) { - // Let the client know the block still exists -+ // Paper start - brute force neighbor blocks for any attached blocks -+ for (EnumDirection dir : EnumDirection.values()) { -+ this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.shift(dir))); -+ } -+ // Paper end - this.player.playerConnection.sendPacket(new PacketPlayOutBlockChange(this.world, blockposition)); - // Update any tile entity data for this block - TileEntity tileentity = this.world.getTileEntity(blockposition); -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - interactItemStack = itemstack.cloneItemStack(); - - if (event.useInteractedBlock() == Event.Result.DENY) { -+ - // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door. - if (iblockdata.getBlock() instanceof BlockDoor) { - boolean bottom = iblockdata.get(BlockDoor.HALF) == BlockPropertyDoubleBlockHalf.LOWER; -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - - // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) - entityplayer.playerConnection.sendPacket(new PacketPlayOutBlockChange(world, blockposition.up())); -+ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method -+ } else if (iblockdata.getBlock() instanceof BlockStructure) { -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); -+ } else if (iblockdata.getBlock() instanceof BlockCommand) { -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCloseWindow()); - } -+ // Paper end - extend Player Interact cancellation - entityplayer.getBukkitEntity().updateInventory(); // SPIGOT-2867 - enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS; - } else if (this.gamemode == EnumGamemode.SPECTATOR) { diff --git a/Spigot-Server-Patches/Extend-block-drop-capture-to-capture-all-items-added.patch b/Spigot-Server-Patches/Extend-block-drop-capture-to-capture-all-items-added.patch deleted file mode 100644 index dee692b501..0000000000 --- a/Spigot-Server-Patches/Extend-block-drop-capture-to-capture-all-items-added.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 17 Sep 2020 00:36:05 +0100 -Subject: [PATCH] Extend block drop capture to capture all items added to the - world - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -0,0 +0,0 @@ import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.ITileInventory; - import net.minecraft.world.InteractionResultWrapper; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.context.ItemActionContext; -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - // return true; // CraftBukkit - } - // CraftBukkit start -+ java.util.List itemsToDrop = world.captureDrops; // Paper - store current list -+ world.captureDrops = null; // Paper - Remove this earlier so that we can actually drop stuff - if (event.isDropItems()) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, world.captureDrops); -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref - } -- world.captureDrops = null; -+ //world.captureDrops = null; // Paper - move up - - // Drop event experience - if (flag && event != null) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.animal.EntityWaterAnimal; - import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.entity.npc.NPC; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.raid.PersistentRaid; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } else if (this.isUUIDTaken(entity)) { - return false; - } else { -+ // Paper start - capture all item additions to the world -+ if (captureDrops != null && entity instanceof EntityItem) { -+ captureDrops.add((EntityItem) entity); -+ return true; -+ } -+ // Paper end -+ - if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { - return false; - } diff --git a/Spigot-Server-Patches/Faster-redstone-torch-rapid-clock-removal.patch b/Spigot-Server-Patches/Faster-redstone-torch-rapid-clock-removal.patch deleted file mode 100644 index 8cada105dd..0000000000 --- a/Spigot-Server-Patches/Faster-redstone-torch-rapid-clock-removal.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Panzer -Date: Mon, 23 May 2016 12:12:37 +0200 -Subject: [PATCH] Faster redstone torch rapid clock removal - -Only resize the the redstone torch list once, since resizing arrays / lists is costly - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.biome.BiomeBase; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockFireAbstract; -+import net.minecraft.world.level.block.BlockRedstoneTorch; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.ITickable; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; - public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions -+ public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here - - public CraftWorld getWorld() { - return this.world; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneTorch.java -@@ -0,0 +0,0 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit - public class BlockRedstoneTorch extends BlockTorch { - - public static final BlockStateBoolean LIT = BlockProperties.r; -- private static final Map> b = new WeakHashMap(); -+ // Paper - Move the mapped list to World - - protected BlockRedstoneTorch(BlockBase.Info blockbase_info) { - super(blockbase_info, ParticleParamRedstone.a); -@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch { - @Override - public void tickAlways(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) { - boolean flag = this.a((World) worldserver, blockposition, iblockdata); -- List list = (List) BlockRedstoneTorch.b.get(worldserver); -- -- while (list != null && !list.isEmpty() && worldserver.getTime() - ((BlockRedstoneTorch.RedstoneUpdateInfo) list.get(0)).b > 60L) { -- list.remove(0); -+ // Paper start -+ java.util.ArrayDeque redstoneUpdateInfos = worldserver.redstoneUpdateInfos; -+ if (redstoneUpdateInfos != null) { -+ BlockRedstoneTorch.RedstoneUpdateInfo curr; -+ while ((curr = redstoneUpdateInfos.peek()) != null && worldserver.getTime() - curr.getTime() > 60L) { -+ redstoneUpdateInfos.poll(); -+ } - } -+ // Paper end - - // CraftBukkit start - org.bukkit.plugin.PluginManager manager = worldserver.getServer().getPluginManager(); -@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch { - } - - private static boolean a(World world, BlockPosition blockposition, boolean flag) { -- List list = (List) BlockRedstoneTorch.b.computeIfAbsent(world, (iblockaccess) -> { -- return Lists.newArrayList(); -- }); -+ // Paper start -+ java.util.ArrayDeque list = world.redstoneUpdateInfos; -+ if (list == null) { -+ list = world.redstoneUpdateInfos = new java.util.ArrayDeque<>(); -+ } -+ - - if (flag) { - list.add(new BlockRedstoneTorch.RedstoneUpdateInfo(blockposition.immutableCopy(), world.getTime())); -@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch { - - int i = 0; - -- for (int j = 0; j < list.size(); ++j) { -- BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = (BlockRedstoneTorch.RedstoneUpdateInfo) list.get(j); -- -+ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { -+ BlockRedstoneTorch.RedstoneUpdateInfo blockredstonetorch_redstoneupdateinfo = iterator.next(); -+ // Paper end - if (blockredstonetorch_redstoneupdateinfo.a.equals(blockposition)) { - ++i; - if (i >= 8) { -@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch { - public static class RedstoneUpdateInfo { - - private final BlockPosition a; -- private final long b; -+ private final long b; final long getTime() { return this.b; } // Paper - OBFHELPER - - public RedstoneUpdateInfo(BlockPosition blockposition, long i) { - this.a = blockposition; diff --git a/Spigot-Server-Patches/Fill-Profile-Property-Events.patch b/Spigot-Server-Patches/Fill-Profile-Property-Events.patch deleted file mode 100644 index ff53dd9224..0000000000 --- a/Spigot-Server-Patches/Fill-Profile-Property-Events.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 2 Jan 2018 00:31:26 -0500 -Subject: [PATCH] Fill Profile Property Events - -Allows plugins to populate profile properties from local sources to avoid calls out to Mojang API -to fill in textures for example. - -If Mojang API does need to be hit, event fire so you can get the results. - -This is useful for implementing a ProfileCache for Player Skulls - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperMinecraftSessionService.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper.profile; - - import com.mojang.authlib.Environment; -+import com.destroystokyo.paper.event.profile.FillProfileEvent; -+import com.destroystokyo.paper.event.profile.PreFillProfileEvent; - import com.mojang.authlib.GameProfile; - import com.mojang.authlib.minecraft.MinecraftProfileTexture; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -@@ -0,0 +0,0 @@ public class PaperMinecraftSessionService extends YggdrasilMinecraftSessionServi - - @Override - public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { -- return super.fillProfileProperties(profile, requireSecure); -+ CraftPlayerProfile playerProfile = (CraftPlayerProfile) CraftPlayerProfile.asBukkitMirror(profile); -+ new PreFillProfileEvent(playerProfile).callEvent(); -+ profile = playerProfile.getGameProfile(); -+ if (profile.isComplete() && profile.getProperties().containsKey("textures")) { -+ return profile; -+ } -+ GameProfile gameProfile = super.fillProfileProperties(profile, requireSecure); -+ new FillProfileEvent(CraftPlayerProfile.asBukkitMirror(gameProfile)).callEvent(); -+ return gameProfile; - } - - @Override diff --git a/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch deleted file mode 100644 index b94709a61f..0000000000 --- a/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sat, 12 Nov 2016 23:25:22 -0600 -Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ package com.destroystokyo.paper; - - import java.util.List; - -+import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void removeCorruptTEs() { - removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); - } -+ -+ public boolean filterNBTFromSpawnEgg = true; -+ private void fitlerNBTFromSpawnEgg() { -+ filterNBTFromSpawnEgg = getBoolean("filter-nbt-data-from-spawn-eggs-and-related", true); -+ if (!filterNBTFromSpawnEgg) { -+ Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - this.block = GameProfileSerializer.c(nbttagcompound.getCompound("BlockState")); -+ // Paper start - Block FallingBlocks with Command Blocks -+ // Check mappings on update - dc = "repeating_command_block" - dd = "chain_command_block" -+ final Block b = this.block.getBlock(); -+ if (this.world.paperConfig.filterNBTFromSpawnEgg && (b == Blocks.COMMAND_BLOCK || b == Blocks.REPEATING_COMMAND_BLOCK || b == Blocks.CHAIN_COMMAND_BLOCK)) { -+ this.block = Blocks.STONE.getBlockData(); -+ } -+ // Paper end - this.ticksLived = nbttagcompound.getInt("Time"); - if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) { - this.hurtEntities = nbttagcompound.getBoolean("HurtEntities"); diff --git a/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch deleted file mode 100644 index b706fccec8..0000000000 --- a/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Thu, 31 Jan 2019 16:33:36 -0500 -Subject: [PATCH] Fire BlockPistonRetractEvent for all empty pistons - -There is an explicit check in the handling code for empty pistons that -prevents sticky pistons from firing the event. However when we look back -at the history we see that this check was originally added so that ONLY -sticky pistons would fire the retract event. I'm not sure why. -https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/commits/1092acbddf07edfa4100bc6824504ac75088e913 - -Over the course of several updates, the meaning of that field appears to -have changed from "is NOT sticky" to "is sticky". So now its having the -opposite effect. Only normal pistons fire the retraction event. And like -all things in CB, it's just been carried around since. - -If we are to believe the history, the correct fix for this issue is to -flip it so it only fires for sticky pistons, but that puts us in a -bind. It's already firing for non-sticky pistons, changing it now would -likely result in breakage. Furthermore, there is little documentation as -to WHY that was ever intended to be the case. - -Instead we opt to remove the check entirely so that the event fires for -all piston types. - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -0,0 +0,0 @@ public class BlockPiston extends BlockDirectional { - } - - // CraftBukkit start -- if (!this.sticky) { -+ //if (!this.sticky) { // Paper - Prevents empty sticky pistons from firing retract - history behind is odd - org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); - BlockPistonRetractEvent event = new BlockPistonRetractEvent(block, ImmutableList.of(), CraftBlock.notchToBlockFace(enumdirection)); - world.getServer().getPluginManager().callEvent(event); -@@ -0,0 +0,0 @@ public class BlockPiston extends BlockDirectional { - if (event.isCancelled()) { - return; - } -- } -+ //} // Paper - // PAIL: checkME - what happened to setTypeAndData? - // CraftBukkit end - world.playBlockAction(blockposition, this, b0, enumdirection.c()); diff --git a/Spigot-Server-Patches/Fire-event-on-GS4-query.patch b/Spigot-Server-Patches/Fire-event-on-GS4-query.patch deleted file mode 100644 index 5c99706b1e..0000000000 --- a/Spigot-Server-Patches/Fire-event-on-GS4-query.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Sun, 17 Mar 2019 21:46:56 +0200 -Subject: [PATCH] Fire event on GS4 query - - -diff --git a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -+++ b/src/main/java/net/minecraft/server/rcon/RemoteStatusReply.java -@@ -0,0 +0,0 @@ public class RemoteStatusReply { - this.b.write(abyte, 0, abyte.length); - } - -+ public void writeString(String string) throws IOException { this.a(string); } // Paper - OBFHELPER - public void a(String s) throws IOException { - this.b.writeBytes(s); - this.b.write(0); - } -+ // Paper start - unchecked exception variant to use in Stream API -+ public void writeStringUnchecked(String string) { -+ try { -+ writeString(string); -+ } catch (IOException e) { -+ com.destroystokyo.paper.util.SneakyThrow.sneaky(e); -+ } -+ } -+ // Paper end - -+ public void writeInt(int i) throws IOException { this.a(i); } // Paper - OBFHELPER - public void a(int i) throws IOException { - this.b.write(i); - } - -+ public void writeShort(short i) throws IOException { this.a(i); } // Paper - OBFHELPER - public void a(short short0) throws IOException { - this.b.writeShort(Short.reverseBytes(short0)); - } -diff --git a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -+++ b/src/main/java/net/minecraft/server/rcon/thread/RemoteStatusListener.java -@@ -0,0 +0,0 @@ import java.util.Random; - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; - import net.minecraft.server.IMinecraftServer; -+import net.minecraft.server.dedicated.DedicatedServer; - import net.minecraft.server.rcon.RemoteStatusReply; - import net.minecraft.server.rcon.StatusChallengeUtils; - import org.apache.logging.log4j.LogManager; -@@ -0,0 +0,0 @@ public class RemoteStatusListener extends RemoteConnectionThread { - private static final Logger LOGGER = LogManager.getLogger(); - private long e; - private final int f; -- private final int g; -- private final int h; -- private final String i; -- private final String j; -+ private final int g; private final int getServerPort() { return this.g; } // Paper - OBFHELPER -+ private final int h; private final int getMaxPlayers() { return this.h; } // Paper - OBFHELPER -+ private final String i; private final String getMotd() { return this.i; } // Paper - OBFHELPER -+ private final String j; private final String getWorldName() { return this.j; } // Paper - OBFHELPER - private DatagramSocket k; - private final byte[] l = new byte[1460]; -- private String m; -+ private String m; public final String getServerHost() { return this.m; } // Paper - OBFHELPER - private String n; - private final Map o; -- private final RemoteStatusReply p; -+ private final RemoteStatusReply p; private final RemoteStatusReply getCachedFullResponse() { return this.p; } // Paper - OBFHELPER - private long q; -- private final IMinecraftServer r; -+ private final IMinecraftServer r; private final IMinecraftServer getServer() { return this.r; } // Paper - OBFHELPER - - private RemoteStatusListener(IMinecraftServer iminecraftserver, int i) { - super("Query Listener"); -@@ -0,0 +0,0 @@ public class RemoteStatusListener extends RemoteConnectionThread { - - remotestatusreply.a((int) 0); - remotestatusreply.a(this.a(datagrampacket.getSocketAddress())); -+ /* Paper start - GS4 Query event - remotestatusreply.a(this.i); - remotestatusreply.a("SMP"); - remotestatusreply.a(this.j); -@@ -0,0 +0,0 @@ public class RemoteStatusListener extends RemoteConnectionThread { - remotestatusreply.a(Integer.toString(this.h)); - remotestatusreply.a((short) this.g); - remotestatusreply.a(this.m); -+ */ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.BASIC; -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .gameVersion(this.getServer().getVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ remotestatusreply.writeString(queryResponse.getMotd()); -+ remotestatusreply.writeString("SMP"); -+ remotestatusreply.writeString(queryResponse.getMap()); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ remotestatusreply.writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ remotestatusreply.writeShort((short) queryResponse.getPort()); -+ remotestatusreply.writeString(queryResponse.getHostname()); -+ // Paper end - this.a(remotestatusreply.a(), datagrampacket); - RemoteStatusListener.LOGGER.debug("Status [{}]", socketaddress); - } -@@ -0,0 +0,0 @@ public class RemoteStatusListener extends RemoteConnectionThread { - this.p.a("splitnum"); - this.p.a((int) 128); - this.p.a((int) 0); -+ /* Paper start - GS4 Query event - this.p.a("hostname"); - this.p.a(this.i); - this.p.a("gametype"); -@@ -0,0 +0,0 @@ public class RemoteStatusListener extends RemoteConnectionThread { - } - - this.p.a((int) 0); -+ */ -+ // Pack plugins -+ java.util.List plugins = java.util.Collections.emptyList(); -+ org.bukkit.plugin.Plugin[] bukkitPlugins; -+ if (((DedicatedServer) this.getServer()).server.getQueryPlugins() && (bukkitPlugins = org.bukkit.Bukkit.getPluginManager().getPlugins()).length > 0) { -+ plugins = java.util.stream.Stream.of(bukkitPlugins) -+ .map(plugin -> com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation.of(plugin.getName(), plugin.getDescription().getVersion())) -+ .collect(java.util.stream.Collectors.toList()); -+ } -+ -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse queryResponse = com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.builder() -+ .motd(this.getMotd()) -+ .map(this.getWorldName()) -+ .currentPlayers(this.getServer().getPlayerCount()) -+ .maxPlayers(this.getMaxPlayers()) -+ .port(this.getServerPort()) -+ .hostname(this.getServerHost()) -+ .plugins(plugins) -+ .players(this.getServer().getPlayers()) -+ .gameVersion(this.getServer().getVersion()) -+ .serverVersion(org.bukkit.Bukkit.getServer().getName() + " on " + org.bukkit.Bukkit.getServer().getBukkitVersion()) -+ .build(); -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType queryType = -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryType.FULL; -+ com.destroystokyo.paper.event.server.GS4QueryEvent queryEvent = -+ new com.destroystokyo.paper.event.server.GS4QueryEvent(queryType, datagrampacket.getAddress(), queryResponse); -+ queryEvent.callEvent(); -+ queryResponse = queryEvent.getResponse(); -+ this.getCachedFullResponse().writeString("hostname"); -+ this.getCachedFullResponse().writeString(queryResponse.getMotd()); -+ this.getCachedFullResponse().writeString("gametype"); -+ this.getCachedFullResponse().writeString("SMP"); -+ this.getCachedFullResponse().writeString("game_id"); -+ this.getCachedFullResponse().writeString("MINECRAFT"); -+ this.getCachedFullResponse().writeString("version"); -+ this.getCachedFullResponse().writeString(queryResponse.getGameVersion()); -+ this.getCachedFullResponse().writeString("plugins"); -+ java.lang.StringBuilder pluginsString = new java.lang.StringBuilder(); -+ pluginsString.append(queryResponse.getServerVersion()); -+ if (!queryResponse.getPlugins().isEmpty()) { -+ pluginsString.append(": "); -+ java.util.Iterator iter = queryResponse.getPlugins().iterator(); -+ while (iter.hasNext()) { -+ com.destroystokyo.paper.event.server.GS4QueryEvent.QueryResponse.PluginInformation info = iter.next(); -+ pluginsString.append(info.getName()); -+ if (info.getVersion() != null) { -+ pluginsString.append(' ').append(info.getVersion().replace(";", ",")); -+ } -+ if (iter.hasNext()) { -+ pluginsString.append(';').append(' '); -+ } -+ } -+ } -+ this.getCachedFullResponse().writeString(pluginsString.toString()); -+ this.getCachedFullResponse().writeString("map"); -+ this.getCachedFullResponse().writeString(queryResponse.getMap()); -+ this.getCachedFullResponse().writeString("numplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getCurrentPlayers())); -+ this.getCachedFullResponse().writeString("maxplayers"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getMaxPlayers())); -+ this.getCachedFullResponse().writeString("hostport"); -+ this.getCachedFullResponse().writeString(Integer.toString(queryResponse.getPort())); -+ this.getCachedFullResponse().writeString("hostip"); -+ this.getCachedFullResponse().writeString(queryResponse.getHostname()); -+ // The "meaningless data" start, copied from above -+ this.getCachedFullResponse().writeInt(0); -+ this.getCachedFullResponse().writeInt(1); -+ this.getCachedFullResponse().writeString("player_"); -+ this.getCachedFullResponse().writeInt(0); -+ // "Meaningless data" end -+ queryResponse.getPlayers().forEach(this.getCachedFullResponse()::writeStringUnchecked); -+ this.getCachedFullResponse().writeInt(0); -+ // Paper end - return this.p.a(); - } - } diff --git a/Spigot-Server-Patches/Firework-API-s.patch b/Spigot-Server-Patches/Firework-API-s.patch deleted file mode 100644 index 679b40524e..0000000000 --- a/Spigot-Server-Patches/Firework-API-s.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 28 Dec 2016 07:18:33 +0100 -Subject: [PATCH] Firework API's - - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - return GameProfileSerializer.a(this.get(s)); - } - -+ public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER - public boolean b(String s) { - NBTBase nbtbase = this.get(s); - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireworks.java -@@ -0,0 +0,0 @@ public class EntityFireworks extends IProjectile { - public static final DataWatcherObject SHOT_AT_ANGLE = DataWatcher.a(EntityFireworks.class, DataWatcherRegistry.i); - private int ticksFlown; - public int expectedLifespan; -- private EntityLiving ridingEntity; -+ public EntityLiving ridingEntity; // Paper - public -+ public java.util.UUID spawningEntity; // Paper - - public EntityFireworks(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityFireworks extends IProjectile { - } - - nbttagcompound.setBoolean("ShotAtAngle", (Boolean) this.datawatcher.get(EntityFireworks.SHOT_AT_ANGLE)); -+ // Paper start -+ if (this.spawningEntity != null) { -+ nbttagcompound.setUUID("SpawningEntity", this.spawningEntity); -+ } -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public class EntityFireworks extends IProjectile { - if (nbttagcompound.hasKey("ShotAtAngle")) { - this.datawatcher.set(EntityFireworks.SHOT_AT_ANGLE, nbttagcompound.getBoolean("ShotAtAngle")); - } -- -+ // Paper start -+ if (nbttagcompound.hasUUID("SpawningEntity")) { -+ this.spawningEntity = nbttagcompound.getUUID("SpawningEntity"); -+ } -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/item/ItemCrossbow.java b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemCrossbow.java -+++ b/src/main/java/net/minecraft/world/item/ItemCrossbow.java -@@ -0,0 +0,0 @@ public class ItemCrossbow extends ItemProjectileWeapon implements ItemVanishable - - if (flag1) { - object = new EntityFireworks(world, itemstack1, entityliving, entityliving.locX(), entityliving.getHeadY() - 0.15000000596046448D, entityliving.locZ(), true); -+ ((EntityFireworks) object).spawningEntity = entityliving.getUniqueID(); // Paper - } else { - object = a(world, entityliving, itemstack, itemstack1); - if (flag || f3 != 0.0F) { -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -0,0 +0,0 @@ public class ItemFireworks extends Item { - Vec3D vec3d = itemactioncontext.getPos(); - EnumDirection enumdirection = itemactioncontext.getClickedFace(); - EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); -+ entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper - - world.addEntity(entityfireworks); - itemstack.subtract(1); -@@ -0,0 +0,0 @@ public class ItemFireworks extends Item { - ItemStack itemstack = entityhuman.b(enumhand); - - if (!world.isClientSide) { -- world.addEntity(new EntityFireworks(world, itemstack, entityhuman)); -+ // Paper start -+ final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); -+ entityfireworks.spawningEntity = entityhuman.getUniqueID(); -+ world.addEntity(entityfireworks); -+ // Paper end - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - - import java.util.Random; -+import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.projectile.EntityFireworks; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -@@ -0,0 +0,0 @@ public class CraftFirework extends CraftProjectile implements Firework { - public void setShotAtAngle(boolean shotAtAngle) { - getHandle().getDataWatcher().set(EntityFireworks.SHOT_AT_ANGLE, shotAtAngle); - } -+ -+ // Paper start -+ @Override -+ public java.util.UUID getSpawningEntity() { -+ return getHandle().spawningEntity; -+ } -+ -+ @Override -+ public org.bukkit.entity.LivingEntity getBoostedEntity() { -+ EntityLiving boostedEntity = getHandle().ridingEntity; -+ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/Spigot-Server-Patches/Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch deleted file mode 100644 index 026814dee7..0000000000 --- a/Spigot-Server-Patches/Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 Jul 2020 06:22:54 -0700 -Subject: [PATCH] Fix AdvancementDataPlayer leak due from quitting early in - login - -Move the criterion storage to the AdvancementDataPlayer object -itself, so the criterion object stores no references - and thus -needs no cleanup. - -diff --git a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -+++ b/src/main/java/net/minecraft/advancements/critereon/CriterionTriggerAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.loot.LootTableInfo; - - public abstract class CriterionTriggerAbstract implements CriterionTrigger { - -- private final Map>> a = Maps.newIdentityHashMap(); -+ //private final Map>> a = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak - - public CriterionTriggerAbstract() {} - - @Override - public final void a(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { -- ((Set) this.a.computeIfAbsent(advancementdataplayer, (advancementdataplayer1) -> { -+ (advancementdataplayer.criterionData.computeIfAbsent(this, (advancementdataplayer1) -> { // Paper - fix AdvancementDataPlayer leak - return Sets.newHashSet(); - })).add(criteriontrigger_a); - } - - @Override - public final void b(AdvancementDataPlayer advancementdataplayer, CriterionTrigger.a criteriontrigger_a) { -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null) { - set.remove(criteriontrigger_a); - if (set.isEmpty()) { -- this.a.remove(advancementdataplayer); -+ advancementdataplayer.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak - } - } - -@@ -0,0 +0,0 @@ public abstract class CriterionTriggerAbstract predicate) { - AdvancementDataPlayer advancementdataplayer = entityplayer.getAdvancementData(); -- Set> set = (Set) this.a.get(advancementdataplayer); -+ Set> set = (Set) advancementdataplayer.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak - - if (set != null && !set.isEmpty()) { - LootTableInfo loottableinfo = CriterionConditionEntity.b(entityplayer, entityplayer); -@@ -0,0 +0,0 @@ public abstract class CriterionTriggerAbstract> criterionData = Maps.newIdentityHashMap(); -+ // Paper end - fix advancement data player leakage -+ - public AdvancementDataPlayer(DataFixer datafixer, PlayerList playerlist, AdvancementDataWorld advancementdataworld, File file, EntityPlayer entityplayer) { - this.d = datafixer; - this.e = playerlist; diff --git a/Spigot-Server-Patches/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/Spigot-Server-Patches/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch deleted file mode 100644 index b82de9b4cc..0000000000 --- a/Spigot-Server-Patches/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lukasz Derlatka -Date: Mon, 11 Nov 2019 16:08:13 +0100 -Subject: [PATCH] Fix AssertionError when player hand set to empty type - -Fixes an AssertionError when setting the player's item in hand to null or a new ItemStack of Air in PlayerInteractEvent -Fixes GH-2718 - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 - return; - } -+ // Paper start -+ itemstack = this.player.getItemInHand(enumhand); -+ if (itemstack.isEmpty()) return; -+ // Paper end - EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand); - - if (enuminteractionresult.b()) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return predicate.test(this.getItemInMainHand().getItem()) || predicate.test(this.getItemInOffHand().getItem()); - } - -+ public final ItemStack getItemInHand(EnumHand enumhand) { return this.b(enumhand); } // Paper - OBFHELPER - public ItemStack b(EnumHand enumhand) { - if (enumhand == EnumHand.MAIN_HAND) { - return this.getEquipment(EnumItemSlot.MAINHAND); diff --git a/Spigot-Server-Patches/Fix-CB-call-to-changed-postToMainThread-method.patch b/Spigot-Server-Patches/Fix-CB-call-to-changed-postToMainThread-method.patch deleted file mode 100644 index 659181a05d..0000000000 --- a/Spigot-Server-Patches/Fix-CB-call-to-changed-postToMainThread-method.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Fri, 10 May 2019 18:38:19 +0100 -Subject: [PATCH] Fix CB call to changed postToMainThread method - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.networkManager.getClass(); - // CraftBukkit - Don't wait -- minecraftserver.postToMainThread(networkmanager::handleDisconnection); -+ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper - } - - private void a(T t0, Consumer consumer, BiFunction>> bifunction) { diff --git a/Spigot-Server-Patches/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/Spigot-Server-Patches/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch deleted file mode 100644 index fdf6f5072d..0000000000 --- a/Spigot-Server-Patches/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Sun, 4 Oct 2020 19:55:25 -0700 -Subject: [PATCH] Fix CME on adding a passenger in CreatureSpawnEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public Stream recursiveStream() { -- return Stream.concat(Stream.of(this), this.passengers.stream().flatMap(Entity::recursiveStream)); -+ return Stream.concat(Stream.of(this), com.google.common.collect.ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::recursiveStream)); // Paper - } - - public boolean hasSinglePlayerPassenger() { diff --git a/Spigot-Server-Patches/Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/Spigot-Server-Patches/Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch deleted file mode 100644 index 65601e031c..0000000000 --- a/Spigot-Server-Patches/Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 Apr 2016 17:48:50 -0400 -Subject: [PATCH] Fix Cancelling BlockPlaceEvent triggering physics - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public void b(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} - - public void applyPhysics(BlockPosition blockposition, Block block) { -+ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement - this.a(blockposition.west(), block, blockposition); - this.a(blockposition.east(), block, blockposition); - this.a(blockposition.down(), block, blockposition); diff --git a/Spigot-Server-Patches/Fix-Chunk-Post-Processing-deadlock-risk.patch b/Spigot-Server-Patches/Fix-Chunk-Post-Processing-deadlock-risk.patch deleted file mode 100644 index d2e39d5cbc..0000000000 --- a/Spigot-Server-Patches/Fix-Chunk-Post-Processing-deadlock-risk.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Apr 2020 04:36:11 -0400 -Subject: [PATCH] Fix Chunk Post Processing deadlock risk - -See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6 - -as part of post processing a chunk, we can call ChunkConverter. - -ChunkConverter then kicks off major physics updates, and when blocks -that have connections across chunk boundries occur, a recursive risk -can occur where A updates a block that triggers a physics request. - -That physics request may trigger a chunk request, that then enqueues -a task into the Mailbox ChunkTaskQueueSorter. - -If anything requests that same chunk that is in the middle of conversion, -it's mailbox queue is going to be held up, so the subsequent chunk request -will be unable to proceed. - -We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into -the executor so that the mailbox ChunkQueue is now considered empty. - -This successfully fixed a reoccurring and highly reproduceable crash -for heightmaps. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - return super.executeNext() || execChunkTask; // Paper - } - } finally { -+ playerChunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter - playerChunkMap.callbackExecutor.run(); - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - // CraftBukkit end - -+ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper -+ - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); -+ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, () -> PlayerChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request. - }); - - completablefuture1.thenAcceptAsync((either) -> { diff --git a/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch deleted file mode 100644 index 713912c88f..0000000000 --- a/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 6 Jul 2020 18:36:41 -0400 -Subject: [PATCH] Fix Concurrency issue in WeightedList - -if multiple threads from worldgen sort at same time, it will crash. -So make a copy of the list for sorting purposes. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorGate.java -@@ -0,0 +0,0 @@ public class BehaviorGate extends Behavior { - private final Set> b; - private final BehaviorGate.Order c; - private final BehaviorGate.Execution d; -- private final WeightedList> e = new WeightedList<>(); -+ private final WeightedList> e = new WeightedList<>(false); // Paper - don't use a clone - - public BehaviorGate(Map, MemoryStatus> map, Set> set, BehaviorGate.Order behaviorgate_order, BehaviorGate.Execution behaviorgate_execution, List, Integer>> list) { - super(map); -@@ -0,0 +0,0 @@ public class BehaviorGate extends Behavior { - }).forEach((behavior) -> { - behavior.g(worldserver, e0, i); - }); -- Set set = this.b; - BehaviorController behaviorcontroller = e0.getBehaviorController(); - -- set.forEach(behaviorcontroller::removeMemory); -+ this.b.forEach(behaviorcontroller::removeMemory); // Paper - decomp fix - } - - @Override -@@ -0,0 +0,0 @@ public class BehaviorGate extends Behavior { - - private final Consumer> c; - -- private Order(Consumer consumer) { -+ private Order(Consumer> consumer) { // Paper - decomp fix - this.c = consumer; - } - -diff --git a/src/main/java/net/minecraft/util/random/WeightedRandomList.java b/src/main/java/net/minecraft/util/random/WeightedRandomList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/random/WeightedRandomList.java -+++ b/src/main/java/net/minecraft/util/random/WeightedRandomList.java -@@ -0,0 +0,0 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.DataResult; - import com.mojang.serialization.Dynamic; - import com.mojang.serialization.DynamicOps; --import com.mojang.serialization.OptionalDynamic; -+ - import java.util.Comparator; - import java.util.List; - import java.util.Random; -@@ -0,0 +0,0 @@ import java.util.stream.Stream; - - public class WeightedList { - -- protected final List> a; -+ protected final List> list; // Paper - decompile conflict - private final Random b; -+ private final boolean isUnsafe; // Paper - -- public WeightedList() { -- this(Lists.newArrayList()); -+ // Paper start - add useClone option -+ public WeightedList() { this(true); } -+ public WeightedList(boolean isUnsafe) { -+ this(Lists.newArrayList(), isUnsafe); - } - -- private WeightedList(List> list) { -+ private WeightedList(List> list) { this(list, true); } -+ private WeightedList(List> list, boolean isUnsafe) { -+ this.isUnsafe = isUnsafe; -+ // Paper end - this.b = new Random(); -- this.a = Lists.newArrayList(list); -+ this.list = Lists.newArrayList(list); // Paper - decompile conflict - } - - public static Codec> a(Codec codec) { -- return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { -- return weightedlist.a; -+ return WeightedList.a.a(codec).listOf().xmap(WeightedList::new, (weightedlist) -> { // Paper - decompile conflict -+ return weightedlist.list; // Paper - decompile conflict - }); - } - - public WeightedList a(U u0, int i) { -- this.a.add(new WeightedList.a<>(u0, i)); -+ this.list.add(new WeightedList.a<>(u0, i)); // Paper - decompile conflict - return this; - } - -@@ -0,0 +0,0 @@ public class WeightedList { - } - - public WeightedList a(Random random) { -- this.a.forEach((weightedlist_a) -> { -- weightedlist_a.a(random.nextFloat()); -- }); -- this.a.sort(Comparator.comparingDouble((object) -> { -- return ((WeightedList.a) object).c(); -- })); -- return this; -+ // Paper start - make concurrent safe, work off a clone of the list -+ List> list = isUnsafe ? new java.util.ArrayList>(this.list) : this.list; -+ list.forEach((weightedlist_a) -> weightedlist_a.a(random.nextFloat())); -+ list.sort(Comparator.comparingDouble(a::c)); -+ return isUnsafe ? new WeightedList<>(list, isUnsafe) : this; -+ // Paper end - } - - public boolean b() { -- return this.a.isEmpty(); -+ return this.list.isEmpty(); // Paper - decompile conflict - } - - public Stream c() { -- return this.a.stream().map(WeightedList.a::a); -+ return this.list.stream().map(WeightedList.a::a); // Paper - decompile conflict - } - - public U b(Random random) { -@@ -0,0 +0,0 @@ public class WeightedList { - } - - public String toString() { -- return "WeightedList[" + this.a + "]"; -+ return "WeightedList[" + this.list + "]"; // Paper - decompile conflict - } - - public static class a { -@@ -0,0 +0,0 @@ public class WeightedList { - return new Codec>() { - public DataResult, T>> decode(DynamicOps dynamicops, T t0) { - Dynamic dynamic = new Dynamic(dynamicops, t0); -- OptionalDynamic optionaldynamic = dynamic.get("data"); -- Codec codec1 = codec; -- -- codec.getClass(); -- return optionaldynamic.flatMap(codec1::parse).map((object) -> { -+ return dynamic.get("data").flatMap(codec::parse).map((object) -> { // Paper - decompile error - return new WeightedList.a<>(object, dynamic.get("weight").asInt(1)); - }).map((weightedlist_a) -> { - return Pair.of(weightedlist_a, dynamicops.empty()); diff --git a/Spigot-Server-Patches/Fix-CraftEntity-hashCode.patch b/Spigot-Server-Patches/Fix-CraftEntity-hashCode.patch deleted file mode 100644 index 7b82d84c7d..0000000000 --- a/Spigot-Server-Patches/Fix-CraftEntity-hashCode.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 20:20:15 -0400 -Subject: [PATCH] Fix CraftEntity hashCode - -hashCodes are not allowed to change, however bukkit used a value -that does change, the entityId. - -When an entity is teleported dimensions, the entity reference is -replaced with a new one with a new entity ID. - -For hashCode, we can simply use the UUID's hashCode to keep -the hashCode from changing. - -equals() is ok to use getEntityId() because equals() should only -be true if both the left and right are the same reference. - -Since entity ids can not duplicate during runtime, this -check is essentially the same as this.getHandle() == other.getHandle() - -However, replaced it too to make it clearer of intent. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - return false; - } - final CraftEntity other = (CraftEntity) obj; -- return (this.getEntityId() == other.getEntityId()); -+ return (this.getHandle() == other.getHandle()); // Paper - while logically the same, this is clearer - } - -+ // Paper - Fix hashCode. entity ID's are not static. -+ // A CraftEntity can change reference to a new entity with a new ID, and hash codes should never change - @Override - public int hashCode() { -- int hash = 7; -- hash = 29 * hash + this.getEntityId(); -- return hash; -+ return getUniqueId().hashCode(); -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/Fix-CraftPotionBrewer-cache.patch b/Spigot-Server-Patches/Fix-CraftPotionBrewer-cache.patch deleted file mode 100644 index 992a2bfb05..0000000000 --- a/Spigot-Server-Patches/Fix-CraftPotionBrewer-cache.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Sceri -Date: Fri, 14 May 2021 19:06:51 +0500 -Subject: [PATCH] Fix CraftPotionBrewer cache - - -diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionBrewer.java -@@ -0,0 +0,0 @@ import org.bukkit.potion.PotionEffectType; - import org.bukkit.potion.PotionType; - - public class CraftPotionBrewer implements PotionBrewer { -- private static final Map> cache = Maps.newHashMap(); -+ private static final Map> cache = Maps.newHashMap(); // Paper - - @Override - public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { -- if (cache.containsKey(damage)) -- return cache.get(damage); -+ // Paper start -+ int key = damage.ordinal() << 2; -+ key |= (upgraded ? 1 : 0) << 1; -+ key |= extended ? 1 : 0; -+ -+ if (cache.containsKey(key)) -+ return cache.get(key); -+ // Paper end - - List mcEffects = PotionRegistry.a(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).a(); - -@@ -0,0 +0,0 @@ public class CraftPotionBrewer implements PotionBrewer { - builder.add(CraftPotionUtil.toBukkit(effect)); - } - -- cache.put(damage, builder.build()); -+ cache.put(key, builder.build()); // Paper - -- return cache.get(damage); -+ return cache.get(key); // Paper - } - - @Override diff --git a/Spigot-Server-Patches/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/Spigot-Server-Patches/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch deleted file mode 100644 index 5c269af548..0000000000 --- a/Spigot-Server-Patches/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ossi -Date: Fri, 12 Jun 2020 01:38:06 +0300 -Subject: [PATCH] Fix CraftScheduler#runTaskTimerAsynchronously(Plugin, - Consumer, long, long) scheduling a non-repeating task instead of - a repeating one. - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public void runTaskTimerAsynchronously(Plugin plugin, Consumer task, long delay, long period) throws IllegalArgumentException { -- runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); -+ runTaskTimerAsynchronously(plugin, (Object) task, delay, period); - } - - @Override diff --git a/Spigot-Server-Patches/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/Spigot-Server-Patches/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch deleted file mode 100644 index dad391c30d..0000000000 --- a/Spigot-Server-Patches/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 13 May 2019 21:10:59 -0700 -Subject: [PATCH] Fix CraftServer#isPrimaryThread and MinecraftServer - isMainThread - -md_5 changed it so he could shut down the server asynchronously -from watchdog, although we have patches that prevent that type -of behavior for this exact reason. - -md_5 also placed code in PlayerConnectionUtils that would have -solved https://bugs.mojang.com/browse/MC-142590, making the change -to MinecraftServer#isMainThread irrelevant. -By reverting his change to MinecraftServer#isMainThread packet -handling that should have been handled synchronously will be handled -synchronously when the server gets shut down. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Thu, 17 Dec 2020 15:25:49 -0600 -Subject: [PATCH] Fix CraftSound backwards compatibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java -@@ -0,0 +0,0 @@ public class CraftSound { - public static Sound getBukkit(SoundEffect soundEffect) { - return Registry.SOUNDS.get(CraftNamespacedKey.fromMinecraft(IRegistry.SOUND_EVENT.getKey(soundEffect))); - } -+ -+ // Paper start -+ public static String getSound(Sound sound) { -+ return sound.getKey().getKey(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Fix-CraftTeam-null-check.patch b/Spigot-Server-Patches/Fix-CraftTeam-null-check.patch deleted file mode 100644 index cab5cbc511..0000000000 --- a/Spigot-Server-Patches/Fix-CraftTeam-null-check.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: foss-mc <69294560+foss-mc@users.noreply.github.com> -Date: Sun, 30 Aug 2020 15:30:29 +0800 -Subject: [PATCH] Fix CraftTeam null check - - -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java -@@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - - @Override - public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { -- Validate.notNull("Entry cannot be null"); -+ Validate.notNull(entry, "Entry cannot be null"); // Paper - - CraftScoreboard scoreboard = checkState(); - diff --git a/Spigot-Server-Patches/Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/Spigot-Server-Patches/Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch deleted file mode 100644 index 5f9ccd08d4..0000000000 --- a/Spigot-Server-Patches/Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Jan 2019 00:08:15 -0500 -Subject: [PATCH] Fix Custom Shapeless Custom Crafting Recipes - -Mojang implemented Shapeless different than Shaped - -This made the Bukkit RecipeChoice API not work for Shapeless. - -This reimplements vanilla logic using the same test logic as Shaped - -diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipes.java -@@ -0,0 +0,0 @@ public class ShapelessRecipes implements RecipeCrafting { - AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager(); - int i = 0; - -+ // Paper start -+ java.util.List providedItems = new java.util.ArrayList<>(); -+ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); -+ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); -+ // Paper end - for (int j = 0; j < inventorycrafting.getSize(); ++j) { - ItemStack itemstack = inventorycrafting.getItem(j); - - if (!itemstack.isEmpty()) { -- ++i; -- autorecipestackmanager.a(itemstack, 1); -+ // Paper start -+ itemstack = itemstack.cloneItemStack(); -+ providedItems.add(itemstack); -+ for (RecipeItemStack ingredient : ingredients) { -+ if (ingredient.test(itemstack)) { -+ matchedProvided.increment(itemstack); -+ matchedIngredients.increment(ingredient); -+ } -+ } -+ // Paper end - } - } - -- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null); -+ // Paper start -+ if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { -+ return false; -+ } -+ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); -+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); -+ ingredients.sort(java.util.Comparator.comparingInt((RecipeItemStack c) -> (int) matchedIngredients.getCount(c))); -+ -+ PROVIDED: -+ for (ItemStack provided : providedItems) { -+ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { -+ RecipeItemStack ingredient = itIngredient.next(); -+ if (ingredient.test(provided)) { -+ itIngredient.remove(); -+ continue PROVIDED; -+ } -+ } -+ return false; -+ } -+ return ingredients.isEmpty(); -+ // Paper end - } - - public ItemStack a(InventoryCrafting inventorycrafting) { diff --git a/Spigot-Server-Patches/Fix-Double-World-Add-issues.patch b/Spigot-Server-Patches/Fix-Double-World-Add-issues.patch deleted file mode 100644 index ba2afb67b3..0000000000 --- a/Spigot-Server-Patches/Fix-Double-World-Add-issues.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 21 Jun 2016 22:54:34 -0400 -Subject: [PATCH] Fix Double World Add issues - -Vanilla will double add Spider Jockeys to the world, so ignore already added. - -Also add debug if something else tries to, and abort before world gets bad state - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit start - private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot -+ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper - if (entity.dead) { - // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit - return false; diff --git a/Spigot-Server-Patches/Fix-Dragon-Server-Crashes.patch b/Spigot-Server-Patches/Fix-Dragon-Server-Crashes.patch deleted file mode 100644 index f8bb0eb299..0000000000 --- a/Spigot-Server-Patches/Fix-Dragon-Server-Crashes.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Mar 2018 20:52:07 -0400 -Subject: [PATCH] Fix Dragon Server Crashes - -If the dragon tries to find "ground" and hits a hole, or off edge, -it will infinitely keep looking for non air and eventually crash. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonControllerLandedFlame.java -@@ -0,0 +0,0 @@ public class DragonControllerLandedFlame extends AbstractDragonControllerLanded - double d3 = d2; - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(d0, d2, d1); - -- while (this.a.world.isEmpty(blockposition_mutableblockposition)) { -+ while (this.a.world.isEmpty(blockposition_mutableblockposition ) && d2 > 0) { // Paper - --d3; - if (d3 < 0.0D) { - d3 = d2; diff --git a/Spigot-Server-Patches/Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/Spigot-Server-Patches/Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch deleted file mode 100644 index 621e56cf01..0000000000 --- a/Spigot-Server-Patches/Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 25 Aug 2020 20:45:36 -0400 -Subject: [PATCH] Fix Entity Teleportation and cancel velocity if teleported - -Uses correct setPositionRotation for Entity teleporting instead of setLocation -as this is how Vanilla teleports entities. - -Cancel any pending motion when teleported. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - public void a(PacketPlayInTeleportAccept packetplayinteleportaccept) { - PlayerConnectionUtils.ensureMainThread(packetplayinteleportaccept, this, this.player.getWorldServer()); - if (packetplayinteleportaccept.b() == this.teleportAwait && this.teleportPos != null) { // CraftBukkit -- this.player.setLocation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); -+ this.player.setPositionRotation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); // Paper - use proper setPositionRotation for teleportation - this.o = this.teleportPos.x; - this.p = this.teleportPos.y; - this.q = this.teleportPos.z; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - this.A = this.e; -- this.player.setLocation(d0, d1, d2, f, f1); -+ this.player.setPositionRotation(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation - this.player.forceCheckHighPriority(); // Paper - this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - // CraftBukkit start - private static final int CURRENT_LEVEL = 2; -+ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation - static boolean isLevelAtLeast(NBTTagCompound tag, int level) { - return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void setPositionRotation(double d0, double d1, double d2, float f, float f1) { -+ // Paper - cancel entity velocity if teleported -+ if (!preserveMotion) { -+ this.mot = Vec3D.ORIGIN; -+ } else { -+ this.preserveMotion = false; -+ } -+ // Paper end - this.g(d0, d1, d2); - this.yaw = f; - this.pitch = f1; -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - return; - } - -+ entity.preserveMotion = true; // Paper - preserve entity motion from tag - entity.setPositionRotation(entity.locX(), entity.locY(), entity.locZ(), world.random.nextFloat() * 360.0F, 0.0F); - if (entity instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) entity; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - } - - // entity.setLocation() throws no event, and so cannot be cancelled -- entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); -+ entity.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); // Paper - use proper setPosition, as per vanilla teleporting - // SPIGOT-619: Force sync head rotation also - entity.setHeadRotation(location.getYaw()); - ((net.minecraft.server.level.WorldServer) entity.world).chunkCheck(entity); // Spigot - register to new chunk diff --git a/Spigot-Server-Patches/Fix-Light-Command.patch b/Spigot-Server-Patches/Fix-Light-Command.patch deleted file mode 100644 index c4cc00e080..0000000000 --- a/Spigot-Server-Patches/Fix-Light-Command.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 7 May 2020 19:17:36 -0400 -Subject: [PATCH] Fix Light Command - -This lets you run /paper fixlight (max 5) to automatically -fix all light data in the chunks. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ import com.google.common.collect.ImmutableSet; - import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.resources.MinecraftKey; - import com.google.gson.JsonObject; - import com.google.gson.internal.Streams; -@@ -0,0 +0,0 @@ import com.google.gson.stream.JsonWriter; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.LightEngineThreaded; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.ChunkCoordIntPair; --import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.chunk.Chunk; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; -@@ -0,0 +0,0 @@ import org.bukkit.command.Command; - import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.entity.Player; - - import java.io.File; -@@ -0,0 +0,0 @@ import java.io.PrintStream; - import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; -+import java.util.ArrayDeque; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; - import java.util.Collections; -+import java.util.Deque; - import java.util.Iterator; - import java.util.List; - import java.util.Locale; -@@ -0,0 +0,0 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); - - public PaperCommand(String name) { - super(name); -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - case "syncloadinfo": - this.doSyncLoadInfo(sender, args); - break; -+ case "fixlight": -+ this.doFixLight(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doFixLight(CommandSender sender, String[] args) { -+ if (!(sender instanceof Player)) { -+ sender.sendMessage("Only players can use this command"); -+ return; -+ } -+ int radius = 2; -+ if (args.length > 1) { -+ try { -+ radius = Math.min(5, Integer.parseInt(args[1])); -+ } catch (Exception e) { -+ sender.sendMessage("Not a number"); -+ return; -+ } -+ -+ } -+ -+ CraftPlayer player = (CraftPlayer) sender; -+ EntityPlayer handle = player.getHandle(); -+ WorldServer world = (WorldServer) handle.world; -+ LightEngineThreaded lightengine = world.getChunkProvider().getLightEngine(); -+ -+ BlockPosition center = MCUtil.toBlockPosition(player.getLocation()); -+ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); -+ updateLight(sender, world, lightengine, queue); -+ } -+ -+ private void updateLight(CommandSender sender, WorldServer world, LightEngineThreaded lightengine, Deque queue) { -+ ChunkCoordIntPair coord = queue.poll(); -+ if (coord == null) { -+ sender.sendMessage("All Chunks Light updated"); -+ return; -+ } -+ world.getChunkProvider().getChunkAtAsynchronously(coord.x, coord.z, false, false).whenCompleteAsync((either, ex) -> { -+ if (ex != null) { -+ sender.sendMessage("Error loading chunk " + coord); -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ Chunk chunk = (Chunk) either.left().orElse(null); -+ if (chunk == null) { -+ updateLight(sender, world, lightengine, queue); -+ return; -+ } -+ lightengine.a(world.paperConfig.lightQueueSize + 16 * 256); // ensure full chunk can fit into queue -+ sender.sendMessage("Updating Light " + coord); -+ int cx = chunk.getPos().x << 4; -+ int cz = chunk.getPos().z << 4; -+ for (int y = 0; y < world.getHeight(); y++) { -+ for (int x = 0; x < 16; x++) { -+ for (int z = 0; z < 16; z++) { -+ BlockPosition pos = new BlockPosition(cx + x, y, cz + z); -+ lightengine.a(pos); -+ } -+ } -+ } -+ lightengine.queueUpdate(); -+ PlayerChunk visibleChunk = world.getChunkProvider().playerChunkMap.getVisibleChunk(chunk.coordinateKey); -+ if (visibleChunk != null) { -+ world.getChunkProvider().playerChunkMap.addLightTask(visibleChunk, () -> { -+ MinecraftServer.getServer().processQueue.add(() -> { -+ visibleChunk.sendPacketToTrackedPlayers(new PacketPlayOutLightUpdate(chunk.getPos(), lightengine, true), false); -+ updateLight(sender, world, lightengine, queue); -+ }); -+ }); -+ } else { -+ updateLight(sender, world, lightengine, queue); -+ } -+ lightengine.a(world.paperConfig.lightQueueSize); -+ }, MinecraftServer.getServer()); -+ } -+ - private void doSyncLoadInfo(CommandSender sender, String[] args) { - if (!SyncLoadFinder.ENABLED) { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - - } - -+ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { a(packet, flag); } // Paper - OBFHELPER - private void a(Packet packet, boolean flag) { - // Paper start - per player view distance - // there can be potential desync with player's last mapped section and the view distance map, so use the -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); - - this.worldLoadListener = worldloadlistener; -- ThreadedMailbox threadedmailbox1 = ThreadedMailbox.a(executor, "light"); -+ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper - - this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); - this.mailboxWorldGen = this.p.a(threadedmailbox, false); - this.mailboxMain = this.p.a(mailbox, false); -+ this.mailboxLight = this.p.a(lightthreaded, false);// Paper - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); - this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper - this.l = supplier; diff --git a/Spigot-Server-Patches/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/Spigot-Server-Patches/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch deleted file mode 100644 index 2b9771e2e0..0000000000 --- a/Spigot-Server-Patches/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 00:05:46 -0400 -Subject: [PATCH] Fix Longstanding Broken behavior of PlayerJoinEvent - -For years, plugin developers have had to delay many things they do -inside of the PlayerJoinEvent by 1 tick to make it actually work. - -This all boiled down to 1 reason why: The event fired before the -player was fully ready and joined to the world! - -Additionally, if that player logged out on a vehicle, the event -fired before the vehicle was even loaded, so that plugins had no -access to the vehicle during this event either. - -This change finally fixes this issue, fully preparing the player -into the world as a fully ready entity, vehicle included. - -There should be no plugins that break because of this change, but might -improve consistency with other plugins instead. - -For example, if 2 plugins listens to this event, and the first one -teleported the player in the event, then the 2nd plugin actually -would be getting a valid player! - -This was very non deterministic. This change will ensure every plugin -receives a deterministic result, and should no longer require 1 tick -delays anymore. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public double maxHealthCache; - public boolean joining = true; - public boolean sentListPacket = false; -+ public boolean supressTrackerForLogin = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - } - -- protected void addEntity(Entity entity) { -+ public void addEntity(Entity entity) { // Paper - protected -> public - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot - // Paper start - ignore and warn about illegal addEntity calls instead of crashing server - if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - .printStackTrace(); - return; - } -+ if (entity instanceof EntityPlayer && ((EntityPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets - // Paper end - if (!(entity instanceof EntityComplexPart)) { - EntityTypes entitytypes = entity.getEntityType(); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - this.j.put(entityplayer.getUniqueID(), entityplayer); - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[]{entityplayer})); // CraftBukkit - replaced with loop below - -+ // Paper start - correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks -+ entityplayer.supressTrackerForLogin = true; -+ worldserver1.addPlayerJoin(entityplayer); -+ this.server.getBossBattleCustomData().a(entityplayer); // see commented out section below worldserver.addPlayerJoin(entityplayer); -+ mountSavedVehicle(entityplayer, worldserver1, nbttagcompound); -+ // Paper end - // CraftBukkit start - PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(cserver.getPlayer(entityplayer), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure - cserver.getPluginManager().callEvent(playerJoinEvent); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer1})); - } - entityplayer.sentListPacket = true; -+ entityplayer.supressTrackerForLogin = false; // Paper -+ ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // Paper - track entity now - // CraftBukkit end - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(entityplayer.getId(), entityplayer.getDataWatcher(), true)); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn -@@ -0,0 +0,0 @@ public abstract class PlayerList { - playerconnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobeffect)); - } - -+ // Paper start - move vehicle into method so it can be called above - short circuit around that code -+ onPlayerJoinFinish(entityplayer, worldserver1, s1); -+ } -+ private void mountSavedVehicle(EntityPlayer entityplayer, WorldServer worldserver1, NBTTagCompound nbttagcompound) { -+ // Paper end - if (nbttagcompound != null && nbttagcompound.hasKeyOfType("RootVehicle", 10)) { - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); - // CraftBukkit start -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - } - -+ // Paper start -+ } -+ public void onPlayerJoinFinish(EntityPlayer entityplayer, WorldServer worldserver1, String s1) { -+ // Paper end - entityplayer.syncInventory(); - // Paper start - Add to collideRule team if needed - final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); diff --git a/Spigot-Server-Patches/Fix-MC-117075-TE-Unload-Lag-Spike.patch b/Spigot-Server-Patches/Fix-MC-117075-TE-Unload-Lag-Spike.patch deleted file mode 100644 index 93dda02681..0000000000 --- a/Spigot-Server-Patches/Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mezz -Date: Wed, 9 Aug 2017 17:51:22 -0500 -Subject: [PATCH] Fix MC-117075: TE Unload Lag Spike - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - gameprofilerfiller.enter("blockEntities"); - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { -- this.tileEntityListTick.removeAll(this.tileEntityListUnload); -+ // Paper start - Use alternate implementation with faster contains -+ java.util.Set toRemove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); -+ toRemove.addAll(tileEntityListUnload); -+ this.tileEntityListTick.removeAll(toRemove); -+ // Paper end - //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } diff --git a/Spigot-Server-Patches/Fix-MC-148809-Increase-structure-block-data-length-t.patch b/Spigot-Server-Patches/Fix-MC-148809-Increase-structure-block-data-length-t.patch deleted file mode 100644 index b17f987517..0000000000 --- a/Spigot-Server-Patches/Fix-MC-148809-Increase-structure-block-data-length-t.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SamB440 -Date: Fri, 21 May 2021 00:22:09 +0100 -Subject: [PATCH] Fix MC-148809: Increase structure block data length to 128 - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInStruct.java -@@ -0,0 +0,0 @@ public class PacketPlayInStruct implements Packet { - this.f = new BlockPosition(MathHelper.clamp(packetdataserializer.readByte(), 0, 48), MathHelper.clamp(packetdataserializer.readByte(), 0, 48), MathHelper.clamp(packetdataserializer.readByte(), 0, 48)); - this.g = (EnumBlockMirror) packetdataserializer.a(EnumBlockMirror.class); - this.h = (EnumBlockRotation) packetdataserializer.a(EnumBlockRotation.class); -- this.i = packetdataserializer.e(12); -+ this.i = packetdataserializer.e(128); // Paper - Fix MC-148809, increase max character input to 128 - this.m = MathHelper.a(packetdataserializer.readFloat(), 0.0F, 1.0F); - this.n = packetdataserializer.j(); - byte b0 = packetdataserializer.readByte(); diff --git a/Spigot-Server-Patches/Fix-MC-158900.patch b/Spigot-Server-Patches/Fix-MC-158900.patch deleted file mode 100644 index 3fa552211c..0000000000 --- a/Spigot-Server-Patches/Fix-MC-158900.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 13 Aug 2019 06:35:17 -0700 -Subject: [PATCH] Fix MC-158900 - -The problem was we were checking isExpired() on the entry, but if it -was expired at that point, then it would be null. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - -- if (getProfileBans().isBanned(gameprofile) && !getProfileBans().get(gameprofile).hasExpired()) { -- GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile); -+ // Paper start - Fix MC-158900 -+ GameProfileBanEntry gameprofilebanentry; -+ if (getProfileBans().isBanned(gameprofile) && (gameprofilebanentry = getProfileBans().get(gameprofile)) != null) { -+ // Paper end - - chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); - if (gameprofilebanentry.getExpires() != null) { diff --git a/Spigot-Server-Patches/Fix-MC-161754.patch b/Spigot-Server-Patches/Fix-MC-161754.patch deleted file mode 100644 index 0e0f6f62be..0000000000 --- a/Spigot-Server-Patches/Fix-MC-161754.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 24 Sep 2019 16:03:00 -0700 -Subject: [PATCH] Fix MC-161754 - -Fixes https://github.com/PaperMC/Paper/issues/2580 - -We can use an entity valid check since this method is invoked for -each inventory iteraction (thanks to CB) and on player tick (vanilla). - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerHorse.java -@@ -0,0 +0,0 @@ public class ContainerHorse extends Container { - - @Override - public boolean canUse(EntityHuman entityhuman) { -- return this.c.a(entityhuman) && this.d.isAlive() && this.d.g((Entity) entityhuman) < 8.0F; -+ return this.c.a(entityhuman) && (this.d.isAlive() && this.d.valid) && this.d.g((Entity) entityhuman) < 8.0F; // Paper - Fix MC-161754 - } - - @Override diff --git a/Spigot-Server-Patches/Fix-MC-187716-Use-configured-height.patch b/Spigot-Server-Patches/Fix-MC-187716-Use-configured-height.patch deleted file mode 100644 index abc8f6cb86..0000000000 --- a/Spigot-Server-Patches/Fix-MC-187716-Use-configured-height.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 15 Aug 2020 08:04:49 -0500 -Subject: [PATCH] Fix MC-187716 Use configured height - - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNether.java -@@ -0,0 +0,0 @@ public class WorldGenSurfaceNether extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherAbstract.java -@@ -0,0 +0,0 @@ public abstract class WorldGenSurfaceNetherAbstract extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata5 = ichunkaccess.getType(blockposition_mutableblockposition); - int l2; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/WorldGenSurfaceNetherForest.java -@@ -0,0 +0,0 @@ public class WorldGenSurfaceNetherForest extends WorldGenSurface= 0; --k2) { -+ for (int k2 = k; k2 >= 0; --k2) { // Paper - fix MC-187716 - use configured height - blockposition_mutableblockposition.d(k1, k2, l1); - IBlockData iblockdata3 = worldgensurfaceconfigurationbase.a(); - IBlockData iblockdata4 = ichunkaccess.getType(blockposition_mutableblockposition); diff --git a/Spigot-Server-Patches/Fix-MC-197271.patch b/Spigot-Server-Patches/Fix-MC-197271.patch deleted file mode 100644 index 0d804913d5..0000000000 --- a/Spigot-Server-Patches/Fix-MC-197271.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ishland -Date: Sun, 23 Aug 2020 10:57:44 +0200 -Subject: [PATCH] Fix MC-197271 - -This patch only fixes an issue for servers running OpenJ9. - -diff --git a/src/main/java/net/minecraft/data/RegistryGeneration.java b/src/main/java/net/minecraft/data/RegistryGeneration.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/data/RegistryGeneration.java -+++ b/src/main/java/net/minecraft/data/RegistryGeneration.java -@@ -0,0 +0,0 @@ public class RegistryGeneration { - public static final IRegistry g = a(IRegistry.aw, () -> { - return ProcessorLists.b; - }); -- public static final IRegistry h = a(IRegistry.ax, WorldGenFeaturePieces::a); -+ public static final IRegistry h = a(IRegistry.ax, () -> WorldGenFeaturePieces.a()); // Paper - MC-197271 - public static final IRegistry WORLDGEN_BIOME = a(IRegistry.ay, () -> { - return BiomeRegistry.a; - }); -- public static final IRegistry j = a(IRegistry.ar, GeneratorSettingBase::i); -+ public static final IRegistry j = a(IRegistry.ar, () -> GeneratorSettingBase.i()); // Paper - MC-197271 - - private static IRegistry a(ResourceKey> resourcekey, Supplier supplier) { - return a(resourcekey, Lifecycle.stable(), supplier); -@@ -0,0 +0,0 @@ public class RegistryGeneration { - MinecraftKey minecraftkey = resourcekey.a(); - - RegistryGeneration.k.put(minecraftkey, supplier); -- IRegistryWritable iregistrywritable = RegistryGeneration.l; -+ IRegistryWritable iregistrywritable = (IRegistryWritable) RegistryGeneration.l; // Paper - decompile fix - -- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); -+ return (R) iregistrywritable.a((ResourceKey) resourcekey, r0, lifecycle); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, String s, T t0) { -@@ -0,0 +0,0 @@ public class RegistryGeneration { - } - - public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { -- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); -+ return (T) ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.f(), minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, int i, ResourceKey resourcekey, T t0) { -- return ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); -+ return (T) ((IRegistryWritable) iregistry).a(i, resourcekey, t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static void a() {} diff --git a/Spigot-Server-Patches/Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch b/Spigot-Server-Patches/Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch deleted file mode 100644 index db90121d4b..0000000000 --- a/Spigot-Server-Patches/Fix-MC-99259-Wither-Boss-Bar-doesn-t-update-until-in.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Thu, 20 Aug 2020 19:24:13 -0700 -Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until - invulnerability period is over - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit - } - -- this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); -+ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down - } -+ this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends) - } - - public static boolean c(IBlockData iblockdata) { diff --git a/Spigot-Server-Patches/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/Spigot-Server-Patches/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch deleted file mode 100644 index d23e0dd88c..0000000000 --- a/Spigot-Server-Patches/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 01:31:06 -0400 -Subject: [PATCH] Fix Non Full Status Chunk NBT Memory Leak - -Any full status chunk that was requested for any status less than full -would hold onto their entire nbt tree and every variable in that function. - -This was due to use of a lambda that persists on the Chunk object -until that chunk reaches FULL status. - -With introduction of no tick, we greatly increased the number of non -full chunks so this was really starting to hurt. - -We further improve it by making a copy of the nbt tag with only the memory -it needs, so that we dont have to hold a copy to the entire compound. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.core.RegistryBlocks; - import net.minecraft.core.SectionPosition; -+import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagLongArray; -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - object2 = protochunkticklist1; - } - -- object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -- loadEntities(nbttagcompound1, chunk); -- // CraftBukkit start - load chunk persistent data from nbt -- net.minecraft.nbt.NBTBase persistentBase = nbttagcompound1.get("ChunkBukkitValues"); -- if (persistentBase instanceof NBTTagCompound) { -- chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); -- } -- // CraftBukkit end -- }); -+ object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. -+ createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here -+ );// Paper end - } else { - ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter - -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading - } - } -+ // Paper start -+ -+ /** -+ * This wrapper will error out if any key is accessed that wasn't copied so we can catch it easy on an update -+ */ -+ private static class SafeNBTCopy extends NBTTagCompound { -+ private final java.util.Set keys = new java.util.HashSet(); -+ public SafeNBTCopy(NBTTagCompound base, String... keys) { -+ for (String key : keys) { -+ this.keys.add(key); -+ final NBTBase nbtBase = base.get(key); -+ if (nbtBase != null) { -+ this.set(key, nbtBase); -+ } -+ } -+ } -+ -+ @Override -+ public boolean hasKey(String s) { -+ if (super.hasKey(s)) { -+ return true; -+ } else if (keys.contains(s)) { -+ return false; -+ } -+ throw new IllegalStateException("Missing Key " + s + " in SafeNBTCopy"); -+ } -+ -+ @Override -+ public boolean hasKeyOfType(String s, int i) { -+ return hasKey(s) && super.hasKeyOfType(s, i); -+ } -+ } -+ private static java.util.function.Consumer createLoadEntitiesConsumer(NBTTagCompound nbt) { -+ return (chunk) -> { -+ loadEntities(nbt, chunk); -+ // CraftBukkit start - load chunk persistent data from nbt -+ NBTBase persistentBase = nbt.get("ChunkBukkitValues"); -+ if (persistentBase instanceof NBTTagCompound) { -+ chunk.persistentDataContainer.putAll((NBTTagCompound) persistentBase); -+ } -+ // CraftBukkit end -+ }; -+ } -+ // Paper end - - // Paper start - async chunk save for unload - public static final class AsyncSaveData { diff --git a/Spigot-Server-Patches/Fix-Not-a-string-Map-Conversion-spam.patch b/Spigot-Server-Patches/Fix-Not-a-string-Map-Conversion-spam.patch deleted file mode 100644 index b5c0e017cf..0000000000 --- a/Spigot-Server-Patches/Fix-Not-a-string-Map-Conversion-spam.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Oct 2020 00:00:25 -0400 -Subject: [PATCH] Fix "Not a string" Map Conversion spam - -The maps did convert successfully, but had noisy logs due to Spigot -implementing this logic incorrectly. - -This stops the spam by converting the old format to new before -requesting the world. - -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -0,0 +0,0 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTBase; -+import net.minecraft.nbt.NBTNumber; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.PacketPlayOutMap; -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - - @Override - public void a(NBTTagCompound nbttagcompound) { -- DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("dimension"))); // CraftBukkit - decompile error -+ // Paper start - fix "Not a string" spam -+ NBTBase dimension = nbttagcompound.get("dimension"); -+ if (dimension instanceof NBTNumber && ((NBTNumber) dimension).asInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { -+ long least = nbttagcompound.getLong("UUIDLeast"); -+ long most = nbttagcompound.getLong("UUIDMost"); -+ -+ if (least != 0L && most != 0L) { -+ this.uniqueId = new UUID(most, least); -+ CraftWorld world = (CraftWorld) server.getWorld(this.uniqueId); -+ if (world != null) { -+ dimension = NBTTagString.create("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); -+ } else { -+ dimension = NBTTagString.create("bukkit:_invalidworld_"); -+ } -+ } else { -+ dimension = NBTTagString.create("bukkit:_invalidworld_"); -+ } -+ } -+ DataResult> dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, dimension)); // CraftBukkit - decompile error -+ // Paper end - fix "Not a string" spam - Logger logger = WorldMap.LOGGER; - - logger.getClass(); diff --git a/Spigot-Server-Patches/Fix-Old-Sign-Conversion.patch b/Spigot-Server-Patches/Fix-Old-Sign-Conversion.patch deleted file mode 100644 index cfd6043320..0000000000 --- a/Spigot-Server-Patches/Fix-Old-Sign-Conversion.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 17 Jun 2016 20:50:11 -0400 -Subject: [PATCH] Fix Old Sign Conversion - -1) Sign loading code was trying to parse the JSON before the check for oldSign. - That code could then skip the old sign converting code if it triggers a JSON parse exception. -2) New Mojang Schematic system has Tile Entities in the new converted format, but missing the Bukkit.isConverted flag - This causes Igloos and such to render broken signs. We fix this by ignoring sign conversion for Defined Structures - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public CraftPersistentDataContainer persistentDataContainer; - // CraftBukkit end - private static final Logger LOGGER = LogManager.getLogger(); -+ public boolean isLoadingStructure = false; // Paper - private final TileEntityTypes tileType; public TileEntityTypes getTileEntityType() { return tileType; } // Paper - OBFHELPER - @Nullable - protected World world; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - try { -- IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); -+ //IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - move down - the old format might throw a json error - -- if (oldSign) { -+ if (oldSign && !isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted - lines[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; - continue; - } - // CraftBukkit end -+ IChatMutableComponent ichatmutablecomponent = IChatBaseComponent.ChatSerializer.a(s.isEmpty() ? "\"\"" : s); // Paper - after old sign - - if (this.world instanceof WorldServer) { - try { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.java -@@ -0,0 +0,0 @@ public class DefinedStructure { - definedstructure_blockinfo.c.setLong("LootTableSeed", random.nextLong()); - } - -+ tileentity.isLoadingStructure = true; // Paper - tileentity.load(definedstructure_blockinfo.b, definedstructure_blockinfo.c); - tileentity.a(definedstructureinfo.c()); - tileentity.a(definedstructureinfo.d()); -+ tileentity.isLoadingStructure = false; // Paper - } - } - diff --git a/Spigot-Server-Patches/Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/Spigot-Server-Patches/Fix-Per-World-Difficulty-Remembering-Difficulty.patch deleted file mode 100644 index 7f346fc26b..0000000000 --- a/Spigot-Server-Patches/Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 03:59:10 -0400 -Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty - -Fixes per world difficulty with /difficulty command and also -makes it so that the server keeps the last difficulty used instead -of restoring the server.properties every single load. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sat, 3 Oct 2020 18:57:47 -0600 -Subject: [PATCH] Fix Player spawnParticle x/y/z precision loss - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - if (data != null && !particle.getDataType().isInstance(data)) { - throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); - } -- PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, (float) x, (float) y, (float) z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); -+ PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(CraftParticle.toNMS(particle, data), true, x, y, z, (float) offsetX, (float) offsetY, (float) offsetZ, (float) extra, count); // Paper - Fix x/y/z coordinate precision loss - getHandle().playerConnection.sendPacket(packetplayoutworldparticles); - - } diff --git a/Spigot-Server-Patches/Fix-PlayerBucketEmptyEvent-result-itemstack.patch b/Spigot-Server-Patches/Fix-PlayerBucketEmptyEvent-result-itemstack.patch deleted file mode 100644 index 2b113d488d..0000000000 --- a/Spigot-Server-Patches/Fix-PlayerBucketEmptyEvent-result-itemstack.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 20 May 2021 22:16:37 -0700 -Subject: [PATCH] Fix PlayerBucketEmptyEvent result itemstack - -Fixes SPIGOT-2560: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-2560 - -diff --git a/src/main/java/net/minecraft/world/item/ItemBucket.java b/src/main/java/net/minecraft/world/item/ItemBucket.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBucket.java -+++ b/src/main/java/net/minecraft/world/item/ItemBucket.java -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - } - - protected ItemStack a(ItemStack itemstack, EntityHuman entityhuman) { -+ // Paper -+ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { -+ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; -+ itemLeftInHandAfterPlayerBucketEmptyEvent = null; -+ return itemInHand; -+ } -+ // Paper - return !entityhuman.abilities.canInstantlyBuild ? new ItemStack(Items.BUCKET) : itemstack; - } - -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - return a(entityhuman, world, blockposition, movingobjectpositionblock, null, null, null, null); - } - -+ private ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper - public boolean a(EntityHuman entityhuman, World world, BlockPosition blockposition, @Nullable MovingObjectPositionBlock movingobjectpositionblock, EnumDirection enumdirection, BlockPosition clicked, ItemStack itemstack, EnumHand enumhand) { - // Paper end - // CraftBukkit end -@@ -0,0 +0,0 @@ public class ItemBucket extends Item { - ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 - return false; - } -+ // Paper start -+ itemLeftInHandAfterPlayerBucketEmptyEvent = event.getItemStack().equals(CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.BUCKET)) ? null : CraftItemStack.asNMSCopy(event.getItemStack()); -+ // Paper end - } - // CraftBukkit end - if (!flag1) { diff --git a/Spigot-Server-Patches/Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/Spigot-Server-Patches/Fix-PlayerItemConsumeEvent-cancelling-properly.patch deleted file mode 100644 index 18910e1d39..0000000000 --- a/Spigot-Server-Patches/Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 19 Mar 2021 00:33:15 -0500 -Subject: [PATCH] Fix PlayerItemConsumeEvent cancelling properly - -When the active item is not cleared, the item is still readied -for use and will repeatedly trigger the PlayerItemConsumeEvent -till their item is switched. -This patch clears the active item when the event is cancelled - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - world.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) { -+ this.clearActiveItem(); // Paper - event is using an item, clear active item to reset its use - // Update client - ((EntityPlayer) this).getBukkitEntity().updateInventory(); - ((EntityPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/Spigot-Server-Patches/Fix-PotionEffect-ignores-icon-flag.patch b/Spigot-Server-Patches/Fix-PotionEffect-ignores-icon-flag.patch deleted file mode 100644 index 22b56184fa..0000000000 --- a/Spigot-Server-Patches/Fix-PotionEffect-ignores-icon-flag.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Fri, 8 May 2020 00:49:18 -0400 -Subject: [PATCH] Fix PotionEffect ignores icon flag - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - - @Override - public boolean addPotionEffect(PotionEffect effect, boolean force) { -- getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); -+ getHandle().addEffect(new MobEffect(MobEffectList.fromId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon - return true; - } - diff --git a/Spigot-Server-Patches/Fix-PotionSplashEvent-for-water-splash-potions.patch b/Spigot-Server-Patches/Fix-PotionSplashEvent-for-water-splash-potions.patch deleted file mode 100644 index f6c8dc0c59..0000000000 --- a/Spigot-Server-Patches/Fix-PotionSplashEvent-for-water-splash-potions.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 20 May 2021 20:40:53 -0700 -Subject: [PATCH] Fix PotionSplashEvent for water splash potions - -Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221 - -diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java -+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -0,0 +0,0 @@ public class DamageSource { - return (new EntityDamageSourceIndirect("thrown", entity, entity1)).c(); - } - -+ public static DamageSource indirectMagic(Entity target, Entity cause) { return c(target, cause); } // Paper - OBFHELPER - public static DamageSource c(Entity entity, @Nullable Entity entity1) { - return (new EntityDamageSourceIndirect("indirectMagic", entity, entity1)).setIgnoreArmor().setMagic(); - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityPotion.java -@@ -0,0 +0,0 @@ public class EntityPotion extends EntityProjectileThrowable { - private void splash() { - AxisAlignedBB axisalignedbb = this.getBoundingBox().grow(4.0D, 2.0D, 4.0D); - List list = this.world.a(EntityLiving.class, axisalignedbb, EntityPotion.b); -+ Map affected = new HashMap<>(); // Paper - - if (!list.isEmpty()) { - Iterator iterator = list.iterator(); -@@ -0,0 +0,0 @@ public class EntityPotion extends EntityProjectileThrowable { - double d0 = this.h(entityliving); - - if (d0 < 16.0D && entityliving.dO()) { -- entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); -+ // Paper start -+ double intensity = 1.0D - Math.sqrt(d0) / 4.0D; -+ affected.put(entityliving.getBukkitLivingEntity(), intensity); -+ // entityliving.damageEntity(DamageSource.c(entityliving, this.getShooter()), 1.0F); // Paper - moved down - } - } - } - -+ org.bukkit.event.entity.PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent(this, affected); -+ if (!event.isCancelled()) { -+ for (LivingEntity affectedEntity : event.getAffectedEntities()) { -+ EntityLiving entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); -+ entityliving.damageEntity(DamageSource.indirectMagic(entityliving, this.getShooter()), 1.0F); -+ } -+ } -+ // Paper end - } - - private void a(List list, @Nullable Entity entity) { -@@ -0,0 +0,0 @@ public class EntityPotion extends EntityProjectileThrowable { - double d0 = this.h(entityliving); - - if (d0 < 16.0D) { -+ // Paper - diff on change, used when calling the splash event for water splash potions - double d1 = 1.0D - Math.sqrt(d0) / 4.0D; - - if (entityliving == entity) { diff --git a/Spigot-Server-Patches/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/Spigot-Server-Patches/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch deleted file mode 100644 index bef3ff597c..0000000000 --- a/Spigot-Server-Patches/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 13:12:33 -0500 -Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ public class Main { - return; - } - -- File file = (File) optionset.valueOf("universe"); // CraftBukkit -+ // Paper start - fix SPIGOT-5824 -+ File file; -+ File userCacheFile = new File("usercache.json"); -+ if (optionset.has("universe")) { -+ file = (File) optionset.valueOf("universe"); // CraftBukkit -+ userCacheFile = new File(file, "usercache.json"); -+ } else { -+ file = new File(bukkitConfiguration.getString("settings.world-container", ".")); -+ } -+ // Paper end - fix SPIGOT-5824 - YggdrasilAuthenticationService yggdrasilauthenticationservice = new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY); // Paper - MinecraftSessionService minecraftsessionservice = yggdrasilauthenticationservice.createMinecraftSessionService(); - GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository(); -- UserCache usercache = new UserCache(gameprofilerepository, new File(file, MinecraftServer.b.getName())); -+ UserCache usercache = new UserCache(gameprofilerepository, userCacheFile); // Paper - only move usercache.json into folder if --universe is used, not world-container - // CraftBukkit start - String s = (String) Optional.ofNullable(optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); - Convertable convertable = Convertable.a(file.toPath()); diff --git a/Spigot-Server-Patches/Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/Spigot-Server-Patches/Fix-SPIGOT-5885-Unable-to-disable-advancements.patch deleted file mode 100644 index 32a6ebafe8..0000000000 --- a/Spigot-Server-Patches/Fix-SPIGOT-5885-Unable-to-disable-advancements.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 10 Jul 2020 12:38:12 -0500 -Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements - - -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ public class Main { - return; - } - -+ org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init - // Paper start - fix SPIGOT-5824 - File file; - File userCacheFile = new File("usercache.json"); diff --git a/Spigot-Server-Patches/Fix-SPIGOT-5989.patch b/Spigot-Server-Patches/Fix-SPIGOT-5989.patch deleted file mode 100644 index 08e39e54ad..0000000000 --- a/Spigot-Server-Patches/Fix-SPIGOT-5989.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Wed, 15 Jul 2020 21:42:52 -0400 -Subject: [PATCH] Fix SPIGOT-5989 - -Before this fix, if a player was respawning to a respawn anchor and -the respawn location was modified away from the anchor with the -PlayerRespawnEvent, the anchor would still lose some charge. -This fixes that by checking if the modified spawn location is -still at a respawn anchor. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; - import net.minecraft.world.level.biome.BiomeManager; -+import net.minecraft.world.level.block.BlockRespawnAnchor; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.border.IWorldBorderListener; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // Paper start - boolean isBedSpawn = false; - boolean isRespawn = false; -+ boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end - - // CraftBukkit start - fire PlayerRespawnEvent -@@ -0,0 +0,0 @@ public abstract class PlayerList { - Optional optional; - - if (blockposition != null) { -- optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, flag); -+ optional = EntityHuman.getBed(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 - } else { - optional = Optional.empty(); - } -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - // Spigot End - -- location = respawnEvent.getRespawnLocation(); -+ // Paper start - Fix SPIGOT-5989 -+ if (!location.equals(respawnEvent.getRespawnLocation()) ) { -+ location = respawnEvent.getRespawnLocation(); -+ isLocAltered = true; -+ } -+ // Paper end - if (!flag) entityplayer.reset(); // SPIGOT-4785 - isRespawn = true; // Paper - } else { -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - // entityplayer1.syncInventory(); - entityplayer1.setHealth(entityplayer1.getHealth()); -- if (flag2) { -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F)); -+ // Paper start - Fix SPIGOT-5989 -+ if (flag2 && !isLocAltered) { -+ IBlockData data = worldserver1.getType(blockposition); -+ worldserver1.setTypeAndData(blockposition, data.set(BlockRespawnAnchor.a, data.get(BlockRespawnAnchor.a) - 1), 3); -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.BLOCK_RESPAWN_ANCHOR_DEPLETE, SoundCategory.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); -+ // Paper end - } - // Added from changeDimension - updateClient(entityplayer); // Update health, etc... diff --git a/Spigot-Server-Patches/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/Spigot-Server-Patches/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch deleted file mode 100644 index 0b95d61e3a..0000000000 --- a/Spigot-Server-Patches/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 22 Aug 2020 23:36:21 +0200 -Subject: [PATCH] Fix SpawnChangeEvent not firing for all use-cases - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ public final void setSpawn(BlockPosition blockposition, float f) { this.a(blockposition, f); } // Paper - OBFHELPER - public void a(BlockPosition blockposition, float f) { - // Paper - configurable spawn radius - BlockPosition prevSpawn = this.getSpawn(); - //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - - this.worldData.setSpawn(blockposition, f); -+ new org.bukkit.event.world.SpawnChangeEvent(getWorld(), MCUtil.toLocation(this, prevSpawn)).callEvent(); // Paper - if (this.keepSpawnInMemory) { - // if this keepSpawnInMemory is false a plugin has already removed our tickets, do not re-add - this.removeTicketsForSpawn(this.paperConfig.keepLoadedRange, prevSpawn); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - public boolean setSpawnLocation(int x, int y, int z, float angle) { - try { - Location previousLocation = getSpawnLocation(); -- world.worldData.setSpawn(new BlockPosition(x, y, z), angle); -+ world.setSpawn(new BlockPosition(x, y, z), angle); // Paper - use WorldServer#setSpawn - -+ // Paper start - move to nms.World - // Notify anyone who's listening. -- SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -- server.getPluginManager().callEvent(event); -+ // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); -+ // server.getPluginManager().callEvent(event); -+ // Paper end - - return true; - } catch (Exception e) { diff --git a/Spigot-Server-Patches/Fix-SpongeAbsortEvent-handling.patch b/Spigot-Server-Patches/Fix-SpongeAbsortEvent-handling.patch deleted file mode 100644 index 704352fb3e..0000000000 --- a/Spigot-Server-Patches/Fix-SpongeAbsortEvent-handling.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 10 Nov 2018 05:15:21 +0000 -Subject: [PATCH] Fix SpongeAbsortEvent handling - -Only process drops when the block is actually going to be removed - -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -0,0 +0,0 @@ public class Block extends BlockBase implements IMaterial { - - } - -+ public static void dropNaturally(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { a(iblockdata, generatoraccess, blockposition, tileentity); } - public static void a(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) { - if (generatoraccess instanceof WorldServer) { - a(iblockdata, (WorldServer) generatoraccess, blockposition, tileentity).forEach((itemstack) -> { -diff --git a/src/main/java/net/minecraft/world/level/block/BlockSponge.java b/src/main/java/net/minecraft/world/level/block/BlockSponge.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockSponge.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockSponge.java -@@ -0,0 +0,0 @@ public class BlockSponge extends Block { - // NOP - } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { - TileEntity tileentity = iblockdata.getBlock().isTileEntity() ? world.getTileEntity(blockposition2) : null; -- -- a(iblockdata, world, blockposition2, tileentity); -+ // Paper start -+ if (block.getHandle().getMaterial() == Material.AIR) { -+ dropNaturally(iblockdata, world, blockposition2, tileentity); -+ } -+ // Paper end - } - } - world.setTypeAndData(blockposition2, block.getHandle(), block.getFlag()); diff --git a/Spigot-Server-Patches/Fix-World-isChunkGenerated-calls.patch b/Spigot-Server-Patches/Fix-World-isChunkGenerated-calls.patch deleted file mode 100644 index 633f6d1a8d..0000000000 --- a/Spigot-Server-Patches/Fix-World-isChunkGenerated-calls.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 08:54:33 -0700 -Subject: [PATCH] Fix World#isChunkGenerated calls - -Optimize World#loadChunk() too -This patch also adds a chunk status cache on region files (note that -its only purpose is to cache the status on DISK) - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - private final WorldServer world; - public final Thread serverThread; // Paper - private -> public - private final LightEngineThreaded lightEngine; -- private final ChunkProviderServer.a serverThreadQueue; -+ public final ChunkProviderServer.a serverThreadQueue; // Paper private -> public - public final PlayerChunkMap playerChunkMap; - private final WorldPersistentData worldPersistentData; - private long lastTickTime; -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - - return ret; - } -+ -+ @Nullable -+ public IChunkAccess getChunkAtImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ // Note: Bypass cache to make this MT-Safe -+ -+ PlayerChunk playerChunk = this.getChunk(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getAvailableChunkNow(); -+ -+ } - // Paper end - - @Nullable -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - return this.p; - } - -- final class a extends IAsyncTaskHandler { -+ public final class a extends IAsyncTaskHandler { // Paper - package -> public - - private a(World world) { - super("Chunk source main thread executor for " + world.getDimensionKey().a()); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - Either either = (Either) statusFuture.getNow(null); - return either == null ? null : (Chunk) either.left().orElse(null); - } -+ -+ public IChunkAccess getAvailableChunkNow() { -+ // TODO can we just getStatusFuture(EMPTY)? -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture> future = this.getStatusFutureUnchecked(curr); -+ Either either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return either.left().get(); -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - @Nullable -- private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public - NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); -+ // Paper start - Cache chunk status on disk -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ nbttagcompound = this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ this.updateChunkStatusOnDisk(chunkcoordintpair, nbttagcompound); -+ -+ return nbttagcompound; -+ // Paper end -+ } -+ -+ // Paper start - chunk status cache "api" -+ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); -+ -+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true); -+ -+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) { -+ return null; -+ } -+ -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ -+ if (status != null) { -+ return status; -+ } -+ -+ this.readChunkData(chunkPos); - -- return nbttagcompound == null ? null : this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - } - -+ public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { -+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ } -+ -+ public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -+ PlayerChunk chunkHolder = this.pendingUnload.get(ChunkCoordIntPair.pair(chunkX, chunkZ)); -+ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); -+ } -+ // Paper end -+ - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkStatus.java -@@ -0,0 +0,0 @@ public class ChunkStatus { - return this.s; - } - -+ public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER - public ChunkStatus e() { - return this.u; - } -@@ -0,0 +0,0 @@ public class ChunkStatus { - return this.y; - } - -+ // Paper start -+ public static ChunkStatus getStatus(String name) { -+ try { -+ // We need this otherwise we return EMPTY for invalid names -+ MinecraftKey key = new MinecraftKey(name); -+ return IRegistry.CHUNK_STATUS.getOptional(key).orElse(null); -+ } catch (Exception ex) { -+ return null; // invalid name -+ } -+ } -+ // Paper end - public static ChunkStatus a(String s) { - return (ChunkStatus) IRegistry.CHUNK_STATUS.get(MinecraftKey.a(s)); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - } - // Paper end - -+ // Paper start -+ public static ChunkStatus getStatus(NBTTagCompound compound) { -+ if (compound == null) { -+ return null; -+ } -+ -+ // Note: Copied from below -+ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); -+ } -+ // Paper end -+ - public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { - if (nbttagcompound != null) { - ChunkStatus chunkstatus = ChunkStatus.a(nbttagcompound.getCompound("Level").getString("Status")); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.dimension.DimensionManager; - - public class IChunkLoader implements AutoCloseable { - -- private final IOWorker a; -+ private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER - protected final DataFixer b; - @Nullable - private PersistentStructureLegacy c; -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -0,0 +0,0 @@ import net.minecraft.SystemUtils; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - protected final RegionFileBitSet freeSectors; - public final File file; // Paper - -+ // Paper start - Cache chunk status -+ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; -+ -+ private boolean closed; -+ -+ // invoked on write/read -+ public void setStatus(int x, int z, ChunkStatus status) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ this.statuses[getChunkLocation(x, z)] = status; -+ } -+ -+ public ChunkStatus getStatusIfCached(int x, int z) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ final int location = getChunkLocation(x, z); -+ return this.statuses[location]; -+ } -+ // Paper end -+ - public RegionFile(File file, File file1, boolean flag) throws IOException { - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); - } -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - return this.getOffset(chunkcoordintpair) != 0; - } - -+ private static int getChunkLocation(int x, int z) { return (x & 31) + (z & 31) * 32; } // Paper - OBFHELPER - sort of, mirror of logic below - private static int g(ChunkCoordIntPair chunkcoordintpair) { - return chunkcoordintpair.j() + chunkcoordintpair.k() * 32; - } - - public void close() throws IOException { -+ this.closed = true; // Paper - try { - this.d(); - } finally { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - this.c = flag; - } - -- private RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit -+ -+ // Paper start -+ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { -+ return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); -+ } -+ -+ // Paper end -+ public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); - -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - - try { - NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); -+ regionfile.setStatus(chunkcoordintpair.x, chunkcoordintpair.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk - regionfile.setOversized(chunkcoordintpair.x, chunkcoordintpair.z, false); // Paper - We don't do this anymore, mojang stores differently, but clear old meta flag if it exists to get rid of our own meta file once last oversized is gone - } catch (Throwable throwable1) { - throwable = throwable1; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ import java.util.Objects; - import java.util.Random; - import java.util.Set; - import java.util.UUID; -+import java.util.concurrent.CompletableFuture; - import java.util.function.Predicate; - import java.util.stream.Collectors; - import net.minecraft.core.BlockPosition; -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkGenerated(int x, int z) { -+ // Paper start - Fix this method -+ if (!Bukkit.isPrimaryThread()) { -+ return CompletableFuture.supplyAsync(() -> { -+ return CraftWorld.this.isChunkGenerated(x, z); -+ }, world.getChunkProvider().serverThreadQueue).join(); -+ } -+ IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (chunk == null) { -+ chunk = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (chunk != null) { -+ return chunk instanceof ProtoChunkExtension || chunk instanceof net.minecraft.world.level.chunk.Chunk; -+ } - try { -- return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) -+ return world.getChunkProvider().playerChunkMap.getChunkStatusOnDisk(new ChunkCoordIntPair(x, z)) == ChunkStatus.FULL; -+ // Paper end - } catch (IOException ex) { - throw new RuntimeException(ex); - } -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -+ // Paper start - Optimize this method -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); - -- // If generate = false, but the chunk already exists, we will get this back. -- if (chunk instanceof ProtoChunkExtension) { -- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition -- chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -- } -+ if (!generate) { -+ IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (immediate == null) { -+ immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (immediate != null) { -+ if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.world.level.chunk.Chunk)) { -+ return false; // not full status -+ } -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower -+ return true; -+ } - -- if (chunk instanceof net.minecraft.world.level.chunk.Chunk) { -- world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); -- return true; -+ net.minecraft.world.level.chunk.storage.RegionFile file; -+ try { -+ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ ChunkStatus status = file.getStatusIfCached(x, z); -+ if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ return false; -+ } -+ -+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); -+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.world.level.chunk.Chunk)) { -+ return false; -+ } -+ -+ // fall through to load -+ // we do this so we do not re-read the chunk data on disk - } - -- return false; -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -+ return true; -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch b/Spigot-Server-Patches/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch deleted file mode 100644 index c8795f5323..0000000000 --- a/Spigot-Server-Patches/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Fri, 23 Apr 2021 22:42:42 +0100 -Subject: [PATCH] Fix anchor respawn acting as a bed respawn from the end - portal - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - // Paper start - boolean isBedSpawn = false; -+ boolean isAnchorSpawn = false; - boolean isRespawn = false; - boolean isLocAltered = false; // Paper - Fix SPIGOT-5989 - // Paper end -@@ -0,0 +0,0 @@ public abstract class PlayerList { - if (optional.isPresent()) { - IBlockData iblockdata = worldserver1.getType(blockposition); - boolean flag3 = iblockdata.a(Blocks.RESPAWN_ANCHOR); -+ isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal - Vec3D vec3d = (Vec3D) optional.get(); - float f1; - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag2, flag2); -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { diff --git a/Spigot-Server-Patches/Fix-and-optimise-world-force-upgrading.patch b/Spigot-Server-Patches/Fix-and-optimise-world-force-upgrading.patch deleted file mode 100644 index 81796c6cef..0000000000 --- a/Spigot-Server-Patches/Fix-and-optimise-world-force-upgrading.patch +++ /dev/null @@ -1,411 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 20 May 2021 07:02:22 -0700 -Subject: [PATCH] Fix and optimise world force upgrading - -The WorldUpgrader class was incorrectly modified by -CB. It will store an IChunkLoader instance for all -dimension types in the world, but obviously with how -CB shifts around worlds only one dimension type exists -per world. But this would be OK if CB did this -change correctly. All IChunkLoader instances -will point to the same regionfiles. And all -IChunkLoader instances are going to be read from. - -This problem hasn't really been reported because -it relies on the persistent legacy data to be converted -as well to cause corruption. Why? Because the legacy -data is also shared, it will result in different -outputs from conversion (as once conversion for legacy -persistent data takes place, it is REMOVED - so the next -convert will _not_ have the data). Which means different -sizes on disk. Which means different regionfile sector -allocations. Which means there are 3 different possible -regionfile sector allocations in memory, and none of them -are going to be correct. - -I've fixed this by writing a world upgrader suited to -CB's changes to world folder format. It was brain dead -easy to add threading, so I did. - -diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.world; -+ -+import com.mojang.datafixers.DataFixer; -+import net.minecraft.SharedConstants; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.resources.ResourceKey; -+import net.minecraft.util.worldupdate.WorldUpgrader; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.chunk.storage.IChunkLoader; -+import net.minecraft.world.level.chunk.storage.RegionFileCache; -+import net.minecraft.world.level.dimension.DimensionManager; -+import net.minecraft.world.level.dimension.WorldDimension; -+import net.minecraft.world.level.storage.Convertable; -+import net.minecraft.world.level.storage.WorldPersistentData; -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+import java.io.File; -+import java.io.IOException; -+import java.text.DecimalFormat; -+import java.util.concurrent.ExecutorService; -+import java.util.concurrent.Executors; -+import java.util.concurrent.ThreadFactory; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.function.Supplier; -+ -+public class ThreadedWorldUpgrader { -+ -+ private static final Logger LOGGER = LogManager.getLogger(); -+ -+ private final ResourceKey dimensionType; -+ private final ResourceKey worldKey; -+ private final String worldName; -+ private final ExecutorService threadPool; -+ private final DataFixer dataFixer; -+ private final boolean removeCaches; -+ -+ public ThreadedWorldUpgrader(final ResourceKey dimensionType, final ResourceKey worldKey, final String worldName, final int threads, -+ final DataFixer dataFixer, final boolean removeCaches) { -+ this.dimensionType = dimensionType; -+ this.worldKey = worldKey; -+ this.worldName = worldName; -+ this.threadPool = Executors.newFixedThreadPool(Math.max(1, threads), new ThreadFactory() { -+ private final AtomicInteger threadCounter = new AtomicInteger(); -+ -+ @Override -+ public Thread newThread(final Runnable run) { -+ final Thread ret = new Thread(run); -+ -+ ret.setName("World upgrader thread for world " + ThreadedWorldUpgrader.this.worldName + " #" + this.threadCounter.getAndIncrement()); -+ ret.setUncaughtExceptionHandler((thread, throwable) -> { -+ LOGGER.fatal("Error upgrading world", throwable); -+ }); -+ -+ return ret; -+ } -+ }); -+ this.dataFixer = dataFixer; -+ this.removeCaches = removeCaches; -+ } -+ -+ public void convert() { -+ final File worldFolder = Convertable.getFolder(new File(this.worldName), this.dimensionType); -+ final WorldPersistentData worldPersistentData = new WorldPersistentData(new File(worldFolder, "data"), this.dataFixer); -+ -+ final File regionFolder = new File(worldFolder, "region"); -+ -+ LOGGER.info("Force upgrading " + this.worldName); -+ LOGGER.info("Counting regionfiles for " + this.worldName); -+ final File[] regionFiles = regionFolder.listFiles((final File dir, final String name) -> { -+ return WorldUpgrader.getRegionfileRegex().matcher(name).matches(); -+ }); -+ if (regionFiles == null) { -+ LOGGER.info("Found no regionfiles to convert for world " + this.worldName); -+ return; -+ } -+ LOGGER.info("Found " + regionFiles.length + " regionfiles to convert"); -+ LOGGER.info("Starting conversion now for world " + this.worldName); -+ -+ final WorldInfo info = new WorldInfo(() -> worldPersistentData, -+ new IChunkLoader(regionFolder, this.dataFixer, false), this.removeCaches, this.worldKey); -+ -+ long expectedChunks = (long)regionFiles.length * (32L * 32L); -+ -+ for (final File regionFile : regionFiles) { -+ final ChunkCoordIntPair regionPos = RegionFileCache.getRegionFileCoordinates(regionFile); -+ if (regionPos == null) { -+ expectedChunks -= (32L * 32L); -+ continue; -+ } -+ -+ this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5)); -+ } -+ this.threadPool.shutdown(); -+ -+ final DecimalFormat format = new DecimalFormat("#0.00"); -+ -+ final long start = System.nanoTime(); -+ -+ while (!this.threadPool.isTerminated()) { -+ final long current = info.convertedChunks.get(); -+ -+ LOGGER.info("{}% completed ({} / {} chunks)...", format.format((double)current / (double)expectedChunks * 100.0), current, expectedChunks); -+ -+ try { -+ Thread.sleep(1000L); -+ } catch (final InterruptedException ignore) {} -+ } -+ -+ final long end = System.nanoTime(); -+ -+ try { -+ info.loader.close(); -+ } catch (final IOException ex) { -+ LOGGER.fatal("Failed to close chunk loader", ex); -+ } -+ LOGGER.info("Completed conversion. Took {}s, {} out of {} chunks needed to be converted/modified ({}%)", -+ (int)Math.ceil((end - start) * 1.0e-9), info.modifiedChunks.get(), expectedChunks, format.format((double)info.modifiedChunks.get() / (double)expectedChunks * 100.0)); -+ } -+ -+ private static final class WorldInfo { -+ -+ public final Supplier persistentDataSupplier; -+ public final IChunkLoader loader; -+ public final boolean removeCaches; -+ public final ResourceKey worldKey; -+ public final AtomicLong convertedChunks = new AtomicLong(); -+ public final AtomicLong modifiedChunks = new AtomicLong(); -+ -+ private WorldInfo(final Supplier persistentDataSupplier, final IChunkLoader loader, final boolean removeCaches, -+ final ResourceKey worldKey) { -+ this.persistentDataSupplier = persistentDataSupplier; -+ this.loader = loader; -+ this.removeCaches = removeCaches; -+ this.worldKey = worldKey; -+ } -+ } -+ -+ private static final class ConvertTask implements Runnable { -+ -+ private final WorldInfo worldInfo; -+ private final int regionX; -+ private final int regionZ; -+ -+ public ConvertTask(final WorldInfo worldInfo, final int regionX, final int regionZ) { -+ this.worldInfo = worldInfo; -+ this.regionX = regionX; -+ this.regionZ = regionZ; -+ } -+ -+ @Override -+ public void run() { -+ final int regionCX = this.regionX << 5; -+ final int regionCZ = this.regionZ << 5; -+ -+ final Supplier persistentDataSupplier = this.worldInfo.persistentDataSupplier; -+ final IChunkLoader loader = this.worldInfo.loader; -+ final boolean removeCaches = this.worldInfo.removeCaches; -+ final ResourceKey worldKey = this.worldInfo.worldKey; -+ -+ for (int cz = regionCZ; cz < (regionCZ + 32); ++cz) { -+ for (int cx = regionCX; cx < (regionCX + 32); ++cx) { -+ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(cx, cz); -+ try { -+ // no need to check the coordinate of the chunk, the regionfilecache does that for us -+ -+ NBTTagCompound chunkNBT = loader.read(chunkPos); -+ -+ if (chunkNBT == null) { -+ continue; -+ } -+ -+ final int versionBefore = IChunkLoader.getVersion(chunkNBT); -+ -+ chunkNBT = loader.getChunkData(worldKey, persistentDataSupplier, chunkNBT, chunkPos, null); -+ -+ boolean modified = versionBefore < SharedConstants.getGameVersion().getWorldVersion(); -+ -+ if (removeCaches) { -+ final NBTTagCompound level = chunkNBT.getCompound("Level"); -+ modified |= level.hasKey("Heightmaps"); -+ level.remove("Heightmaps"); -+ modified |= level.hasKey("isLightOn"); -+ level.remove("isLightOn"); -+ } -+ -+ if (modified) { -+ this.worldInfo.modifiedChunks.getAndIncrement(); -+ loader.write(chunkPos, chunkNBT); -+ } -+ } catch (final Exception ex) { -+ LOGGER.error("Error upgrading chunk {}", chunkPos, ex); -+ } finally { -+ this.worldInfo.convertedChunks.getAndIncrement(); -+ } -+ } -+ } -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ import java.nio.file.Paths; - import java.util.Optional; - import java.util.concurrent.CompletableFuture; - import java.util.function.BooleanSupplier; -+import io.papermc.paper.world.ThreadedWorldUpgrader; - import joptsimple.NonOptionArgumentSpec; - import joptsimple.OptionParser; - import joptsimple.OptionSet; -@@ -0,0 +0,0 @@ public class Main { - } - // Paper end - -+ // Paper start - fix and optimise world upgrading -+ public static void convertWorldButItWorks(ResourceKey dimensionType, ResourceKey worldKey, String worldName, -+ DataFixer dataFixer, boolean removeCaches) { -+ int threads = Runtime.getRuntime().availableProcessors() * 3 / 8; -+ final ThreadedWorldUpgrader worldUpgrader = new ThreadedWorldUpgrader(dimensionType, worldKey, worldName, threads, dataFixer, removeCaches); -+ worldUpgrader.convert(); -+ } -+ // Paper end - fix and optimise world upgrading -+ - public static void convertWorld(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, ImmutableSet> immutableset) { // CraftBukkit - Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelName()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return true; -- }, worlddata.getGeneratorSettings().d().d().stream().map((entry1) -> { -- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry1.getKey()).a()); -- }).collect(ImmutableSet.toImmutableSet())); -- } -+ // Paper - move down - - IWorldDataServer iworlddataserver = worlddata; - GeneratorSettings generatorsettings = worlddata.getGeneratorSettings(); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant worldKey = ResourceKey.a(IRegistry.L, dimensionKey.a()); - - if (dimensionKey == WorldDimension.OVERWORLD) { -diff --git a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -+++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java -@@ -0,0 +0,0 @@ public class WorldUpgrader { - private volatile int m; - private final Object2FloatMap> n = Object2FloatMaps.synchronize(new Object2FloatOpenCustomHashMap(SystemUtils.k())); // CraftBukkit - private volatile IChatBaseComponent o = new ChatMessage("optimizeWorld.stage.counting"); -- private static final Pattern p = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); -+ private static final Pattern p = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); public static final Pattern getRegionfileRegex() { return p; } // Paper - OBFHELPER - private final WorldPersistentData q; - - public WorldUpgrader(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, ImmutableSet> immutableset, boolean flag) { // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return typeKey; - } - -+ // Paper start - fix and optimise world upgrading -+ // copied from below -+ public static ResourceKey getDimensionKey(DimensionManager manager) { -+ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().customRegistry.a().c(manager).orElseThrow(() -> { -+ return new IllegalStateException("Unregistered dimension type: " + manager); -+ }); -+ } -+ // Paper end - fix and optimise world upgrading -+ - protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) { // Paper - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot - this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable { - return nbttagcompound; - } - -+ public static int getVersion(NBTTagCompound nbttagcompound) { return a(nbttagcompound); } // Paper - OBFHELPER - public static int a(NBTTagCompound nbttagcompound) { - return nbttagcompound.hasKeyOfType("DataVersion", 99) ? nbttagcompound.getInt("DataVersion") : -1; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -0,0 +0,0 @@ public class RegionFileCache implements AutoCloseable { // Paper - no final - - - // Paper start -+ public static ChunkCoordIntPair getRegionFileCoordinates(File file) { -+ String fileName = file.getName(); -+ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { -+ return null; -+ } -+ -+ String[] split = fileName.split("\\."); -+ -+ if (split.length != 4) { -+ return null; -+ } -+ -+ try { -+ int x = Integer.parseInt(split[1]); -+ int z = Integer.parseInt(split[2]); -+ -+ return new ChunkCoordIntPair(x << 5, z << 5); -+ } catch (NumberFormatException ex) { -+ return null; -+ } -+ } -+ - public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io - return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - worlddata.checkName(name); - worlddata.a(console.getServerModName(), console.getModded().isPresent()); -- -- if (console.options.has("forceUpgrade")) { -- net.minecraft.server.Main.convertWorld(worldSession, DataConverterRegistry.a(), console.options.has("eraseCache"), () -> { -- return true; -- }, worlddata.getGeneratorSettings().d().d().stream().map((entry) -> { -- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry.getKey()).a()); -- }).collect(ImmutableSet.toImmutableSet())); -- } -+ // Paper - move down - - long j = BiomeManager.a(creator.seed()); - List list = ImmutableList.of(new MobSpawnerPhantom(), new MobSpawnerPatrol(), new MobSpawnerCat(), new VillageSiege(), new MobSpawnerTrader(worlddata)); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - chunkgenerator = worlddimension.c(); - } - -+ // Paper start - fix and optimise world upgrading -+ if (console.options.has("forceUpgrade")) { -+ net.minecraft.server.Main.convertWorldButItWorks( -+ actualDimension, net.minecraft.world.level.World.getDimensionKey(dimensionmanager), worldSession.getLevelName(), DataConverterRegistry.getDataFixer(), console.options.has("eraseCache") -+ ); -+ } -+ // Paper end - fix and optimise world upgrading -+ - ResourceKey worldKey; - String levelName = this.getServer().getDedicatedServerProperties().levelName; - if (name.equals(levelName + "_nether")) { diff --git a/Spigot-Server-Patches/Fix-arrows-never-despawning-MC-125757.patch b/Spigot-Server-Patches/Fix-arrows-never-despawning-MC-125757.patch deleted file mode 100644 index 2e4681ab18..0000000000 --- a/Spigot-Server-Patches/Fix-arrows-never-despawning-MC-125757.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 8 Jul 2020 11:24:30 -0500 -Subject: [PATCH] Fix arrows never despawning MC-125757 - -This forces the despawn counter to start ticking regardless of -state after the arrow has been alive for 200 ticks (10 seconds) -instead of getting stuck in a never despawn state (bubble columns, -etc). - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile { - - ++this.c; - } else { -+ if (ticksLived > 200) this.tickDespawnCounter(); // Paper - tick despawnCounter regardless after 10 seconds - this.c = 0; - Vec3D vec3d2 = this.getPositionVector(); - -@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile { - - } - -+ protected final void tickDespawnCounter() { this.h(); } // Paper - OBFHELPER - protected void h() { - ++this.despawnCounter; - if (this.despawnCounter >= (fromPlayer == PickupStatus.CREATIVE_ONLY ? world.paperConfig.creativeArrowDespawnRate : (fromPlayer == PickupStatus.DISALLOWED ? world.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof EntityThrownTrident) ? world.spigotConfig.tridentDespawnRate : world.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? diff --git a/Spigot-Server-Patches/Fix-checkReach-check-for-Shulker-boxes.patch b/Spigot-Server-Patches/Fix-checkReach-check-for-Shulker-boxes.patch deleted file mode 100644 index 8cce88d3fd..0000000000 --- a/Spigot-Server-Patches/Fix-checkReach-check-for-Shulker-boxes.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Sun, 4 Apr 2021 14:25:04 -0400 -Subject: [PATCH] Fix checkReach check for Shulker boxes - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerShulkerBox.java -@@ -0,0 +0,0 @@ public class ContainerShulkerBox extends Container { - - @Override - public boolean canUse(EntityHuman entityhuman) { -+ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox - return this.c.a(entityhuman); - } - diff --git a/Spigot-Server-Patches/Fix-client-lag-on-advancement-loading.patch b/Spigot-Server-Patches/Fix-client-lag-on-advancement-loading.patch deleted file mode 100644 index acd39431de..0000000000 --- a/Spigot-Server-Patches/Fix-client-lag-on-advancement-loading.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Sat, 31 Oct 2020 11:49:01 -0700 -Subject: [PATCH] Fix client lag on advancement loading - -When new advancements are added via the UnsafeValues#loadAdvancement -API, it triggers a full datapack reload when this is not necessary. The -advancement is already loaded directly into the advancement registry, -and the point of saving the advancement to the Bukkit datapack seems to -be for persistence. By removing the call to reload datapacks when an -advancement is loaded, the client no longer completely freezes up when -adding a new advancement. -To ensure the client still receives the updated advancement data, we -manually reload the advancement data for all players, which -normally takes place as a part of the datapack reloading. - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -0,0 +0,0 @@ public class AdvancementDataPlayer { - - } - -+ public final void reload(AdvancementDataWorld advancementDataWorld) { this.a(advancementDataWorld); } // Paper - OBFHELPER - public void a(AdvancementDataWorld advancementdataworld) { - this.a(); - this.data.clear(); -@@ -0,0 +0,0 @@ public class AdvancementDataPlayer { - - } - -+ public final void sendUpdateIfNeeded(EntityPlayer entityPlayer) { this.b(entityPlayer); } // Paper - OBFHELPER - public void b(EntityPlayer entityplayer) { - if (this.m || !this.i.isEmpty() || !this.j.isEmpty()) { - Map map = Maps.newHashMap(); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); - } - -- MinecraftServer.getServer().getPlayerList().reload(); -+ // Paper start -+ //MinecraftServer.getServer().getPlayerList().reload(); -+ MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { -+ player.getAdvancementData().reload(MinecraftServer.getServer().getAdvancementData()); -+ player.getAdvancementData().sendUpdateIfNeeded(player); -+ }); -+ // Paper end - - return bukkit; - } diff --git a/Spigot-Server-Patches/Fix-client-rendering-skulls-from-same-user.patch b/Spigot-Server-Patches/Fix-client-rendering-skulls-from-same-user.patch deleted file mode 100644 index 41ae25611f..0000000000 --- a/Spigot-Server-Patches/Fix-client-rendering-skulls-from-same-user.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Nov 2016 00:40:42 -0500 -Subject: [PATCH] Fix client rendering skulls from same user - -See: https://github.com/PaperMC/Paper/issues/1304 - -Changes the UUID sent to client to be based on either -the texture payload, or random. - -This allows the client to render multiple skull textures from the same user, -for when different skins were used when skull was made. - -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -0,0 +0,0 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.level.block.entity.TileEntitySkull; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; - -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - if (item.usesDurability() || item.n()) { - // Spigot start - filter - itemstack = itemstack.cloneItemStack(); -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - // Spigot end - nbttagcompound = itemstack.getTag(); -+ // Paper start -+ if (nbttagcompound != null && nbttagcompound.hasKeyOfType("SkullOwner", 10)) { -+ NBTTagCompound owner = nbttagcompound.getCompound("SkullOwner"); -+ if (owner.hasUUID("Id")) { -+ nbttagcompound.setUUID("SkullOwnerOrig", owner.getUUID("Id")); -+ TileEntitySkull.sanitizeUUID(owner); -+ } -+ } -+ // Paper end - } - - this.a(nbttagcompound); -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - itemstack.setTag(this.l()); - // CraftBukkit start - if (itemstack.getTag() != null) { -- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); -+ // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client -+ if (itemstack.tag.hasKey("SkullOwnerOrig")) { -+ NBTTagCompound owner = itemstack.tag.getCompound("SkullOwner"); -+ if (itemstack.tag.hasKey("SkullOwnerOrig")) { -+ owner.map.put("Id", itemstack.tag.map.get("SkullOwnerOrig")); -+ itemstack.tag.remove("SkullOwnerOrig"); -+ } -+ } -+ // Paper end -+ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported - } - // CraftBukkit end - return itemstack; -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -0,0 +0,0 @@ import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntitySkull; - import net.minecraft.world.level.chunk.BiomeStorage; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkSection; -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - - if (this.f() || (i & 1 << j) != 0) { - NBTTagCompound nbttagcompound = tileentity.b(); -+ if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper - - this.g.add(nbttagcompound); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - private int g; - @Deprecated - private Item item; -- private NBTTagCompound tag; -+ public NBTTagCompound tag; // Paper private -> public - private boolean j; - private Entity k; - private ShapeDetectorBlock l; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySkull.java -@@ -0,0 +0,0 @@ import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; - import net.minecraft.server.players.UserCache; - import net.minecraft.util.UtilColor; -@@ -0,0 +0,0 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa - @Nullable - @Override - public PacketPlayOutTileEntityData getUpdatePacket() { -- return new PacketPlayOutTileEntityData(this.position, 4, this.b()); -+ return new PacketPlayOutTileEntityData(this.position, 4, sanitizeTileEntityUUID(this.b())); // Paper - } - -+ // Paper start -+ public static NBTTagCompound sanitizeTileEntityUUID(NBTTagCompound cmp) { -+ NBTTagCompound owner = cmp.getCompound("Owner"); -+ if (!owner.isEmpty()) { -+ sanitizeUUID(owner); -+ } -+ return cmp; -+ } -+ -+ public static void sanitizeUUID(NBTTagCompound owner) { -+ NBTTagCompound properties = owner.getCompound("Properties"); -+ NBTTagList list = null; -+ if (!properties.isEmpty()) { -+ list = properties.getList("textures", 10); -+ } -+ -+ if (list != null && !list.isEmpty()) { -+ String textures = ((NBTTagCompound)list.get(0)).getString("Value"); -+ if (textures != null && textures.length() > 3) { -+ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); -+ owner.setUUID("Id", uuid); -+ return; -+ } -+ } -+ owner.setUUID("Id", UUID.randomUUID()); -+ } -+ // Paper end -+ - @Override - public NBTTagCompound b() { - return this.save(new NBTTagCompound()); diff --git a/Spigot-Server-Patches/Fix-console-spam-when-removing-chests-in-water.patch b/Spigot-Server-Patches/Fix-console-spam-when-removing-chests-in-water.patch deleted file mode 100644 index 1753ff91a2..0000000000 --- a/Spigot-Server-Patches/Fix-console-spam-when-removing-chests-in-water.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: HexedHero <6012891+HexedHero@users.noreply.github.com> -Date: Thu, 19 Nov 2020 02:07:10 +0000 -Subject: [PATCH] Fix console spam when removing chests in water - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -0,0 +0,0 @@ public class BlockChest extends BlockChestAbstract implements I - @Override - public void remove(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata.a(iblockdata1.getBlock())) { -- TileEntity tileentity = world.getTileEntity(blockposition); -+ TileEntity tileentity = world.getTileEntity(blockposition, false); // Paper - Don't validate TE - Fix console spam when removing chests in water - - if (tileentity instanceof IInventory) { - InventoryUtils.dropInventory(world, blockposition, (IInventory) tileentity); diff --git a/Spigot-Server-Patches/Fix-curing-zombie-villager-discount-exploit.patch b/Spigot-Server-Patches/Fix-curing-zombie-villager-discount-exploit.patch deleted file mode 100644 index 47f59b8240..0000000000 --- a/Spigot-Server-Patches/Fix-curing-zombie-villager-discount-exploit.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:14:20 -0600 -Subject: [PATCH] Fix curing zombie villager discount exploit - -This fixes the exploit used to gain absurd trading discounts with infecting -and curing a villager on repeat by simply resetting the relevant part of -the reputation when it is cured. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void fixClimbingBypassingCrammingRule() { - fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); - } -+ -+ public boolean fixCuringZombieVillagerDiscountExploit = true; -+ private void fixCuringExploit() { -+ fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -0,0 +0,0 @@ public class Reputation { - - } - -+ public final void removeReputationForType(ReputationType reputationType) { this.b(reputationType); } // Paper - OBFHELPER - public void b(ReputationType reputationtype) { - this.a.removeInt(reputationtype); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - @Override - public void a(ReputationEvent reputationevent, Entity entity) { - if (reputationevent == ReputationEvent.a) { -+ // Paper start - fix MC-181190 -+ if (world.paperConfig.fixCuringZombieVillagerDiscountExploit) { -+ final Reputation.a playerReputation = this.getReputation().getReputations().get(entity.getUniqueID()); -+ if (playerReputation != null) { -+ playerReputation.removeReputationForType(ReputationType.MAJOR_POSITIVE); -+ playerReputation.removeReputationForType(ReputationType.MINOR_POSITIVE); -+ } -+ } -+ // Paper end - this.by.a(entity.getUniqueID(), ReputationType.MAJOR_POSITIVE, 20); - this.by.a(entity.getUniqueID(), ReputationType.MINOR_POSITIVE, 25); - } else if (reputationevent == ReputationEvent.e) { diff --git a/Spigot-Server-Patches/Fix-dangerous-end-portal-logic.patch b/Spigot-Server-Patches/Fix-dangerous-end-portal-logic.patch deleted file mode 100644 index 9eda02348c..0000000000 --- a/Spigot-Server-Patches/Fix-dangerous-end-portal-logic.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 4 Jun 2021 17:06:52 -0400 -Subject: [PATCH] Fix dangerous end portal logic - -End portals could teleport entities during move calls. Stupid -logic given the caller will never expect that kind of thing, -and will result in all kinds of dupes. - -Move the tick logic into the post tick, where portaling was -designed to happen in the first place. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return b(worldserver, TeleportCause.UNKNOWN); - } - -+ @Nullable public final Entity changeDimension(WorldServer worldserver, PlayerTeleportEvent.TeleportCause cause) { return this.b(worldserver, cause); } // Paper - OBFHELPER - @Nullable - public Entity b(WorldServer worldserver, PlayerTeleportEvent.TeleportCause cause) { - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // Paper end - optimise entity tracking - -+ // Paper start - make end portalling safe -+ public BlockPosition portalBlock; -+ public WorldServer portalWorld; -+ public void tickEndPortal() { -+ BlockPosition pos = this.portalBlock; -+ WorldServer world = this.portalWorld; -+ this.portalBlock = null; -+ this.portalWorld = null; -+ -+ if (pos == null || world == null || world != this.world) { -+ return; -+ } -+ -+ if (this.isPassenger() || this.isVehicle() || !this.canPortal() || this.dead || !this.valid || !this.isAlive()) { -+ return; -+ } -+ -+ ResourceKey resourcekey = world.getTypeKey() == DimensionManager.THE_END ? World.OVERWORLD : World.THE_END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends -+ WorldServer worldserver = world.getMinecraftServer().getWorldServer(resourcekey); -+ -+ org.bukkit.event.entity.EntityPortalEnterEvent event = new org.bukkit.event.entity.EntityPortalEnterEvent(this.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); -+ event.callEvent(); -+ -+ if (this instanceof EntityPlayer) { -+ ((EntityPlayer)this).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); -+ return; -+ } -+ this.teleportTo(worldserver, null); -+ } -+ // Paper end - make end portalling safe -+ - public Entity(EntityTypes entitytypes, World world) { - this.id = Entity.entityCount.incrementAndGet(); - this.passengers = Lists.newArrayList(); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - this.E(); -+ this.tickEndPortal(); // Paper - make end portalling safe - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockEnderPortal.java -@@ -0,0 +0,0 @@ public class BlockEnderPortal extends BlockTileEntity { - // return; // CraftBukkit - always fire event in case plugins wish to change it - } - -- // CraftBukkit start - Entity in portal -- EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ())); -- world.getServer().getPluginManager().callEvent(event); -- -- if (entity instanceof EntityPlayer) { -- ((EntityPlayer) entity).b(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); -- return; -- } -- // CraftBukkit end -- entity.b(worldserver); -+ // Paper start - move all of this logic into portal tick -+ entity.portalWorld = ((WorldServer)world); -+ entity.portalBlock = blockposition.immutableCopy(); -+ // Paper end - move all of this logic into portal tick - } - - } diff --git a/Spigot-Server-Patches/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch b/Spigot-Server-Patches/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch deleted file mode 100644 index 62d1af6029..0000000000 --- a/Spigot-Server-Patches/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 22:00:27 -0500 -Subject: [PATCH] Fix deop kicking non-whitelisted player when white list is - not enabled - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = Lists.newArrayList(playerlist.getPlayers()); - Iterator iterator = list.iterator(); - diff --git a/Spigot-Server-Patches/Fix-duplicating-give-items-on-item-drop-cancel.patch b/Spigot-Server-Patches/Fix-duplicating-give-items-on-item-drop-cancel.patch deleted file mode 100644 index ef4ced2b1d..0000000000 --- a/Spigot-Server-Patches/Fix-duplicating-give-items-on-item-drop-cancel.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alphaesia -Date: Fri, 23 Apr 2021 09:57:56 +1200 -Subject: [PATCH] Fix duplicating /give items on item drop cancel - -Fixes SPIGOT-2942 (Give command fires PlayerDropItemEvent, cancelling it causes item duplication). - -For every stack of items to give, /give puts the item stack straight -into the player's inventory. However, it also summons a "fake item" -at the player's location. When the PlayerDropItemEvent for this fake -item is cancelled, the server attempts to put the item back into the -player's inventory. The result is that the fake item, which is never -meant to be obtained, is combined with the real items injected directly -into the player's inventory. This means more items than the amount -specified in /give are given to the player - one for every stack of -items given. (e.g. /give @s dirt 1 gives you 2 dirt). - -While this isn't a big issue for general building usage, it can affect -e.g. adventure maps where the number of items the player receives is -important (and you want to restrict the player from throwing items). - -If there are any overflow items that didn't make it into the inventory -(insufficient space), those items are dropped as a real item instead -of a fake one. While cancelling this drop would also result in the -server attempting to put those items into the inventory, since it is -full this has no effect. - -Just ignoring cancellation of the PlayerDropItemEvent seems like the -cleanest and least intrusive way to fix it. - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGive.java b/src/main/java/net/minecraft/server/commands/CommandGive.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGive.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGive.java -@@ -0,0 +0,0 @@ public class CommandGive { - - if (flag && itemstack.isEmpty()) { - itemstack.setCount(1); -- entityitem = entityplayer.drop(itemstack, false); -+ entityitem = entityplayer.drop(itemstack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel - if (entityitem != null) { - entityitem.s(); - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - - @Nullable - public EntityItem a(ItemStack itemstack, boolean flag, boolean flag1) { -+ // Paper start - Fix duplicating /give items on item drop cancel -+ return this.drop(itemstack, flag, flag1, false); -+ } -+ -+ @Nullable -+ public EntityItem drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { -+ // Paper end - if (itemstack.isEmpty()) { - return null; - } else { -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); - this.world.getServer().getPluginManager().callEvent(event); - -- if (event.isCancelled()) { -+ if (event.isCancelled() && !alwaysSucceed) { // Paper - Fix duplicating /give items on item drop cancel - org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand(); - if (flag1 && (cur == null || cur.getAmount() == 0)) { - // The complete stack was dropped diff --git a/Spigot-Server-Patches/Fix-enderdragon-exp-dupe.patch b/Spigot-Server-Patches/Fix-enderdragon-exp-dupe.patch deleted file mode 100644 index 9ce9e2dd24..0000000000 --- a/Spigot-Server-Patches/Fix-enderdragon-exp-dupe.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 22:25:11 -0700 -Subject: [PATCH] Fix enderdragon exp dupe - -Properly track death stage when unloading/loading in the -dragon - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); - nbttagcompound.setInt("DragonPhase", this.bG.a().getControllerPhase().b()); -+ nbttagcompound.setInt("Paper.DeathTick", this.deathAnimationTicks); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (nbttagcompound.hasKey("DragonPhase")) { - this.bG.setControllerPhase(DragonControllerPhase.getById(nbttagcompound.getInt("DragonPhase"))); - } -+ this.deathAnimationTicks = nbttagcompound.getInt("Paper.DeathTick"); // Paper - - } - diff --git a/Spigot-Server-Patches/Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/Spigot-Server-Patches/Fix-exploit-that-allowed-colored-signs-to-be-created.patch deleted file mode 100644 index fbf83424f5..0000000000 --- a/Spigot-Server-Patches/Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 0x22 <0x22@futureclient.net> -Date: Thu, 26 Apr 2018 04:41:11 -0400 -Subject: [PATCH] Fix exploit that allowed colored signs to be created - - -diff --git a/src/main/java/net/minecraft/SharedConstants.java b/src/main/java/net/minecraft/SharedConstants.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/SharedConstants.java -+++ b/src/main/java/net/minecraft/SharedConstants.java -@@ -0,0 +0,0 @@ public class SharedConstants { - return c0 != 167 && c0 >= ' ' && c0 != 127; - } - -+ public static String filterAllowedChatCharacters(String input) { return a(input); } // Paper - OBFHELPER - public static String a(String s) { - StringBuilder stringbuilder = new StringBuilder(); - char[] achar = s.toCharArray(); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(list.get(i))); -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); diff --git a/Spigot-Server-Patches/Fix-for-large-move-vectors-crashing-server.patch b/Spigot-Server-Patches/Fix-for-large-move-vectors-crashing-server.patch deleted file mode 100644 index 42c87fec18..0000000000 --- a/Spigot-Server-Patches/Fix-for-large-move-vectors-crashing-server.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 17 May 2020 23:47:33 -0700 -Subject: [PATCH] Fix for large move vectors crashing server - -Check movement distance also based on current position. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (entity != this.player && entity.getRidingPassenger() == this.player && entity == this.r) { - WorldServer worldserver = this.player.getWorldServer(); -- double d0 = entity.locX(); -- double d1 = entity.locY(); -- double d2 = entity.locZ(); -- double d3 = packetplayinvehiclemove.getX(); -- double d4 = packetplayinvehiclemove.getY(); -- double d5 = packetplayinvehiclemove.getZ(); -+ double d0 = entity.locX();double fromX = d0; // Paper - OBFHELPER -+ double d1 = entity.locY();double fromY = d1; // Paper - OBFHELPER -+ double d2 = entity.locZ();double fromZ = d2; // Paper - OBFHELPER -+ double d3 = packetplayinvehiclemove.getX();double toX = d3; // Paper - OBFHELPER -+ double d4 = packetplayinvehiclemove.getY();double toY = d4; // Paper - OBFHELPER -+ double d5 = packetplayinvehiclemove.getZ();double toZ = d5; // Paper - OBFHELPER - float f = packetplayinvehiclemove.getYaw(); - float f1 = packetplayinvehiclemove.getPitch(); - double d6 = d3 - this.s; - double d7 = d4 - this.t; - double d8 = d5 - this.u; - double d9 = entity.getMot().g(); -- double d10 = d6 * d6 + d7 * d7 + d8 * d8; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - fromX; -+ double currDeltaY = toY - fromY; -+ double currDeltaZ = toZ - fromZ; -+ double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - - // CraftBukkit start - handle custom speeds and skipped ticks -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d2 = this.player.locZ(); - double d3 = this.player.locY(); - double d4 = packetplayinflying.a(this.player.locX());double toX = d4; // Paper - OBFHELPER -- double d5 = packetplayinflying.b(this.player.locY()); -+ double d5 = packetplayinflying.b(this.player.locY());double toY = d5; // Paper - OBFHELPER - double d6 = packetplayinflying.c(this.player.locZ());double toZ = d6; // Paper - OBFHELPER - float f = packetplayinflying.a(this.player.yaw); - float f1 = packetplayinflying.b(this.player.pitch); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - double d8 = d5 - this.m; - double d9 = d6 - this.n; - double d10 = this.player.getMot().g(); -- double d11 = d7 * d7 + d8 * d8 + d9 * d9; -+ // Paper start - fix large move vectors killing the server -+ double currDeltaX = toX - prevX; -+ double currDeltaY = toY - prevY; -+ double currDeltaZ = toZ - prevZ; -+ double d11 = Math.max(d7 * d7 + d8 * d8 + d9 * d9, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); -+ // Paper end - fix large move vectors killing the server - - if (this.player.isSleeping()) { - if (d11 > 1.0D) { diff --git a/Spigot-Server-Patches/Fix-harming-potion-dupe.patch b/Spigot-Server-Patches/Fix-harming-potion-dupe.patch deleted file mode 100644 index de56bb26e2..0000000000 --- a/Spigot-Server-Patches/Fix-harming-potion-dupe.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: PepperCode1 <44146161+PepperCode1@users.noreply.github.com> -Date: Thu, 23 Jul 2020 14:25:07 -0700 -Subject: [PATCH] Fix harming potion dupe - -EntityLiving#applyInstantEffect() immediately kills the player and drops their inventory. -Before this patch, instant effects would be applied before the potion ItemStack is removed and replaced with a glass bottle. This caused the potion ItemStack to be dropped before it was supposed to be removed from the inventory. It also caused the glass bottle to be put into a dead player's inventory. -This patch makes it so that instant effects are applied after the potion ItemStack is removed, and the glass bottle is only put into the player's inventory if the player is not dead. Otherwise, the glass bottle is dropped on the ground. - -diff --git a/src/main/java/net/minecraft/world/item/ItemPotion.java b/src/main/java/net/minecraft/world/item/ItemPotion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemPotion.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.alchemy.PotionRegistry; - import net.minecraft.world.item.alchemy.PotionUtil; - import net.minecraft.world.item.alchemy.Potions; -+import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; - - public class ItemPotion extends Item { -@@ -0,0 +0,0 @@ public class ItemPotion extends Item { - CriterionTriggers.z.a((EntityPlayer) entityhuman, itemstack); - } - -+ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe - if (!world.isClientSide) { - List list = PotionUtil.getEffects(itemstack); - Iterator iterator = list.iterator(); -@@ -0,0 +0,0 @@ public class ItemPotion extends Item { - MobEffect mobeffect = (MobEffect) iterator.next(); - - if (mobeffect.getMobEffect().isInstant()) { -- mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); -+ instantLater.add(mobeffect); // Paper - Fix harming potion dupe - } else { - entityliving.addEffect(new MobEffect(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit - } -@@ -0,0 +0,0 @@ public class ItemPotion extends Item { - } - } - -+ // Paper start - Fix harming potion dupe -+ for (MobEffect mobeffect : instantLater) { -+ mobeffect.getMobEffect().applyInstantEffect(entityhuman, entityhuman, entityliving, mobeffect.getAmplifier(), 1.0D); -+ } -+ // Paper end -+ - if (entityhuman == null || !entityhuman.abilities.canInstantlyBuild) { -+ // Paper start - Fix harming potion dupe -+ if (entityliving.getHealth() <= 0 && !entityliving.world.getGameRules().getBoolean(GameRules.KEEP_INVENTORY)) { -+ entityliving.dropItem(new ItemStack(Items.GLASS_BOTTLE), 0); -+ return ItemStack.NULL_ITEM; -+ } -+ // Paper end -+ - if (itemstack.isEmpty()) { - return new ItemStack(Items.GLASS_BOTTLE); - } diff --git a/Spigot-Server-Patches/Fix-hex-colors-not-working-in-some-kick-messages.patch b/Spigot-Server-Patches/Fix-hex-colors-not-working-in-some-kick-messages.patch deleted file mode 100644 index a79f3ccd91..0000000000 --- a/Spigot-Server-Patches/Fix-hex-colors-not-working-in-some-kick-messages.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Thu, 27 Aug 2020 16:57:25 -0400 -Subject: [PATCH] Fix hex colors not working in some kick messages - - -diff --git a/src/main/java/net/minecraft/server/network/HandshakeListener.java b/src/main/java/net/minecraft/server/network/HandshakeListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/HandshakeListener.java -+++ b/src/main/java/net/minecraft/server/network/HandshakeListener.java -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); -- ChatMessage chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message -+ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage, true)[0]; // Paper - Configurable connection throttle kick message // Paper - Fix hex colors not working in some kick messages - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.c.close(chatmessage); - return; -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - } - // CraftBukkit end - if (packethandshakinginsetprotocol.c() != SharedConstants.getGameVersion().getProtocolVersion()) { -- ChatMessage chatmessage; -+ IChatBaseComponent chatmessage; // Paper - Fix hex colors not working in some kick messages - - if (packethandshakinginsetprotocol.c() < 754) { -- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } else { -- chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot -+ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages - } - - this.c.sendPacket(new PacketLoginOutDisconnect(chatmessage)); -@@ -0,0 +0,0 @@ public class HandshakeListener implements PacketHandshakingInListener { - if (event.callEvent()) { - // If we've failed somehow, let the client know so and go no further. - if (event.isFailed()) { -- chatmessage = new ChatMessage(event.getFailMessage()); -+ IChatBaseComponent chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages - this.getNetworkManager().sendPacket(new PacketLoginOutDisconnect(chatmessage)); - this.getNetworkManager().close(chatmessage); - return; -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - // CraftBukkit start - @Deprecated - public void disconnect(String s) { -- try { -- IChatBaseComponent ichatbasecomponent = new ChatComponentText(s); -- LoginListener.LOGGER.info("Disconnecting {}: {}", this.d(), s); -- this.networkManager.sendPacket(new PacketLoginOutDisconnect(ichatbasecomponent)); -- this.networkManager.close(ichatbasecomponent); -- } catch (Exception exception) { -- LoginListener.LOGGER.error("Error whilst disconnecting player", exception); -- } -+ disconnect(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s, true)[0]); // Paper - Fix hex colors not working in some kick messages - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch b/Spigot-Server-Patches/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch deleted file mode 100644 index f777c9c767..0000000000 --- a/Spigot-Server-Patches/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 10 May 2021 15:46:57 -0700 -Subject: [PATCH] Fix incorrect status dataconverter for pre 1.13 chunks - -Vanilla was setting non-populated OR non-lit chunks to empty, but -really this is just completely wrong. It should be set to "carved" -at minmum, because pre 1.13 chunks went through 3 distinct stages -of generation: carving, population, and lighting - in this order. -There is no "empty" status, because a chunk was simply carved -or it didn't exist. So mapping any chunk data to empty is simply -invalid. - -If the chunk is terrain populated, then obviously it must be at -minmum "decorated." If the chunk is lit and populated, then it is marked -"mobs_spawned" (which is what Vanilla is doing, and this is the last -stage before moving to full so it looks correct). - -So now here is a table representing the new status conversion: - -Chunk is lit Chunk is populated Vanilla - F F empty - T F empty - F T empty - T T mobs_spawned - -Chunk is lit Chunk is populated Paper - F F carved - T F carved - F T decorated - T T mobs_spawned - -This should fix some problems converting old data, as the -changes here are going to prevent the chunk from being regenerated -incorrectly. - -diff --git a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java -+++ b/src/main/java/net/minecraft/util/datafix/fixes/DataConverterProtoChunk.java -@@ -0,0 +0,0 @@ public class DataConverterProtoChunk extends DataFix { - return dynamic.asStreamOpt().result(); - }); - Dynamic dynamic = (Dynamic) typed1.get(DSL.remainderFinder()); -- boolean flag = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); -- -- dynamic = dynamic.set("Status", dynamic.createString(flag ? "mobs_spawned" : "empty")); -+ // Paper start - fix incorrect status conversion -+ // Vanilla is setting chunks to incorrect status here, they should be using at minimum carved. -+ // for populated chunks, it should be at minimum decorated -+ // and for lit and populated, mobs_spawned is correct (technically mobs_spawned should be for populated, -+ // but if it's not lit then it can't be set above lit) -+ final boolean terrainPopulated = dynamic.get("TerrainPopulated").asBoolean(false); -+ final boolean lightPopulated = dynamic.get("LightPopulated").asBoolean(false) || dynamic.get("LightPopulated").asNumber().result().isPresent(); -+ final String newStatus = !terrainPopulated ? "carved" : (lightPopulated ? "mobs_spawned" : "decorated"); -+ -+ dynamic = dynamic.set("Status", dynamic.createString(newStatus)); - dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); -- Dynamic dynamic1; -+ // Paper end - fix incorrect status conversion -+ Dynamic dynamic1; // Paper - decompile fix - -- if (flag) { -+ if (true) { // Paper - fix incorrect status conversion - Optional optional1 = dynamic.get("Biomes").asByteBufferOpt().result(); - - if (optional1.isPresent()) { -@@ -0,0 +0,0 @@ public class DataConverterProtoChunk extends DataFix { - }).collect(Collectors.toList()); - - if (optional.isPresent()) { -- ((Stream) optional.get()).forEach((dynamic2) -> { -+ optional.get().forEach((dynamic2) -> { // Paper - decompile fix - int j = dynamic2.get("x").asInt(0); - int k = dynamic2.get("y").asInt(0); - int l = dynamic2.get("z").asInt(0); -@@ -0,0 +0,0 @@ public class DataConverterProtoChunk extends DataFix { - - ((ShortList) list.get(k >> 4)).add(short0); - }); -+ Dynamic finalDynamic = dynamic; // Paper - decompile fix - dynamic = dynamic.set("ToBeTicked", dynamic.createList(list.stream().map((shortlist) -> { -- Stream stream = shortlist.stream(); -+ Stream stream = shortlist.stream(); // Paper - decompile fix - -- dynamic.getClass(); -- return dynamic.createList(stream.map(dynamic::createShort)); -+ return finalDynamic.createList(stream.map(finalDynamic::createShort)); - }))); - } - diff --git a/Spigot-Server-Patches/Fix-interact-event-not-being-called-in-adventure.patch b/Spigot-Server-Patches/Fix-interact-event-not-being-called-in-adventure.patch deleted file mode 100644 index 206b781c2b..0000000000 --- a/Spigot-Server-Patches/Fix-interact-event-not-being-called-in-adventure.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheMolkaPL -Date: Sun, 21 Jun 2020 17:21:46 +0200 -Subject: [PATCH] Fix interact event not being called in adventure - -Call PlayerInteractEvent when left-clicking on a block in adventure mode - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - IChatMutableComponent ichatmutablecomponent = (new ChatMessage("build.tooHigh", new Object[]{this.minecraftServer.getMaxBuildHeight()})).a(EnumChatFormat.RED); - - this.player.playerConnection.sendPacket(new PacketPlayOutChat(ichatmutablecomponent, ChatMessageType.GAME_INFO, SystemUtils.b)); -- } else if (enuminteractionresult.b()) { -+ } else if (enuminteractionresult.b() && !this.player.playerInteractManager.interactResult) { - this.player.swingHand(enumhand, true); - } - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); - MovingObjectPosition movingobjectposition = this.player.world.rayTrace(new RayTrace(vec3d, vec3d1, RayTrace.BlockCollisionOption.OUTLINE, RayTrace.FluidCollisionOption.NONE, player)); - -- if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK) { -+ if (movingobjectposition == null || movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.BLOCK || this.player.playerInteractManager.getGameMode() == EnumGamemode.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode - CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.inventory.getItemInHand(), EnumHand.MAIN_HAND); - } - diff --git a/Spigot-Server-Patches/Fix-invulnerable-end-crystals.patch b/Spigot-Server-Patches/Fix-invulnerable-end-crystals.patch deleted file mode 100644 index 69839d4346..0000000000 --- a/Spigot-Server-Patches/Fix-invulnerable-end-crystals.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Max Lee -Date: Thu, 27 May 2021 14:52:30 -0700 -Subject: [PATCH] Fix invulnerable end crystals - -MC-108513 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void fixItemsMergingThroughWalls() { - fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); - } -+ -+ public boolean fixInvulnerableEndCrystalExploit = true; -+ private void fixInvulnerableEndCrystalExploit() { -+ fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderCrystal.java -@@ -0,0 +0,0 @@ public class EntityEnderCrystal extends Entity { - private static final DataWatcherObject> c = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.m); - private static final DataWatcherObject d = DataWatcher.a(EntityEnderCrystal.class, DataWatcherRegistry.i); - public int b; -+ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals - - public EntityEnderCrystal(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityEnderCrystal extends Entity { - } - // CraftBukkit end - } -+ // Paper start - Fix invulnerable end crystals -+ if (this.world.paperConfig.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { -+ if ((this.origin.getWorld() != null && !((WorldServer) this.world).uuid.equals(this.origin.getWorld().getUID())) -+ || ((WorldServer) this.world).getDragonBattle() == null -+ || ((WorldServer) this.world).getDragonBattle().respawnPhase == null -+ || ((WorldServer) this.world).getDragonBattle().respawnPhase.ordinal() > net.minecraft.world.level.dimension.end.EnumDragonRespawn.SUMMONING_DRAGON.ordinal()) { -+ this.setInvulnerable(false); -+ this.setBeamTarget(null); -+ } -+ } -+ // Paper end - } - - } -@@ -0,0 +0,0 @@ public class EntityEnderCrystal extends Entity { - } - - nbttagcompound.setBoolean("ShowBottom", this.isShowingBottom()); -+ if (this.generatedByDragonFight) nbttagcompound.setBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals - } - - @Override -@@ -0,0 +0,0 @@ public class EntityEnderCrystal extends Entity { - if (nbttagcompound.hasKeyOfType("ShowBottom", 1)) { - this.setShowingBottom(nbttagcompound.getBoolean("ShowBottom")); - } -+ if (nbttagcompound.hasKeyOfType("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = nbttagcompound.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals - - } - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEnder.java -@@ -0,0 +0,0 @@ public class WorldGenEnder extends WorldGenerator list = worldgenfeatureendspikeconfiguration.c(); - - if (list.isEmpty()) { -@@ -0,0 +0,0 @@ public class WorldGenEnder extends WorldGenerator -Date: Fri, 28 Sep 2018 21:49:53 -0400 -Subject: [PATCH] Fix issues with entity loss due to unloaded chunks - -Vanilla has risk of losing entities by causing them to be -removed from all chunks if they try to move into an unloaded chunk. - -This pretty much means high chance this entity will be lost in this -scenario. - -There is another case that adding an entity to the world can fail if -the chunk isn't loaded. - -Lots of the server is designed around addEntity never expecting to fail -for these reasons, nor is it really logical. - -This change ensures the chunks are always loaded when entities are -added to the world, or a valid entity moves between chunks. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - int k = MathHelper.floor(entity.locZ() / 16.0D); - - if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) { -+ // Paper start - remove entity if its in a chunk more correctly. -+ Chunk currentChunk = entity.getCurrentChunk(); -+ if (currentChunk != null) { -+ currentChunk.removeEntity(entity); -+ } -+ // Paper end -+ - if (entity.inChunk && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) { - this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.chunkY); - } - -- if (!entity.ck() && !this.isChunkLoaded(i, k)) { -+ if (!entity.valid && !entity.ck() && !this.isChunkLoaded(i, k)) { // Paper - always load chunks to register valid entities location - if (entity.inChunk) { - WorldServer.LOGGER.warn("Entity {} left loaded chunk area", entity); - } -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return false; - } - // CraftBukkit end -- IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, entity.attachedToPlayer); -+ IChunkAccess ichunkaccess = this.getChunkAt(MathHelper.floor(entity.locX() / 16.0D), MathHelper.floor(entity.locZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds - - if (!(ichunkaccess instanceof Chunk)) { - return false; diff --git a/Spigot-Server-Patches/Fix-item-locations-dropped-from-campfires.patch b/Spigot-Server-Patches/Fix-item-locations-dropped-from-campfires.patch deleted file mode 100644 index c300f1e338..0000000000 --- a/Spigot-Server-Patches/Fix-item-locations-dropped-from-campfires.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sat, 3 Oct 2020 20:32:25 -0500 -Subject: [PATCH] Fix item locations dropped from campfires - -Fixes #4259 by not flooring the blockposition among other weirdness - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityCampfire.java -@@ -0,0 +0,0 @@ import net.minecraft.world.Clearable; - import net.minecraft.world.ContainerUtil; - import net.minecraft.world.InventorySubcontainer; - import net.minecraft.world.InventoryUtils; -+import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.RecipeCampfire; - import net.minecraft.world.item.crafting.Recipes; -@@ -0,0 +0,0 @@ public class TileEntityCampfire extends TileEntity implements Clearable, ITickab - result = blockCookEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - // CraftBukkit end -- InventoryUtils.dropItem(this.world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1); -+ // Paper start -+ EntityItem droppedItem = new EntityItem(this.world, blockposition.getX() + 0.5D, blockposition.getY() + 0.5D, blockposition.getZ() + 0.5D, itemstack1.cloneAndSubtract(this.world.random.nextInt(21) + 10)); -+ droppedItem.setMot(this.world.random.nextGaussian() * 0.05D, this.world.random.nextGaussian() * 0.05D + 0.2D, this.world.random.nextGaussian() * 0.05D); -+ this.world.addEntity(droppedItem); -+ // Paper end - this.items.set(i, ItemStack.b); - this.k(); - } diff --git a/Spigot-Server-Patches/Fix-items-not-falling-correctly.patch b/Spigot-Server-Patches/Fix-items-not-falling-correctly.patch deleted file mode 100644 index 69bff970cc..0000000000 --- a/Spigot-Server-Patches/Fix-items-not-falling-correctly.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Fri, 17 Jan 2020 17:17:54 -0600 -Subject: [PATCH] Fix items not falling correctly - -Since 1.14, Mojang has added an optimization which skips checking if -an item should fall every fourth tick. - -However, Spigot's entity activation range class also has an -optimization which skips ticking active entities every fourth tick. -This can result in a state where an item will never properly fall -due to its move method never being called. - -This patch resolves the conflict by offsetting checking an item's -move method from Spigot's entity activation range check. - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - } - } - -- if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || (this.ticksLived + this.getId()) % 4 == 0) { -+ if (!this.onGround || c(this.getMot()) > 9.999999747378752E-6D || this.ticksLived % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check - this.move(EnumMoveType.SELF, this.getMot()); - float f1 = 0.98F; - diff --git a/Spigot-Server-Patches/Fix-items-vanishing-through-end-portal.patch b/Spigot-Server-Patches/Fix-items-vanishing-through-end-portal.patch deleted file mode 100644 index 0ed2564cc5..0000000000 --- a/Spigot-Server-Patches/Fix-items-vanishing-through-end-portal.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AJMFactsheets -Date: Wed, 22 Jan 2020 19:52:28 -0600 -Subject: [PATCH] Fix items vanishing through end portal - -If the Paper configuration option "keep-spawn-loaded" is set to false, -items entering the overworld from the end will spawn at Y = 0. - -This is due to logic in the getHighestBlockYAt method in World.java -only searching the heightmap if the chunk is loaded. - -Quickly loading the exact world spawn chunk before searching the -heightmap resolves the issue without having to load all spawn chunks. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - BlockPosition blockposition1; - - if (flag1) { -+ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate -+ this.world.getChunkAtWorldCoords(this.world.getSpawn()); -+ // Paper end - blockposition1 = WorldServer.a; - } else { - blockposition1 = worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn()); diff --git a/Spigot-Server-Patches/Fix-lag-from-explosions-processing-dead-entities.patch b/Spigot-Server-Patches/Fix-lag-from-explosions-processing-dead-entities.patch deleted file mode 100644 index fc9fdbf52a..0000000000 --- a/Spigot-Server-Patches/Fix-lag-from-explosions-processing-dead-entities.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Iceee -Date: Wed, 2 Mar 2016 01:39:52 -0600 -Subject: [PATCH] Fix lag from explosions processing dead entities - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -0,0 +0,0 @@ public class Explosion { - int i1 = MathHelper.floor(this.posY + (double) f2 + 1.0D); - int j1 = MathHelper.floor(this.posZ - (double) f2 - 1.0D); - int k1 = MathHelper.floor(this.posZ + (double) f2 + 1.0D); -- List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); -+ List list = this.world.getEntities(this.source, new AxisAlignedBB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1), (com.google.common.base.Predicate) entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities - Vec3D vec3d = new Vec3D(this.posX, this.posY, this.posZ); - - for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/Spigot-Server-Patches/Fix-last-firework-in-stack-not-having-effects-when-d.patch b/Spigot-Server-Patches/Fix-last-firework-in-stack-not-having-effects-when-d.patch deleted file mode 100644 index d82c491966..0000000000 --- a/Spigot-Server-Patches/Fix-last-firework-in-stack-not-having-effects-when-d.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 17 Jan 2020 18:44:55 -0800 -Subject: [PATCH] Fix last firework in stack not having effects when dispensed - - #2871 - -CB used the resulting item in the dispenser rather than the item -dispensed. The resulting item would have size == 0 and therefore -be convertered to air, hence why the effects disappeared. - -diff --git a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -+++ b/src/main/java/net/minecraft/core/dispenser/IDispenseBehavior.java -@@ -0,0 +0,0 @@ public interface IDispenseBehavior { - } - - itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); -- EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); -+ EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack1, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed - - IDispenseBehavior.a(isourceblock, entityfireworks, enumdirection); - entityfireworks.shoot((double) enumdirection.getAdjacentX(), (double) enumdirection.getAdjacentY(), (double) enumdirection.getAdjacentZ(), 0.5F, 1.0F); diff --git a/Spigot-Server-Patches/Fix-missing-chunks-due-to-integer-overflow.patch b/Spigot-Server-Patches/Fix-missing-chunks-due-to-integer-overflow.patch deleted file mode 100644 index a02a965a2c..0000000000 --- a/Spigot-Server-Patches/Fix-missing-chunks-due-to-integer-overflow.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Slovikosky -Date: Tue, 9 Jun 2020 00:10:03 -0700 -Subject: [PATCH] Fix missing chunks due to integer overflow - -This patch fixes a bug in the WorldChunkManagerTheEnd class where the distance -from 0,0 squared overflows the maximum size of an integer. The overflow leads -to hard chunk borders around 370,000 blocks from 0,0. After this cutoff there -is a few hundred thousand block gap before end land resuming to generate at -530,000 blocks from spawn. This is due to the integer flipping back and forth. - -The fix for the issue is quite simple, casting chunk coordinates to longs -allows the distance calculation to avoid overflow and work as intended. - -diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -@@ -0,0 +0,0 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - int l = j / 2; - int i1 = i % 2; - int j1 = j % 2; -- float f = 100.0F - MathHelper.c((float) (i * i + j * j)) * 8.0F; -+ // Paper start - cast ints to long to avoid integer overflow -+ float f = 100.0F - MathHelper.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; -+ // Paper end - - f = MathHelper.a(f, -100.0F, 80.0F); - diff --git a/Spigot-Server-Patches/Fix-nerfed-slime-when-splitting.patch b/Spigot-Server-Patches/Fix-nerfed-slime-when-splitting.patch deleted file mode 100644 index 807a2ce72c..0000000000 --- a/Spigot-Server-Patches/Fix-nerfed-slime-when-splitting.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 24 Aug 2020 08:39:06 -0700 -Subject: [PATCH] Fix nerfed slime when splitting - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - entityslime.setPersistent(); - } - -+ entityslime.aware = this.aware; // Paper - entityslime.setCustomName(ichatbasecomponent); - entityslime.setNoAI(flag); - entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/Spigot-Server-Patches/Fix-numerous-item-duplication-issues-and-teleport-is.patch b/Spigot-Server-Patches/Fix-numerous-item-duplication-issues-and-teleport-is.patch deleted file mode 100644 index 86cbe8626a..0000000000 --- a/Spigot-Server-Patches/Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 25 Apr 2020 06:46:35 -0400 -Subject: [PATCH] Fix numerous item duplication issues and teleport issues - -This notably fixes the newest "Donkey Dupe", but also fixes a lot -of dupe bugs in general around nether portals and entity world transfer - -We also fix item duplication generically by anytime we clone an item -to drop it on the ground, destroy the source item. - -This avoid an itemstack ever existing twice in the world state pre -clean up stage. - -So even if something NEW comes up, it would be impossible to drop the -same item twice because the source was destroyed. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } else { - // CraftBukkit start - Capture drops for death event - if (this instanceof EntityLiving && !((EntityLiving) this).forceDrops) { -- ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); -+ ((EntityLiving) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // Paper - mirror so we can destroy it later - return null; - } - // CraftBukkit end -- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack); -+ EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY() + (double) f, this.locZ(), itemstack.cloneItemStack()); // Paper - clone so we can destroy original -+ itemstack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe - - entityitem.defaultPickupDelay(); - // CraftBukkit start -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - @Nullable - public Entity teleportTo(WorldServer worldserver, BlockPosition location) { - // CraftBukkit end -+ // Paper start - fix bad state entities causing dupes -+ if (!isAlive() || !valid) { -+ LOGGER.warn("Illegal Entity Teleport " + this + " to " + worldserver + ":" + location, new Throwable()); -+ return null; -+ } -+ // Paper end - if (this.world instanceof WorldServer && !this.dead) { - this.world.getMethodProfiler().enter("changeDimension"); - // CraftBukkit start -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - // CraftBukkit end - - this.world.getMethodProfiler().exitEnter("reloading"); -+ // Paper start - Change lead drop timing to prevent dupe -+ if (this instanceof EntityInsentient) { -+ ((EntityInsentient) this).unleash(true, true); // Paper drop lead -+ } -+ // Paper end - Entity entity = this.getEntityType().a((World) worldserver); - - if (entity != null) { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - // CraftBukkit start - Forward the CraftEntity to the new entity - this.getBukkitEntity().setHandle(entity); - entity.bukkitEntity = this.getBukkitEntity(); -- -- if (this instanceof EntityInsentient) { -- ((EntityInsentient) this).unleash(true, false); // Unleash to prevent duping of leads. -- } - // CraftBukkit end - } - -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean canPortal() { -- return true; -+ return isAlive() && valid; // Paper - } - - public float a(Explosion explosion, IBlockAccess iblockaccess, BlockPosition blockposition, IBlockData iblockdata, Fluid fluid, float f) { -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - for (i = 0; i < this.handItems.size(); ++i) { - itemstack = (ItemStack) this.handItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.handItems.set(i, ItemStack.b); - } - } -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - for (i = 0; i < this.armorItems.size(); ++i) { - itemstack = (ItemStack) this.armorItems.get(i); - if (!itemstack.isEmpty()) { -- drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops -+ drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe - this.armorItems.set(i, ItemStack.b); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { - if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue; - -- world.dropItem(entity.getLocation(), stack); -+ world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS -+ if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items - } - - return event; diff --git a/Spigot-Server-Patches/Fix-piston-physics-inconsistency-MC-188840.patch b/Spigot-Server-Patches/Fix-piston-physics-inconsistency-MC-188840.patch deleted file mode 100644 index 6ced3c8536..0000000000 --- a/Spigot-Server-Patches/Fix-piston-physics-inconsistency-MC-188840.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 11 Jun 2020 17:29:42 -0700 -Subject: [PATCH] Fix piston physics inconsistency - MC-188840 - -Pistons invoke physics when they move blocks. The physics can cause -tnt blocks to ignite. However, pistons (when storing the blocks they "moved") -don't actually go back to the world state sometimes to check if something -like that happened. As a result they end up moving the tnt like it was -never ignited. This resulted in the ability to create machines -that can duplicate tnt, called "world eaters". -This patch makes the piston logic retrieve the block state from the world -prevent this from occuring. - -This patch also sets the moved pos to air immediately after creating -the moving piston TE. This prevents the block from being updated from -other physics calls by the piston. - -Tested against the following tnt duper design: -https://www.youtube.com/watch?v=mS7xxNGhjxs - -This patch also affects every type of machine that utilises -this mechanic. For example, dead coral is removed by a physics -update when being moved while it is attached to slimeblocks. - -Standard piston machines that don't destroy or modify the -blocks they move by physics updates should be entirely -unaffected. - -This patch fixes https://bugs.mojang.com/browse/MC-188840 - -This patch also fixes rail duping and carpet duping. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - consoleHasAllPermissions = getBoolean("settings.console-has-all-permissions", consoleHasAllPermissions); - } - -+ public static boolean allowPistonDuplication; -+ private static void allowPistonDuplication() { -+ config.set("settings.unsupported-settings.allow-piston-duplication-readme", "This setting controls if player should be able to use TNT duplication, but this also allows duplicating carpet, rails and potentially other items"); -+ allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); -+ set("settings.unsupported-settings.allow-tnt-duplication", null); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -0,0 +0,0 @@ public class BlockPiston extends BlockDirectional { - } - - for (k = list.size() - 1; k >= 0; --k) { -- blockposition3 = (BlockPosition) list.get(k); -- iblockdata1 = world.getType(blockposition3); -+ // Paper start - fix a variety of piston desync dupes -+ boolean allowDesync = com.destroystokyo.paper.PaperConfig.allowPistonDuplication; -+ BlockPosition oldPos = blockposition3 = (BlockPosition) list.get(k); -+ iblockdata1 = allowDesync ? world.getType(oldPos) : null; -+ // Paper end - fix a variety of piston desync dupes - blockposition3 = blockposition3.shift(enumdirection1); - map.remove(blockposition3); - world.setTypeAndData(blockposition3, (IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPiston.FACING, enumdirection), 68); -- world.setTileEntity(blockposition3, BlockPistonMoving.a((IBlockData) list1.get(k), enumdirection, flag, false)); -+ // Paper start - fix a variety of piston desync dupes -+ if (!allowDesync) { -+ iblockdata1 = world.getType(oldPos); -+ map.replace(oldPos, iblockdata1); -+ } -+ world.setTileEntity(blockposition3, BlockPistonMoving.a(allowDesync ? list1.get(k) : iblockdata1, enumdirection, flag, false)); -+ if (!allowDesync) { -+ world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block -+ } -+ // Paper end - fix a variety of piston desync dupes - aiblockdata[j++] = iblockdata1; - } - -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -0,0 +0,0 @@ public class TileEntityPiston extends TileEntity implements ITickable { - IBlockData iblockdata = Block.b(this.a, (GeneratorAccess) this.world, this.position); - - if (iblockdata.isAir()) { -- this.world.setTypeAndData(this.position, this.a, 84); -+ this.world.setTypeAndData(this.position, this.a, com.destroystokyo.paper.PaperConfig.allowPistonDuplication ? 84 : (84 | 2)); // Paper - force notify (flag 2), it's possible the set type by the piston block (which doesn't notify) set this block to air - Block.a(this.a, iblockdata, this.world, this.position, 3); - } else { - if (iblockdata.b(BlockProperties.C) && (Boolean) iblockdata.get(BlockProperties.C)) { diff --git a/Spigot-Server-Patches/Fix-reducedDebugInfo-not-initialized-on-client.patch b/Spigot-Server-Patches/Fix-reducedDebugInfo-not-initialized-on-client.patch deleted file mode 100644 index d2ffbe614b..0000000000 --- a/Spigot-Server-Patches/Fix-reducedDebugInfo-not-initialized-on-client.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Sat, 2 Apr 2016 20:37:03 -0400 -Subject: [PATCH] Fix reducedDebugInfo not initialized on client - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - playerconnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex)); - playerconnection.sendPacket(new PacketPlayOutRecipeUpdate(this.server.getCraftingManager().b())); - playerconnection.sendPacket(new PacketPlayOutTags(this.server.getTagRegistry())); -+ playerconnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, (byte) (worldserver1.getGameRules().getBoolean(GameRules.REDUCED_DEBUG_INFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client - this.d(entityplayer); - entityplayer.getStatisticManager().c(); - entityplayer.getRecipeBook().a(entityplayer); diff --git a/Spigot-Server-Patches/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/Spigot-Server-Patches/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch deleted file mode 100644 index 2a81479287..0000000000 --- a/Spigot-Server-Patches/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: mbax -Date: Mon, 17 Aug 2020 12:17:37 -0400 -Subject: [PATCH] Fix regex mistake in CB NBT int deserialization - -The existing regex is too open and allows for the absence of any actual -number data, detecting an NBT entry of just the letter "i" in upper or -lower case. This causes a single-character NBT entry to be processed as -an integer ending in "i", passing an empty String to to Integer.parseInt, -triggering an exception in loading the item. - -This commit forces numbers to be present prior to the ending "i" -letter. - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializer.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagString; - public class CraftNBTTagConfigSerializer { - - private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); -- private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", Pattern.CASE_INSENSITIVE); -+ private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)i", Pattern.CASE_INSENSITIVE); // Paper - fix regex - private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", Pattern.CASE_INSENSITIVE); - private static final MojangsonParser MOJANGSON_PARSER = new MojangsonParser(new StringReader("")); - diff --git a/Spigot-Server-Patches/Fix-sand-duping.patch b/Spigot-Server-Patches/Fix-sand-duping.patch deleted file mode 100644 index ee660b7d9e..0000000000 --- a/Spigot-Server-Patches/Fix-sand-duping.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 13:33:19 -0700 -Subject: [PATCH] Fix sand duping - -If the falling block dies during teleportation (entity#move), then we need -to detect that by placing a check after the move. - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { - - @Override - public void tick() { -+ // Paper start - fix sand duping -+ if (this.dead) { -+ return; -+ } -+ // Paper end - fix sand duping - if (this.block.isAir()) { - this.die(); - } else { -@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { - - this.move(EnumMoveType.SELF, this.getMot()); - -+ // Paper start - fix sand duping -+ if (this.dead) { -+ return; -+ } -+ // Paper end - fix sand duping -+ - // Paper start - Configurable EntityFallingBlock height nerf - if (this.world.paperConfig.fallingBlockHeightNerf != 0 && this.locY() > this.world.paperConfig.fallingBlockHeightNerf) { - if (this.dropItem && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) { diff --git a/Spigot-Server-Patches/Fix-sign-edit-memory-leak.patch b/Spigot-Server-Patches/Fix-sign-edit-memory-leak.patch deleted file mode 100644 index 49c7b72ab3..0000000000 --- a/Spigot-Server-Patches/Fix-sign-edit-memory-leak.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Feb 2019 00:15:28 -0500 -Subject: [PATCH] Fix sign edit memory leak - -when a player edits a sign, a reference to their Entity is never cleand up. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - TileEntitySign tileentitysign = (TileEntitySign) tileentity; - -- if (!tileentitysign.d() || tileentitysign.f() != this.player) { -+ if (!tileentitysign.d() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUniqueID())) { - PlayerConnection.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getDisplayName().getString()); - this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit - return; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntitySign.java -@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - private EntityHuman c; - private final FormattedString[] g; - private EnumColor color; -+ public java.util.UUID signEditor; // Paper - - public TileEntitySign() { - super(TileEntityTypes.SIGN); -@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // - } - - public void a(EntityHuman entityhuman) { -- this.c = entityhuman; -+ // Paper start -+ //this.c = entityhuman; -+ signEditor = entityhuman != null ? entityhuman.getUniqueID() : null; -+ // Paper end - } - - public EntityHuman f() { diff --git a/Spigot-Server-Patches/Fix-some-rails-connecting-improperly.patch b/Spigot-Server-Patches/Fix-some-rails-connecting-improperly.patch deleted file mode 100644 index b9515aae81..0000000000 --- a/Spigot-Server-Patches/Fix-some-rails-connecting-improperly.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 24 Jul 2020 15:56:05 -0700 -Subject: [PATCH] Fix some rails connecting improperly - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartDetector.java -@@ -0,0 +0,0 @@ public class BlockMinecartDetector extends BlockMinecartTrackAbstract { - - private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { - if (this.canPlace(iblockdata, world, blockposition)) { -+ if (iblockdata.getBlock() != this) { return; } // Paper - not our block, don't do anything - boolean flag = (Boolean) iblockdata.get(BlockMinecartDetector.POWERED); - boolean flag1 = false; - List list = this.a(world, blockposition, EntityMinecartAbstract.class, (Predicate) null); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockMinecartTrackAbstract.java -@@ -0,0 +0,0 @@ public abstract class BlockMinecartTrackAbstract extends Block { - iblockdata = this.a(world, blockposition, iblockdata, true); - if (this.c) { - iblockdata.doPhysics(world, blockposition, this, blockposition, flag); -+ iblockdata = world.getType(blockposition); // Paper - don't desync, update again - } - - return iblockdata; -diff --git a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -+++ b/src/main/java/net/minecraft/world/level/block/MinecartTrackLogic.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.properties.BlockPropertyTrackPositi - - public class MinecartTrackLogic { - -- private final World a; -- private final BlockPosition b; -+ private final World a; public final World getWorld() { return this.a; } // Paper - OBFHELPER -+ private final BlockPosition b; public final BlockPosition getPos() { return this.b; } // Paper - OBFHELPER - private final BlockMinecartTrackAbstract c; -- private IBlockData d; -+ private IBlockData d; public final IBlockData getRailState() { return this.d; } // Paper - OBFHELPER - private final boolean e; - private final List f = Lists.newArrayList(); - -+ // Paper start - prevent desync -+ public boolean isValid() { -+ return this.getWorld().getType(this.getPos()).getBlock() == this.getRailState().getBlock(); -+ } -+ // Paper end - prevent desync -+ - public MinecartTrackLogic(World world, BlockPosition blockposition, IBlockData iblockdata) { - this.a = world; - this.b = blockposition; -@@ -0,0 +0,0 @@ public class MinecartTrackLogic { - } - - private void c(MinecartTrackLogic minecarttracklogic) { -+ // Paper start - prevent desync -+ if (!this.isValid() || !minecarttracklogic.isValid()) { -+ return; -+ } -+ // Paper end - prevent desync - this.f.add(minecarttracklogic.b); - BlockPosition blockposition = this.b.north(); - BlockPosition blockposition1 = this.b.south(); -@@ -0,0 +0,0 @@ public class MinecartTrackLogic { - this.d = (IBlockData) this.d.set(this.c.d(), blockpropertytrackposition1); - if (flag1 || this.a.getType(this.b) != this.d) { - this.a.setTypeAndData(this.b, this.d, 3); -+ // Paper start - prevent desync -+ if (!this.isValid()) { -+ return this; -+ } -+ // Paper end - prevent desync - - for (int i = 0; i < this.f.size(); ++i) { - MinecartTrackLogic minecarttracklogic = this.b((BlockPosition) this.f.get(i)); - -- if (minecarttracklogic != null) { -+ if (minecarttracklogic != null && minecarttracklogic.isValid()) { // Paper - prevent desync - minecarttracklogic.d(); - if (minecarttracklogic.b(this)) { - minecarttracklogic.c(this); -@@ -0,0 +0,0 @@ public class MinecartTrackLogic { - } - - public IBlockData c() { -- return this.d; -+ return this.getWorld().getType(this.getPos()); // Paper - prevent desync - } - } diff --git a/Spigot-Server-Patches/Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/Spigot-Server-Patches/Fix-sounds-when-item-frames-are-modified-MC-123450.patch deleted file mode 100644 index aac7b63a1a..0000000000 --- a/Spigot-Server-Patches/Fix-sounds-when-item-frames-are-modified-MC-123450.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 27 Apr 2019 20:00:43 +0100 -Subject: [PATCH] Fix sounds when item frames are modified (MC-123450) - -This also fixes the adding sound playing when the item frame direction is changed. - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityItemFrame.java -@@ -0,0 +0,0 @@ public class EntityItemFrame extends EntityHanging { - } - - this.getDataWatcher().set(EntityItemFrame.ITEM, itemstack); -- if (!itemstack.isEmpty() && playSound) { // CraftBukkit -+ if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set - this.playSound(SoundEffects.ENTITY_ITEM_FRAME_ADD_ITEM, 1.0F, 1.0F); - } - diff --git a/Spigot-Server-Patches/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/Spigot-Server-Patches/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch deleted file mode 100644 index 05a729bd3c..0000000000 --- a/Spigot-Server-Patches/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterErwin -Date: Wed, 30 Oct 2019 16:57:54 +0100 -Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and - can not face UP or DOWN - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - height = 9; - } - -- BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ // Paper start - In addition to d65a2576e40e58c8e446b330febe6799d13a604f do not check UP/DOWN for non item frames -+ // BlockFace[] faces = new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN}; -+ BlockFace[] faces = (ItemFrame.class.isAssignableFrom(clazz)) -+ ? new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH, BlockFace.UP, BlockFace.DOWN} -+ : new BlockFace[]{BlockFace.EAST, BlockFace.NORTH, BlockFace.WEST, BlockFace.SOUTH}; -+ // Paper end - final BlockPosition pos = new BlockPosition(x, y, z); - for (BlockFace dir : faces) { - IBlockData nmsBlock = world.getType(pos.shift(CraftBlock.blockFaceToNotch(dir))); diff --git a/Spigot-Server-Patches/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/Spigot-Server-Patches/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch deleted file mode 100644 index db9f230d16..0000000000 --- a/Spigot-Server-Patches/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 9 Oct 2019 21:51:43 -0500 -Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657) - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.lastHealthSent = -1.0F; - this.lastFoodSent = -1; - -+ setSneaking(false); // Paper - fix MC-10657 -+ - // CraftBukkit start - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); - this.world.getServer().getPluginManager().callEvent(changeEvent); -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(entityplayer.getId(), mobEffect)); - } - -+ entityplayer.setSneaking(false); // Paper - fix MC-10657 -+ - // Fire advancement trigger - entityplayer.triggerDimensionAdvancements(((CraftWorld) fromWorld).getHandle()); - diff --git a/Spigot-Server-Patches/Fix-this-stupid-bullshit.patch b/Spigot-Server-Patches/Fix-this-stupid-bullshit.patch deleted file mode 100644 index dbed0057de..0000000000 --- a/Spigot-Server-Patches/Fix-this-stupid-bullshit.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: DemonWav -Date: Sun, 6 Aug 2017 17:17:53 -0500 -Subject: [PATCH] Fix this stupid bullshit - -Disable the 15 second sleep when the server jar hasn't been rebuilt within a period of time. - -modified in order to prevent merge conflicts when Spigot changes/disables the warning, -and to provide some level of hint without being disruptive. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); - if (buildDate.before(deadline.getTime())) { -- System.err.println("*** Error, this build is outdated ***"); -+ // Paper start - This is some stupid bullshit -+ System.err.println("*** Warning, you've not updated in a while! ***"); - System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper -- System.err.println("*** Server will start in 20 seconds ***"); -- Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ //System.err.println("*** Server will start in 20 seconds ***"); -+ //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); -+ // Paper End - } - } - diff --git a/Spigot-Server-Patches/Fix-unregistering-entities-from-unloading-chunks.patch b/Spigot-Server-Patches/Fix-unregistering-entities-from-unloading-chunks.patch deleted file mode 100644 index b726036f8d..0000000000 --- a/Spigot-Server-Patches/Fix-unregistering-entities-from-unloading-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:01:45 -0400 -Subject: [PATCH] Fix unregistering entities from unloading chunks - -CraftBukkit caused a regression here by making unloading chunks not -have a ticket added and returning unloaded future. - -This caused entities who were killed in same tick their chunk is unloading -to not be able to be removed from the chunk. - -This then results in dead entities lingering in the Chunk. - -Combine that with a buggy detail of the previous implementation of -the Dupe UUID patch, then this was the likely source of the "Ghost entities" - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - private void removeEntityFromChunk(Entity entity) { -- IChunkAccess ichunkaccess = chunkProvider.getChunkUnchecked(entity.chunkX, entity.chunkZ); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). -+ Chunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways - -- if (ichunkaccess instanceof Chunk) { -+ if (ichunkaccess != null) { // Paper - ((Chunk) ichunkaccess).b(entity); - } - diff --git a/Spigot-Server-Patches/Fix-villager-boat-exploit.patch b/Spigot-Server-Patches/Fix-villager-boat-exploit.patch deleted file mode 100644 index 92d97361ed..0000000000 --- a/Spigot-Server-Patches/Fix-villager-boat-exploit.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Mon, 11 Jan 2021 12:43:51 -0800 -Subject: [PATCH] Fix villager boat exploit - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import net.minecraft.util.MathHelper; - import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.npc.EntityVillagerAbstract; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - for (Iterator iterator = entity.getAllPassengers().iterator(); iterator.hasNext(); entity1.dead = true) { - entity1 = (Entity) iterator.next(); -+ // Paper start -+ if (entity1 instanceof EntityVillagerAbstract) { -+ final EntityVillagerAbstract villager = (EntityVillagerAbstract) entity1; -+ final EntityHuman human = villager.getTrader(); -+ if (human != null) { -+ villager.setTradingPlayer(null); -+ } -+ } -+ // Paper end - worldserver.removeEntity(entity1); - } - diff --git a/Spigot-Server-Patches/Fix-villager-trading-demand-MC-163962.patch b/Spigot-Server-Patches/Fix-villager-trading-demand-MC-163962.patch deleted file mode 100644 index f0a985f29b..0000000000 --- a/Spigot-Server-Patches/Fix-villager-trading-demand-MC-163962.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Fri, 5 Jun 2020 20:02:04 -0500 -Subject: [PATCH] Fix villager trading demand - MC-163962 - -Prevent demand from going negative and tending to negative infinity - -diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -+++ b/src/main/java/net/minecraft/world/item/trading/MerchantRecipe.java -@@ -0,0 +0,0 @@ public class MerchantRecipe { - } - - public void e() { -- this.demand = this.demand + this.uses - (this.maxUses - this.uses); -+ this.demand = Math.max(0, this.demand + this.uses - (this.maxUses - this.uses)); // Paper - } - - public ItemStack f() { diff --git a/Spigot-Server-Patches/Fixed-TileEntityBell-memory-leak.patch b/Spigot-Server-Patches/Fixed-TileEntityBell-memory-leak.patch deleted file mode 100644 index c51b56feb6..0000000000 --- a/Spigot-Server-Patches/Fixed-TileEntityBell-memory-leak.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: giacomo <32515303+giacomozama@users.noreply.github.com> -Date: Sat, 10 Oct 2020 12:15:33 +0200 -Subject: [PATCH] Fixed TileEntityBell memory leak - -TileEntityBell has a list of entities (entitiesAtRing) that was not being cleared at the right time, causing leaks whenever a bell would be rung near a crowd of entities. - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBell.java -@@ -0,0 +0,0 @@ public class TileEntityBell extends TileEntity implements ITickable { - public int a; - public boolean b; - public EnumDirection c; -- private List h; -- private boolean i; -+ private List h; private List getEntitiesAtRing() { return this.h; } // Paper - OBFHELPER -+ private boolean i; private boolean getShouldReveal() { return this.i; } // Paper - OBFHELPER - private int j; - - public TileEntityBell() { -@@ -0,0 +0,0 @@ public class TileEntityBell extends TileEntity implements ITickable { - - if (this.a >= 50) { - this.b = false; -+ // Paper start -+ if (!this.getShouldReveal()) { -+ this.getEntitiesAtRing().clear(); -+ } -+ // Paper end - this.a = 0; - } - -@@ -0,0 +0,0 @@ public class TileEntityBell extends TileEntity implements ITickable { - } else { - this.a(this.world); - this.b(this.world); -+ this.getEntitiesAtRing().clear(); // Paper - this.i = false; - } - } -@@ -0,0 +0,0 @@ public class TileEntityBell extends TileEntity implements ITickable { - EntityLiving entityliving = (EntityLiving) iterator.next(); - - if (entityliving.isAlive() && !entityliving.dead && blockposition.a((IPosition) entityliving.getPositionVector(), 32.0D)) { -- entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, (Object) this.world.getTime()); -+ entityliving.getBehaviorController().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.world.getTime()); // Paper - decompile fix - } - } - } - -+ this.getEntitiesAtRing().removeIf(e -> !e.isAlive()); // Paper - } - - private boolean h() { diff --git a/Spigot-Server-Patches/Flag-to-disable-the-channel-limit.patch b/Spigot-Server-Patches/Flag-to-disable-the-channel-limit.patch deleted file mode 100644 index 32a02c51e3..0000000000 --- a/Spigot-Server-Patches/Flag-to-disable-the-channel-limit.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 31 Mar 2018 17:04:26 +0100 -Subject: [PATCH] Flag to disable the channel limit - -In some enviroments, the channel limit set by spigot can cause issues, -e.g. servers which allow and support the usage of mod packs. - -provide an optional flag to disable this check, at your own risk. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - // Paper start - private org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; - private String resourcePackHash; -+ private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit - // Paper end - - public CraftPlayer(CraftServer server, EntityPlayer entity) { -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void addChannel(String channel) { -- Preconditions.checkState(channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); -+ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); // Paper - flag to disable channel limit - channel = StandardMessenger.validateAndCorrectChannel(channel); - if (channels.add(channel)) { - server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/Spigot-Server-Patches/Further-improve-server-tick-loop.patch b/Spigot-Server-Patches/Further-improve-server-tick-loop.patch deleted file mode 100644 index 3d8fe2a992..0000000000 --- a/Spigot-Server-Patches/Further-improve-server-tick-loop.patch +++ /dev/null @@ -1,208 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:09:29 -0600 -Subject: [PATCH] Further improve server tick loop - -Improves how the catchup buffer is handled, allowing it to roll both ways -increasing the effeciency of the thread sleep so it only will sleep once. - -Also increases the buffer of the catchup to ensure server stays at 20 TPS unless extreme conditions - -Previous implementation did not calculate TPS correctly. -Switch to a realistic rolling average and factor in std deviation as an extra reporting variable - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; - public CommandDispatcher vanillaCommandDispatcher; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 5000L && this.nextTick - this.lastOverloadTime >= 30000L) { // CraftBukkit - long j = i / 50L; - - if (server.getWarnOnOverload()) // CraftBukkit -- MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); -+ MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", i, j); - this.nextTick += j * 50L; - this.lastOverloadTime = this.nextTick; - } - -- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) -+ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) - { -- double currentTps = 1E3 / ( curTime - tickSection ) * SAMPLE_INTERVAL; -- recentTps[0] = calcTps( recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) -- recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) -- recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) -+ final long diff = curTime - tickSection; -+ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); -+ tps1.add(currentTps, diff); -+ tps5.add(currentTps, diff); -+ tps15.add(currentTps, diff); -+ // Backwards compat with bad plugins -+ recentTps[0] = tps1.getAverage(); -+ recentTps[1] = tps5.getAverage(); -+ recentTps[2] = tps15.getAverage(); -+ // Paper end - tickSection = curTime; - } - // Spigot end - -- MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit -+ //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time -+ lastTick = curTime; - this.nextTick += 50L; - GameProfilerTick gameprofilertick = GameProfilerTick.a("Server"); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return CraftMagicNumbers.INSTANCE; - } - -+ // Paper - Add getTPS API - Further improve tick loop -+ @Override -+ public double[] getTPS() { -+ return new double[] { -+ net.minecraft.server.MinecraftServer.getServer().tps1.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps5.getAverage(), -+ net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() -+ }; -+ } -+ // Paper end -+ - // Spigot start - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { -diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java -+++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java -@@ -0,0 +0,0 @@ public class TicksPerSecondCommand extends Command - return true; - } - -- StringBuilder sb = new StringBuilder( ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " ); -- for ( double tps : MinecraftServer.getServer().recentTps ) -- { -- sb.append( format( tps ) ); -- sb.append( ", " ); -+ // Paper start - Further improve tick handling -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int i = 0; i < tps.length; i++) { -+ tpsAvg[i] = format( tps[i] ); -+ } -+ sender.sendMessage(ChatColor.GOLD + "TPS from last 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); -+ if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { -+ sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ if (!hasShownMemoryWarning) { -+ sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); -+ hasShownMemoryWarning = true; -+ } - } -- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); -- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " -- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); -+ // Paper end - - return true; - } - -- private String format(double tps) -+ private boolean hasShownMemoryWarning; // Paper -+ private static String format(double tps) // Paper - Made static - { - return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString() -- + ( ( tps > 20.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise - } - } diff --git a/Spigot-Server-Patches/Generator-Settings.patch b/Spigot-Server-Patches/Generator-Settings.patch deleted file mode 100644 index d369838eec..0000000000 --- a/Spigot-Server-Patches/Generator-Settings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 02:17:54 -0600 -Subject: [PATCH] Generator Settings - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void perPlayerMobSpawns() { - perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); - } -+ -+ public boolean generateFlatBedrock; -+ private void generatorSettings() { -+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; - - public interface IChunkAccess extends IBlockAccess, IStructureAccess { - -+ // Paper start -+ default boolean generateFlatBedrock() { -+ if (this instanceof ProtoChunk) { -+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; -+ } else if (this instanceof Chunk) { -+ return ((Chunk)this).world.paperConfig.generateFlatBedrock; -+ } else { -+ return false; -+ } -+ } -+ // Paper end -+ - IBlockData getType(final int x, final int y, final int z); // Paper - @Nullable - IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -0,0 +0,0 @@ public class ProtoChunk implements IChunkAccess { - private long s; - private final Map t; - private volatile boolean u; -- private final World world; // Paper - Anti-Xray - Add world -+ final World world; // Paper - Anti-Xray - Add world // Paper - private -> default - - // Paper start - Anti-Xray - Add world - @Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -@@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - int i = ichunkaccess.getPos().d(); - int j = ichunkaccess.getPos().e(); - GeneratorSettingBase generatorsettingbase = (GeneratorSettingBase) this.h.get(); -- int k = generatorsettingbase.f(); -- int l = this.x - 1 - generatorsettingbase.e(); -+ int k = generatorsettingbase.f(); final int floorHeight = k; // Paper -+ int l = this.x - 1 - generatorsettingbase.e(); final int roofHeight = l; // Paper - boolean flag = true; - boolean flag1 = l + 4 >= 0 && l < this.x; - boolean flag2 = k + 4 >= 0 && k < this.x; -@@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - - if (flag1) { - for (i1 = 0; i1 < 5; ++i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (ichunkaccess.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof - ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); - } - } -@@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - - if (flag2) { - for (i1 = 4; i1 >= 0; --i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (ichunkaccess.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor - ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); - } - } diff --git a/Spigot-Server-Patches/Guard-against-serializing-mismatching-chunk-coordina.patch b/Spigot-Server-Patches/Guard-against-serializing-mismatching-chunk-coordina.patch deleted file mode 100644 index 9e984b559a..0000000000 --- a/Spigot-Server-Patches/Guard-against-serializing-mismatching-chunk-coordina.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 27 Dec 2019 09:42:26 -0800 -Subject: [PATCH] Guard against serializing mismatching chunk coordinate - -Should help if something dumb happens - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - - private static final Logger LOGGER = LogManager.getLogger(); - -+ // Paper start - guard against serializing mismatching coordinates -+ // TODO Note: This needs to be re-checked each update -+ public static ChunkCoordIntPair getChunkCoordinate(NBTTagCompound chunkData) { -+ NBTTagCompound levelData = chunkData.getCompound("Level"); -+ return new ChunkCoordIntPair(levelData.getInt("xPos"), levelData.getInt("zPos")); -+ } -+ // Paper end - // Paper start - public static final class InProgressChunkHolder { - -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); -- NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); -- ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); -+ NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate -+ ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate - - if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { - ChunkRegionLoader.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IChunkLoader.java -@@ -0,0 +0,0 @@ import net.minecraft.SharedConstants; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.World; -@@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable { - - public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER - public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) -+ // Paper start -+ if (!chunkcoordintpair.equals(ChunkRegionLoader.getChunkCoordinate(nbttagcompound))) { -+ String world = (this instanceof PlayerChunkMap) ? ((PlayerChunkMap)this).world.getWorld().getName() : null; -+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() -+ + " but compound says coordinate is " + ChunkRegionLoader.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); -+ } -+ // Paper end - this.regionFileCache.write(chunkcoordintpair, nbttagcompound); - if (this.c != null) { - synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/Spigot-Server-Patches/Guardian-beam-workaround.patch b/Spigot-Server-Patches/Guardian-beam-workaround.patch deleted file mode 100644 index de78d7f8b5..0000000000 --- a/Spigot-Server-Patches/Guardian-beam-workaround.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Gabscap -Date: Sat, 19 Mar 2016 22:25:11 +0100 -Subject: [PATCH] Guardian beam workaround - -This patch is a workaround for MC-165595 - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutUpdateTime.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet; - - public class PacketPlayOutUpdateTime implements Packet { - -- private long a; -+ private long a; private final void setWorldAge(final long age) { this.a = age; } private final long getWorldAge() { return this.a; } // Paper - OBFHELPER - private long b; - - public PacketPlayOutUpdateTime() {} -@@ -0,0 +0,0 @@ public class PacketPlayOutUpdateTime implements Packet { - } - } - -+ // Paper start -+ this.setWorldAge(this.getWorldAge() % 192000); -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/Handle-Item-Meta-Inconsistencies.patch b/Spigot-Server-Patches/Handle-Item-Meta-Inconsistencies.patch deleted file mode 100644 index 1d2011c4f3..0000000000 --- a/Spigot-Server-Patches/Handle-Item-Meta-Inconsistencies.patch +++ /dev/null @@ -1,331 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 May 2015 23:00:19 -0400 -Subject: [PATCH] Handle Item Meta Inconsistencies - -First, Enchantment order would blow away seeing 2 items as the same, -however the Client forces enchantment list in a certain order, as well -as does the /enchant command. Anvils can insert it into forced order, -causing 2 same items to be considered different. - -This change makes unhandled NBT Tags and Enchantments use a sorted tree map, -so they will always be in a consistent order. - -Additionally, the old enchantment API was never updated when ItemMeta -was added, resulting in 2 different ways to modify an items enchantments. - -For consistency, the old API methods now forward to use the -ItemMeta API equivalents, and should deprecate the old API's. - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; - import java.text.DecimalFormat; - import java.text.DecimalFormatSymbols; -+import java.util.Collections; -+import java.util.Comparator; - import java.util.Locale; - import java.util.Objects; - import java.util.Optional; -@@ -0,0 +0,0 @@ public final class ItemStack { - private ShapeDetectorBlock n; - private boolean o; - -+ // Paper start -+ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); -+ private void processEnchantOrder(NBTTagCompound tag) { -+ if (tag == null || !tag.hasKeyOfType("Enchantments", 9)) { -+ return; -+ } -+ NBTTagList list = tag.getList("Enchantments", 10); -+ if (list.size() < 2) { -+ return; -+ } -+ try { -+ //noinspection unchecked -+ list.sort((Comparator) enchantSorter); // Paper -+ } catch (Exception ignored) {} -+ } -+ // Paper end -+ - public ItemStack(IMaterial imaterial) { - this(imaterial, 1); - } -@@ -0,0 +0,0 @@ public final class ItemStack { - if (nbttagcompound.hasKeyOfType("tag", 10)) { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); -+ processEnchantOrder(this.tag); // Paper - this.getItem().b(this.tag); - // CraftBukkit end - } -@@ -0,0 +0,0 @@ public final class ItemStack { - // Paper end - public void setTag(@Nullable NBTTagCompound nbttagcompound) { - this.tag = nbttagcompound; -+ processEnchantOrder(this.tag); // Paper - if (this.getItem().usesDurability()) { - this.setDamage(this.getDamage()); - } -@@ -0,0 +0,0 @@ public final class ItemStack { - nbttagcompound.setString("id", String.valueOf(IRegistry.ENCHANTMENT.getKey(enchantment))); - nbttagcompound.setShort("lvl", (short) ((byte) i)); - nbttaglist.add(nbttagcompound); -+ processEnchantOrder(nbttagcompound); // Paper - } - - public boolean hasEnchantments() { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack { - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); - -- if (!makeTag(handle)) { -- return; -- } -- NBTTagList list = getEnchantmentList(handle); -- if (list == null) { -- list = new NBTTagList(); -- handle.getTag().set(ENCHANTMENTS.NBT, list); -- } -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- NBTTagCompound tag = (NBTTagCompound) list.get(i); -- String id = tag.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); -- return; -- } -- } -- NBTTagCompound tag = new NBTTagCompound(); -- tag.setString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); -- list.add(tag); -+ // Paper start - Replace whole method -+ final ItemMeta itemMeta = getItemMeta(); -+ itemMeta.addEnchant(ench, level, true); -+ setItemMeta(itemMeta); -+ // Paper end - } - - static boolean makeTag(net.minecraft.world.item.ItemStack item) { -@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack { - - @Override - public boolean containsEnchantment(Enchantment ench) { -- return getEnchantmentLevel(ench) > 0; -+ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta - } - - @Override - public int getEnchantmentLevel(Enchantment ench) { -- Validate.notNull(ench, "Cannot find null enchantment"); -- if (handle == null) { -- return 0; -- } -- return EnchantmentManager.getEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); -+ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta - } - - @Override - public int removeEnchantment(Enchantment ench) { - Validate.notNull(ench, "Cannot remove null enchantment"); - -- NBTTagList list = getEnchantmentList(handle), listCopy; -- if (list == null) { -- return 0; -- } -- int index = Integer.MIN_VALUE; -- int level = Integer.MIN_VALUE; -- int size = list.size(); -- -- for (int i = 0; i < size; i++) { -- NBTTagCompound enchantment = (NBTTagCompound) list.get(i); -- String id = enchantment.getString(ENCHANTMENTS_ID.NBT); -- if (id.equals(ench.getKey().toString())) { -- index = i; -- level = 0xffff & enchantment.getShort(ENCHANTMENTS_LVL.NBT); -- break; -- } -- } -- -- if (index == Integer.MIN_VALUE) { -- return 0; -- } -- if (size == 1) { -- handle.getTag().remove(ENCHANTMENTS.NBT); -- if (handle.getTag().isEmpty()) { -- handle.setTag(null); -- } -- return level; -- } -- -- // This is workaround for not having an index removal -- listCopy = new NBTTagList(); -- for (int i = 0; i < size; i++) { -- if (i != index) { -- listCopy.add(list.get(i)); -- } -+ // Paper start - replace entire method -+ final ItemMeta itemMeta = getItemMeta(); -+ int level = itemMeta.getEnchantLevel(ench); -+ if (level > 0) { -+ itemMeta.removeEnchant(ench); -+ setItemMeta(itemMeta); - } -- handle.getTag().set(ENCHANTMENTS.NBT, listCopy); -+ // Paper end - - return level; - } - - @Override - public Map getEnchantments() { -- return getEnchantments(handle); -+ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta - } - - static Map getEnchantments(net.minecraft.world.item.ItemStack item) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -0,0 +0,0 @@ import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.ImmutableMultimap; - import com.google.common.collect.LinkedHashMultimap; -+import com.google.common.collect.ImmutableSortedMap; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Multimap; - import com.google.common.collect.SetMultimap; -@@ -0,0 +0,0 @@ import java.lang.reflect.InvocationTargetException; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Collection; -+import java.util.Comparator; // Paper - import java.util.EnumSet; - import java.util.HashMap; - import java.util.Iterator; -@@ -0,0 +0,0 @@ import java.util.Map; - import java.util.NoSuchElementException; - import java.util.Objects; - import java.util.Set; -+import java.util.TreeMap; // Paper - import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private List lore; // null and empty are two different states internally - private Integer customModelData; - private NBTTagCompound blockData; -- private Map enchantments; -+ private EnchantmentMap enchantments; // Paper - private Multimap attributeModifiers; - private int repairCost; - private int hideFlag; -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - - private NBTTagCompound internalTag; -- private final Map unhandledTags = new HashMap(); -+ private final Map unhandledTags = new TreeMap<>(); // Paper - private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - - private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.blockData = meta.blockData; - - if (meta.enchantments != null) { // Spigot -- this.enchantments = new LinkedHashMap(meta.enchantments); -+ this.enchantments = new EnchantmentMap(meta.enchantments); // Paper - } - - if (meta.hasAttributeModifiers()) { -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { // Paper - if (!tag.hasKey(key.NBT)) { - return null; - } - - NBTTagList ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - - for (int i = 0; i < ench.size(); i++) { - String id = ((NBTTagCompound) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -- static Map buildEnchantments(Map map, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper - Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); - if (ench == null) { - return null; - } - -- Map enchantments = new LinkedHashMap(ench.size()); -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper - for (Map.Entry entry : ench.entrySet()) { - // Doctor older enchants - String enchantKey = entry.getKey().toString(); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Override - public Map getEnchants() { -- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); -+ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper - } - - @Override - public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { - Validate.notNull(ench, "Enchantment cannot be null"); - if (enchantments == null) { -- enchantments = new LinkedHashMap(4); -+ enchantments = new EnchantmentMap(); // Paper - } - - if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.customModelData = this.customModelData; - clone.blockData = this.blockData; - if (this.enchantments != null) { -- clone.enchantments = new LinkedHashMap(this.enchantments); -+ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper - } - if (this.hasAttributeModifiers()) { - clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return HANDLED_TAGS; - } - } -+ -+ // Paper start -+ private static class EnchantmentMap extends TreeMap { -+ private EnchantmentMap(Map enchantments) { -+ this(); -+ putAll(enchantments); -+ } -+ -+ private EnchantmentMap() { -+ super(Comparator.comparing(o -> o.getKey().toString())); -+ } -+ -+ public EnchantmentMap clone() { -+ return (EnchantmentMap) super.clone(); -+ } -+ } -+ // Paper end -+ - } diff --git a/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch b/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch deleted file mode 100644 index 78bc5c9473..0000000000 --- a/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Nov 2018 21:18:06 -0500 -Subject: [PATCH] Handle Large Packets disconnecting client - -If a players inventory is too big to send in a single packet, -split the inventory set into multiple packets instead. - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ import io.netty.channel.epoll.EpollEventLoopGroup; - import io.netty.channel.local.LocalChannel; - import io.netty.channel.local.LocalServerChannel; - import io.netty.channel.nio.NioEventLoopGroup; -+import io.netty.handler.codec.EncoderException; // Paper - import io.netty.handler.timeout.TimeoutException; - import io.netty.util.AttributeKey; - import io.netty.util.concurrent.Future; -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { -+ // Paper start -+ if (throwable instanceof EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { -+ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { -+ return; -+ } else { -+ throwable = throwable.getCause(); -+ } -+ } -+ // Paper end - if (throwable instanceof SkipEncodeException) { - NetworkManager.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); - } else { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -0,0 +0,0 @@ public class PacketEncoder extends MessageToByteEncoder> { - throw throwable; - } - } -+ -+ // Paper start -+ int packetLength = bytebuf.readableBytes(); -+ if (packetLength > MAX_PACKET_SIZE) { -+ throw new PacketTooLargeException(packet, packetLength); -+ } -+ // Paper end - } - } - } -+ -+ // Paper start -+ private static int MAX_PACKET_SIZE = 2097152; -+ -+ public static class PacketTooLargeException extends RuntimeException { -+ private final Packet packet; -+ -+ PacketTooLargeException(Packet packet, int packetLength) { -+ super("PacketTooLarge - " + packet.getClass().getSimpleName() + " is " + packetLength + ". Max is " + MAX_PACKET_SIZE); -+ this.packet = packet; -+ } -+ -+ public Packet getPacket() { -+ return packet; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -0,0 +0,0 @@ public interface Packet { - - void a(T t0); - -+ // Paper start -+ default boolean packetTooLarge(NetworkManager manager) { -+ return false; -+ } -+ // Paper end -+ - default boolean a() { - return false; - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - - int i = packetdataserializer.i(); - -- if (i > 2097152) { -+ if (i > 2097152) { // Paper - if this changes, update PacketEncoder - throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); - } else { - this.f = new byte[i]; -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutWindowItems.java -@@ -0,0 +0,0 @@ import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; - import net.minecraft.world.item.ItemStack; -@@ -0,0 +0,0 @@ public class PacketPlayOutWindowItems implements Packet { - private int a; - private List b; - -+ //Paper start -+ @Override -+ public boolean packetTooLarge(NetworkManager manager) { -+ for (int i = 0 ; i < this.b.size() ; i++) { -+ manager.sendPacket(new PacketPlayOutSetSlot(this.a, i, this.b.get(i))); -+ } -+ return true; -+ } -+ // Paper end - public PacketPlayOutWindowItems() {} - - public PacketPlayOutWindowItems(int i, NonNullList nonnulllist) { diff --git a/Spigot-Server-Patches/Handle-Oversized-Tile-Entities-in-chunks.patch b/Spigot-Server-Patches/Handle-Oversized-Tile-Entities-in-chunks.patch deleted file mode 100644 index 857f5f2541..0000000000 --- a/Spigot-Server-Patches/Handle-Oversized-Tile-Entities-in-chunks.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 05:00:57 -0400 -Subject: [PATCH] Handle Oversized Tile Entities in chunks - -Splits out Extra Packets if too many TE's are encountered to prevent -creating too large of a packet to sed. - -Co authored by Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - private boolean h; - - public PacketPlayOutMapChunk() {} -+ // Paper start -+ private final java.util.List extraPackets = new java.util.ArrayList<>(); -+ private static final int TE_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750); - -+ @Override -+ public java.util.List getExtraPackets() { -+ return extraPackets; -+ } -+ // Paper end - public PacketPlayOutMapChunk(Chunk chunk, int i) { - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); - this.g = Lists.newArrayList(); - iterator = chunk.getTileEntities().entrySet().iterator(); -+ int totalTileEntities = 0; // Paper - - while (iterator.hasNext()) { - entry = (Entry) iterator.next(); -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - int j = blockposition.getY() >> 4; - - if (this.f() || (i & 1 << j) != 0) { -+ // Paper start - improve oversized chunk data packet handling -+ if (++totalTileEntities > TE_LIMIT) { -+ PacketPlayOutTileEntityData updatePacket = tileentity.getUpdatePacket(); -+ if (updatePacket != null) { -+ this.extraPackets.add(updatePacket); -+ continue; -+ } -+ } -+ // Paper end - NBTTagCompound nbttagcompound = tileentity.b(); - if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper - diff --git a/Spigot-Server-Patches/Handle-plugin-prefixes-using-Log4J-configuration.patch b/Spigot-Server-Patches/Handle-plugin-prefixes-using-Log4J-configuration.patch deleted file mode 100644 index 67a82a57ab..0000000000 --- a/Spigot-Server-Patches/Handle-plugin-prefixes-using-Log4J-configuration.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Thu, 21 Sep 2017 16:14:55 +0200 -Subject: [PATCH] Handle plugin prefixes using Log4J configuration - -Display logger name in the console for all loggers except the -root logger, Bukkit's logger ("Minecraft") and Minecraft loggers. -Since plugins now use the plugin name as logger name this will -restore the plugin prefixes without having to prepend them manually -to the log messages. - -Logger prefixes are shown by default for all loggers except for -the root logger, the Minecraft/Mojang loggers and the Bukkit loggers. -This may cause additional prefixes to be disabled for plugins bypassing -the plugin logger. - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - - org.apache.logging.log4j - log4j-core -- runtime -+ compile - - - org.apache.logging.log4j -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -0,0 +0,0 @@ public class SpigotConfig - private static void playerSample() - { - playerSample = getInt( "settings.sample-count", 12 ); -- System.out.println( "Server Ping Player Sample Count: " + playerSample ); -+ Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - - public static int playerShuffle; -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -0,0 +0,0 @@ - - - -- -+ -+ -+ -+ -+ -+ - - -- -+ -+ -+ -+ -+ -+ - - - diff --git a/Spigot-Server-Patches/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/Spigot-Server-Patches/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch deleted file mode 100644 index 804a77eb7c..0000000000 --- a/Spigot-Server-Patches/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alexander -Date: Thu, 6 May 2021 13:01:25 +0100 -Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent - - -diff --git a/src/main/java/net/minecraft/world/item/trading/IMerchant.java b/src/main/java/net/minecraft/world/item/trading/IMerchant.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/trading/IMerchant.java -+++ b/src/main/java/net/minecraft/world/item/trading/IMerchant.java -@@ -0,0 +0,0 @@ public interface IMerchant { - - MerchantRecipeList getOffers(); - -- void a(MerchantRecipe merchantrecipe); -+ void a(MerchantRecipe merchantrecipe); default void handlePurchase(MerchantRecipe merchantRecipe) { a(merchantRecipe); } // Paper - OBFHELPER - - void k(ItemStack itemstack); - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java -@@ -0,0 +0,0 @@ public class CraftMerchantCustom extends CraftMerchant { - - @Override - public void a(MerchantRecipe merchantrecipe) { -+ // Paper start -+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerAbstract#b(MerchantRecipe)} */ -+ if (getTrader() instanceof net.minecraft.server.level.EntityPlayer) { -+ final net.minecraft.server.level.EntityPlayer trader = (net.minecraft.server.level.EntityPlayer) getTrader(); -+ final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent( -+ trader.getBukkitEntity(), -+ merchantrecipe.asBukkit(), -+ false, // reward xp? -+ true); // should increase uses? -+ event.callEvent(); -+ if (event.isCancelled()) { -+ return; -+ } -+ final org.bukkit.inventory.MerchantRecipe eventTrade = event.getTrade(); -+ if (event.willIncreaseTradeUses()) { -+ eventTrade.setUses(eventTrade.getUses() + 1); -+ } -+ if (event.isRewardingExp() && eventTrade.hasExperienceReward()) { -+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerTrader#b(MerchantRecipe)} */ -+ final int xp = 3 + net.minecraft.world.entity.Entity.SHARED_RANDOM.nextInt(4); -+ final World world = trader.getWorld(); -+ world.addEntity(new net.minecraft.world.entity.EntityExperienceOrb( -+ world, trader.locX(), trader.locY() + 0.5d, trader.locZ(), xp, -+ org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null)); -+ } -+ return; -+ } -+ // Paper end -+ - // increase recipe's uses - merchantrecipe.increaseUses(); - } diff --git a/Spigot-Server-Patches/Here-s-Johnny.patch b/Spigot-Server-Patches/Here-s-Johnny.patch deleted file mode 100644 index 715a877bad..0000000000 --- a/Spigot-Server-Patches/Here-s-Johnny.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 12 Oct 2018 01:37:22 -0500 -Subject: [PATCH] Here's Johnny! - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -0,0 +0,0 @@ public class EntityVindicator extends EntityIllagerAbstract { - private static final Predicate b = (enumdifficulty) -> { - return enumdifficulty == EnumDifficulty.NORMAL || enumdifficulty == EnumDifficulty.HARD; - }; -- private boolean bo; -+ private boolean bo; public boolean isJohnny() { return bo; } public void setJohnny(boolean johnny) { bo = johnny; } // Paper - OBFHELPER - - public EntityVindicator(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -@@ -0,0 +0,0 @@ public class CraftVindicator extends CraftIllager implements Vindicator { - public EntityType getType() { - return EntityType.VINDICATOR; - } -+ -+ // Paper start -+ public boolean isJohnny() { -+ return getHandle().isJohnny(); -+ } -+ -+ public void setJohnny(boolean johnny) { -+ getHandle().setJohnny(johnny); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Hide-sync-chunk-writes-behind-flag.patch b/Spigot-Server-Patches/Hide-sync-chunk-writes-behind-flag.patch deleted file mode 100644 index 6c68bfef29..0000000000 --- a/Spigot-Server-Patches/Hide-sync-chunk-writes-behind-flag.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 26 Jun 2020 22:35:08 -0700 -Subject: [PATCH] Hide sync chunk writes behind flag - -Syncing writes on each write call has terrible performance -on harddrives. - --DPaper.enable-sync-chunk-writes=true to enable - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServerProperties.java -@@ -0,0 +0,0 @@ public class DedicatedServerProperties extends PropertyManager { - return MathHelper.clamp(integer, 1, 29999984); - }, 29999984); -- this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true); -+ this.syncChunkWrites = this.getBoolean("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag - this.enableJmxMonitoring = this.getBoolean("enable-jmx-monitoring", false); - this.enableStatus = this.getBoolean("enable-status", true); - this.entityBroadcastRangePercentage = this.a("entity-broadcast-range-percentage", (integer) -> { diff --git a/Spigot-Server-Patches/Honor-EntityAgeable.ageLock.patch b/Spigot-Server-Patches/Honor-EntityAgeable.ageLock.patch deleted file mode 100644 index 3074961968..0000000000 --- a/Spigot-Server-Patches/Honor-EntityAgeable.ageLock.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 23 Sep 2018 20:59:53 -0500 -Subject: [PATCH] Honor EntityAgeable.ageLock - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityAgeable.java b/src/main/java/net/minecraft/world/entity/EntityAgeable.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityAgeable.java -+++ b/src/main/java/net/minecraft/world/entity/EntityAgeable.java -@@ -0,0 +0,0 @@ public abstract class EntityAgeable extends EntityCreature { - } - - public void setAge(int i, boolean flag) { -+ if (ageLocked) return; // Paper - GH-1459 - int j = this.getAge(); - int k = j; - diff --git a/Spigot-Server-Patches/Hook-into-CB-plugin-rewrites.patch b/Spigot-Server-Patches/Hook-into-CB-plugin-rewrites.patch deleted file mode 100644 index f27a178b43..0000000000 --- a/Spigot-Server-Patches/Hook-into-CB-plugin-rewrites.patch +++ /dev/null @@ -1,184 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Wed, 3 Oct 2018 20:09:18 -0400 -Subject: [PATCH] Hook into CB plugin rewrites - -Allows us to do fun stuff like rewrite the OBC util fastutil location to -our own relocation. Also lets us rewrite NMS calls for when we're -debugging in an IDE pre-relocate. - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -@@ -0,0 +0,0 @@ import java.io.FileOutputStream; - import java.io.InputStream; - import java.util.Arrays; - import java.util.Enumeration; -+import java.util.HashMap; - import java.util.HashSet; -+import java.util.Map; - import java.util.Set; - import java.util.jar.JarEntry; - import java.util.jar.JarFile; -@@ -0,0 +0,0 @@ import org.bukkit.plugin.AuthorNagException; - import org.objectweb.asm.ClassReader; - import org.objectweb.asm.ClassVisitor; - import org.objectweb.asm.ClassWriter; -+import org.objectweb.asm.FieldVisitor; -+import org.objectweb.asm.Handle; -+import org.objectweb.asm.Label; - import org.objectweb.asm.MethodVisitor; - import org.objectweb.asm.Opcodes; - import org.objectweb.asm.Type; - -+import javax.annotation.Nonnull; -+ - /** - * This file is imported from Commodore. - * -@@ -0,0 +0,0 @@ public class Commodore - "org/bukkit/inventory/ItemStack (I)V setTypeId" - ) ); - -+ // Paper start - Plugin rewrites -+ private static final Map SEARCH_AND_REMOVE = initReplacementsMap(); -+ private static Map initReplacementsMap() -+ { -+ Map getAndRemove = new HashMap<>(); -+ // Be wary of maven shade's relocations -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/libs/it/unimi/dsi/fastutil/" ), "org/bukkit/".concat( "craftbukkit/libs/" ) ); // Remap fastutil to our location -+ -+ if ( Boolean.getBoolean( "debug.rewriteForIde" ) ) -+ { -+ // unversion incoming calls for pre-relocate debug work -+ final String NMS_REVISION_PACKAGE = "v1_16_R3/"; -+ -+ getAndRemove.put( "net/minecraft/".concat( "server/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ getAndRemove.put( "org/bukkit/".concat( "craftbukkit/" + NMS_REVISION_PACKAGE ), NMS_REVISION_PACKAGE ); -+ } -+ -+ return getAndRemove; -+ } -+ -+ @Nonnull -+ private static String getOriginalOrRewrite(@Nonnull String original) -+ { -+ String rewrite = null; -+ for ( Map.Entry entry : SEARCH_AND_REMOVE.entrySet() ) -+ { -+ if ( original.contains( entry.getKey() ) ) -+ { -+ rewrite = original.replace( entry.getValue(), "" ); -+ } -+ } -+ -+ return rewrite != null ? rewrite : original; -+ } -+ // Paper end -+ - public static void main(String[] args) - { - OptionParser parser = new OptionParser(); -@@ -0,0 +0,0 @@ public class Commodore - - cr.accept( new ClassVisitor( Opcodes.ASM9, cw ) - { -+ // Paper start - Rewrite plugins -+ @Override -+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ if ( signature != null ) { -+ signature = getOriginalOrRewrite( signature ); -+ } -+ -+ return super.visitField( access, name, desc, signature, value) ; -+ } -+ // Paper end -+ - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) - { - return new MethodVisitor( api, super.visitMethod( access, name, desc, signature, exceptions ) ) - { -+ // Paper start - Plugin rewrites -+ @Override -+ public void visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) -+ { -+ // Paper start - Rewrite plugins -+ name = getOriginalOrRewrite( name ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ -+ super.visitInvokeDynamicInsn( name, desc, bootstrapMethodHandle, bootstrapMethodArguments ); -+ } -+ -+ @Override -+ public void visitTypeInsn(int opcode, String type) -+ { -+ type = getOriginalOrRewrite( type ); -+ -+ super.visitTypeInsn( opcode, type ); -+ } -+ -+ @Override -+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { -+ for ( int i = 0; i < local.length; i++ ) -+ { -+ if ( !( local[i] instanceof String ) ) { continue; } -+ -+ local[i] = getOriginalOrRewrite( (String) local[i] ); -+ } -+ -+ for ( int i = 0; i < stack.length; i++ ) -+ { -+ if ( !( stack[i] instanceof String ) ) { continue; } -+ -+ stack[i] = getOriginalOrRewrite( (String) stack[i] ); -+ } -+ -+ super.visitFrame( type, nLocal, local, nStack, stack ); -+ } -+ -+ @Override -+ public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) -+ { -+ descriptor = getOriginalOrRewrite( descriptor ); -+ -+ super.visitLocalVariable( name, descriptor, signature, start, end, index ); -+ } -+ // Paper end - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) - { -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner ); -+ if ( desc != null ) -+ { -+ desc = getOriginalOrRewrite( desc ); -+ } -+ // Paper end -+ - if ( owner.equals( "org/bukkit/block/Biome" ) ) - { - switch ( name ) -@@ -0,0 +0,0 @@ public class Commodore - return; - } - -+ // Paper start - Rewrite plugins -+ owner = getOriginalOrRewrite( owner) ; -+ if (desc != null) -+ { -+ desc = getOriginalOrRewrite(desc); -+ } -+ // Paper end -+ - if ( modern ) - { - if ( owner.equals( "org/bukkit/Material" ) ) diff --git a/Spigot-Server-Patches/Ignore-Dead-Entities-in-entityList-iteration.patch b/Spigot-Server-Patches/Ignore-Dead-Entities-in-entityList-iteration.patch deleted file mode 100644 index 0dbc75bda4..0000000000 --- a/Spigot-Server-Patches/Ignore-Dead-Entities-in-entityList-iteration.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 28 Jul 2018 12:18:27 -0400 -Subject: [PATCH] Ignore Dead Entities in entityList iteration - -A spigot change delays removal of entities from the entity list. -This causes a change in behavior from Vanilla where getEntities type -methods will return dead entities that they shouldn't otherwise be doing. - -This will ensure that dead entities are skipped from iteration since -they shouldn't of been in the list in the first place. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - Collection entities = world.entitiesById.values(); - entities.forEach(e -> { - MinecraftKey key = e.getMinecraftKey(); -+ if (e.shouldBeRemoved) return; // Paper - - MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); - ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - entity.origin = entity.getBukkitEntity().getLocation(); - } - // Paper end -+ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added - new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid - } - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.removeEntityFromChunk(entity); - this.entitiesById.remove(entity.getId()); - this.unregisterEntity(entity); -+ entity.shouldBeRemoved = true; // Paper - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - protected int numCollisions = 0; // Paper - public void inactiveTick() { } - // Spigot end -+ public boolean shouldBeRemoved; // Paper - - public float getBukkitYaw() { - return this.yaw; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - for (int i1 = 0; i1 < l; ++i1) { - Entity entity1 = (Entity) list1.get(i1); -+ if (entity1.shouldBeRemoved) continue; // Paper - - if (entity1.getBoundingBox().c(axisalignedbb) && entity1 != entity) { - if (predicate == null || predicate.test(entity1)) { -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - while (iterator.hasNext()) { - T entity = (T) iterator.next(); // CraftBukkit - decompile error -+ if (entity.shouldBeRemoved) continue; // Paper - - if ((entitytypes == null || entity.getEntityType() == entitytypes) && entity.getBoundingBox().c(axisalignedbb) && predicate.test(entity)) { - list.add(entity); -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - while (iterator.hasNext()) { - T t0 = (T) iterator.next(); // CraftBukkit - decompile error -+ if (t0.shouldBeRemoved) continue; // Paper - - if (oclass.isInstance(t0) && t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) { // Spigot - instance check - list.add(t0); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - for (Object o : world.entitiesById.values()) { - if (o instanceof net.minecraft.world.entity.Entity) { - net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o; -+ if (mcEnt.shouldBeRemoved) continue; // Paper - Entity bukkitEntity = mcEnt.getBukkitEntity(); - - // Assuming that bukkitEntity isn't null -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - for (Object entity: world.entitiesById.values()) { - if (entity instanceof net.minecraft.world.entity.Entity) { -+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper - Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity(); - - if (bukkitEntity == null) { diff --git a/Spigot-Server-Patches/Implement-API-to-expose-exact-interaction-point.patch b/Spigot-Server-Patches/Implement-API-to-expose-exact-interaction-point.patch deleted file mode 100644 index 3b18238515..0000000000 --- a/Spigot-Server-Patches/Implement-API-to-expose-exact-interaction-point.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Mon, 4 Jan 2021 16:40:27 +1000 -Subject: [PATCH] Implement API to expose exact interaction point - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -+++ b/src/main/java/net/minecraft/server/level/PlayerInteractManager.java -@@ -0,0 +0,0 @@ public class PlayerInteractManager { - cancelledBlock = true; - } - -- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand); -+ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(entityplayer, Action.RIGHT_CLICK_BLOCK, blockposition, movingobjectpositionblock.getDirection(), itemstack, cancelledBlock, enumhand, movingobjectpositionblock.getPos()); // Paper - firedInteract = true; - interactResult = event.useItemInHand() == Event.Result.DENY; - interactPosition = blockposition.immutableCopy(); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParameters; - import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.MovingObjectPositionEntity; -+import net.minecraft.world.phys.Vec3D; - import org.bukkit.Bukkit; -+import org.bukkit.Location; // Paper - import org.bukkit.Material; - import org.bukkit.NamespacedKey; - import org.bukkit.Server; -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand); - } - -+ // Paper start - Add interactionPoint - public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand) { -+ return callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, hand, null); -+ } -+ -+ public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, BlockPosition position, EnumDirection direction, ItemStack itemstack, boolean cancelledBlock, EnumHand hand, Vec3D hitVec) { -+ // Paper end - Player player = (who == null) ? null : (Player) who.getBukkitEntity(); - CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); - -@@ -0,0 +0,0 @@ public class CraftEventFactory { - itemInHand = null; - } - -- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); -+ // Paper start -+ Location interactionPoint = hitVec == null ? null : new Location(craftWorld, hitVec.x, hitVec.y, hitVec.z); -+ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND), interactionPoint); -+ // Paper end - if (cancelledBlock) { - event.setUseInteractedBlock(Event.Result.DENY); - } diff --git a/Spigot-Server-Patches/Implement-API-to-get-Material-from-Boats-and-Minecar.patch b/Spigot-Server-Patches/Implement-API-to-get-Material-from-Boats-and-Minecar.patch deleted file mode 100644 index ac3f58e31b..0000000000 --- a/Spigot-Server-Patches/Implement-API-to-get-Material-from-Boats-and-Minecar.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Thu, 31 Dec 2020 12:48:19 +1000 -Subject: [PATCH] Implement API to get Material from Boats and Minecarts - - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - - } - -+ public final Item getBoatItem() { return this.g(); } // Paper - OBFHELPER - public Item g() { - switch (this.getType()) { - case OAK: -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.world.entity.vehicle.EntityBoat; -+import org.bukkit.Material; // Paper - import org.bukkit.TreeSpecies; - import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; // Paper - import org.bukkit.entity.Boat; - import org.bukkit.entity.EntityType; - -@@ -0,0 +0,0 @@ public class CraftBoat extends CraftVehicle implements Boat { - getHandle().landBoats = workOnLand; - } - -+ // Paper start -+ @Override -+ public Material getBoatMaterial() { -+ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); -+ } -+ // Paper end -+ - @Override - public EntityBoat getHandle() { - return (EntityBoat) entity; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; -+import net.minecraft.world.item.Items; // Paper - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -+import org.bukkit.Material; // Paper - import org.bukkit.block.data.BlockData; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.block.data.CraftBlockData; -@@ -0,0 +0,0 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { - getHandle().setDerailedVelocityMod(derailed); - } - -+ // Paper start -+ @Override -+ public Material getMinecartMaterial() { -+ net.minecraft.world.item.Item minecartItem; -+ switch (getHandle().getMinecartType()) { -+ case CHEST: -+ minecartItem = Items.CHEST_MINECART; -+ break; -+ case FURNACE: -+ minecartItem = Items.FURNACE_MINECART; -+ break; -+ case TNT: -+ minecartItem = Items.TNT_MINECART; -+ break; -+ case HOPPER: -+ minecartItem = Items.HOPPER_MINECART; -+ break; -+ case COMMAND_BLOCK: -+ minecartItem = Items.COMMAND_BLOCK_MINECART; -+ break; -+ case RIDEABLE: -+ case SPAWNER: -+ minecartItem = Items.MINECART; -+ break; -+ default: -+ throw new IllegalStateException("Unexpected value: " + getHandle().getMinecartType()); -+ } -+ -+ return CraftMagicNumbers.getMaterial(minecartItem); -+ } -+ // Paper end -+ - @Override - public EntityMinecartAbstract getHandle() { - return (EntityMinecartAbstract) entity; diff --git a/Spigot-Server-Patches/Implement-BlockPreDispenseEvent.patch b/Spigot-Server-Patches/Implement-BlockPreDispenseEvent.patch deleted file mode 100644 index 0479cdd328..0000000000 --- a/Spigot-Server-Patches/Implement-BlockPreDispenseEvent.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Miller -Date: Sun, 17 Jan 2021 13:16:09 +1000 -Subject: [PATCH] Implement BlockPreDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -@@ -0,0 +0,0 @@ public class BlockDispenser extends BlockTileEntity { - IDispenseBehavior idispensebehavior = this.a(itemstack); - - if (idispensebehavior != IDispenseBehavior.NONE) { -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(worldserver, blockposition, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here - eventFired = false; // CraftBukkit - reset event status - tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.MovingObjectPositionEntity; - import net.minecraft.world.phys.Vec3D; -+import io.papermc.paper.event.block.BlockPreDispenseEvent; // Paper - import org.bukkit.Bukkit; - import org.bukkit.Location; // Paper - import org.bukkit.Material; -@@ -0,0 +0,0 @@ public class CraftEventFactory { - BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); - return event.callEvent(); - } -+ -+ public static boolean handleBlockPreDispenseEvent(WorldServer worldserver, BlockPosition blockposition, ItemStack itemStack, int slot) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockPreDispenseEvent event = new BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); -+ return event.callEvent(); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Implement-Brigadier-Mojang-API.patch b/Spigot-Server-Patches/Implement-Brigadier-Mojang-API.patch deleted file mode 100644 index 825a34750a..0000000000 --- a/Spigot-Server-Patches/Implement-Brigadier-Mojang-API.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 18:15:29 -0400 -Subject: [PATCH] Implement Brigadier Mojang API - -Adds AsyncPlayerSendCommandsEvent - - Allows modifying on a per command basis what command data they see. - -Adds CommandRegisteredEvent - - Allows manipulating the CommandNode to add more children/metadata for the client - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -0,0 +0,0 @@ public class CommandDispatcher { - bukkit.add(node.getName()); - } - // Paper start - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - MinecraftServer.getServer().execute(() -> { - runSync(entityplayer, bukkit, rootcommandnode); - }); -@@ -0,0 +0,0 @@ public class CommandDispatcher { - - private void runSync(EntityPlayer entityplayer, Collection bukkit, RootCommandNode rootcommandnode) { - // Paper end - Async command map building -+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent(entityplayer.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - PlayerCommandSendEvent event = new PlayerCommandSendEvent(entityplayer.getBukkitEntity(), new LinkedHashSet<>(bukkit)); - event.getPlayer().getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.Vec3D; - - import com.mojang.brigadier.tree.CommandNode; // CraftBukkit - --public class CommandListenerWrapper implements ICompletionProvider { -+public class CommandListenerWrapper implements ICompletionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper - - public static final SimpleCommandExceptionType a = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.player")); - public static final SimpleCommandExceptionType b = new SimpleCommandExceptionType(new ChatMessage("permissions.requires.entity")); -@@ -0,0 +0,0 @@ public class CommandListenerWrapper implements ICompletionProvider { - return this.g; - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity getBukkitEntity() { -+ return getEntity() != null ? getEntity().getBukkitEntity() : null; -+ } -+ -+ @Override -+ public org.bukkit.World getBukkitWorld() { -+ return getWorld() != null ? getWorld().getWorld() : null; -+ } -+ -+ @Override -+ public org.bukkit.Location getBukkitLocation() { -+ Vec3D pos = getPosition(); -+ org.bukkit.World world = getBukkitWorld(); -+ return world != null && pos != null ? new org.bukkit.Location(world, pos.x, pos.y, pos.z) : null; -+ } -+ // Paper end -+ - @Override - public boolean hasPermission(int i) { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); - - this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); -+ // Paper start -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper -+ // Paper end - }); - }); - } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); - completions.forEach(builder::suggest); -- player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); -+ com.mojang.brigadier.suggestion.Suggestions suggestions = builder.buildFuture().join(); -+ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getPlayer(), suggestions, buffer); -+ suggestEvent.setCancelled(suggestions.isEmpty()); -+ if (!suggestEvent.callEvent()) return; -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestEvent.getSuggestions())); - } - // Paper end - async tab completion - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/BukkitCommandWrapper.java -@@ -0,0 +0,0 @@ import net.minecraft.commands.CommandListenerWrapper; - import org.bukkit.command.Command; - import org.bukkit.craftbukkit.CraftServer; - --public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider { -+public class BukkitCommandWrapper implements com.mojang.brigadier.Command, Predicate, SuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommand { // Paper - - private final CraftServer server; - private final Command command; -@@ -0,0 +0,0 @@ public class BukkitCommandWrapper implements com.mojang.brigadier.Command register(CommandDispatcher dispatcher, String label) { -- return dispatcher.register( -- LiteralArgumentBuilder.literal(label).requires(this).executes(this) -- .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this)) -- ); -+ // Paper start - Expose Brigadier to Paper-MojangAPI -+ com.mojang.brigadier.tree.RootCommandNode root = dispatcher.getRoot(); -+ LiteralCommandNode literal = LiteralArgumentBuilder.literal(label).requires(this).executes(this).build(); -+ com.mojang.brigadier.tree.ArgumentCommandNode defaultArgs = RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()).suggests(this).executes(this).build(); -+ literal.addChild(defaultArgs); -+ com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent event = new com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent<>(label, this, this.command, root, literal, defaultArgs); -+ if (!event.callEvent()) { -+ return null; -+ } -+ literal = event.getLiteral(); -+ root.addChild(literal); -+ return literal; -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/Spigot-Server-Patches/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch deleted file mode 100644 index b7095bae31..0000000000 --- a/Spigot-Server-Patches/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch +++ /dev/null @@ -1,1326 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Apr 2020 03:56:07 -0400 -Subject: [PATCH] Implement Chunk Priority / Urgency System for Chunks - -Mark chunks that are blocking main thread for world generation as urgent - -Implements a general priority system so that chunks that are sorted in -the generator queues can prioritize certain chunks over another. - -Urgent chunks will jump to the front of the line, ensuring that a -sync chunk load on an ungenerated chunk does not lag the server for -a long period of time if the servers generator queues are filled with -lots of chunks already. - -This massively reduces the lag spikes from sync chunk gens. - -Then we further prioritize loading order so nearby chunks have higher -priority than distant chunks, reducing the pressure a high no tick -view distance holds on you. - -Chunks in front of the player have higher priority, to help with -fast traveling players keep up with their movement. - -diff --git a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -+++ b/src/main/java/com/destroystokyo/paper/io/chunk/ChunkTaskManager.java -@@ -0,0 +0,0 @@ public final class ChunkTaskManager { - } - - static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { -- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); -+ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); - } - - static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z, int indent, int maxDepth) { -@@ -0,0 +0,0 @@ public final class ChunkTaskManager { - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Status - " + ((chunk == null) ? "null chunk" : chunk.getChunkStatus().toString())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + PlayerChunk.getChunkStatus(chunkHolder.getTicketLevel())); - PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.getCurrentPriority()); -+ -+ if (!chunkHolder.neighbors.isEmpty()) { -+ if (indent >= maxDepth) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: (Can't show, too deeply nested)"); -+ return; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Neighbors: "); -+ for (PlayerChunk neighbor : chunkHolder.neighbors.keySet()) { -+ ChunkStatus status = neighbor.getChunkHolderStatus(); -+ if (status != null && status.isAtLeastStatus(PlayerChunk.getChunkStatus(neighbor.getTicketLevel()))) { -+ continue; -+ } -+ int nx = neighbor.location.x; -+ int nz = neighbor.location.z; -+ if (seenChunks.contains(neighbor)) { -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + " (CIRCULAR)"); -+ continue; -+ } -+ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + " " + nx + "," + nz + " in " + chunkHolder.getWorld().getWorld().getName() + ":"); -+ dumpChunkInfo(seenChunks, neighbor, nx, nz, indent + 1, maxDepth); -+ } -+ } -+ - } - } - -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ public final class MCUtil { - chunkData.addProperty("x", playerChunk.location.x); - chunkData.addProperty("z", playerChunk.location.z); - chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); -+ chunkData.addProperty("priority", playerChunk.getCurrentPriority()); - chunkData.addProperty("state", PlayerChunk.getChunkState(playerChunk.getTicketLevel()).toString()); - chunkData.addProperty("queued-for-unload", chunkMap.unloadQueue.contains(playerChunk.location.pair())); - chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -0,0 +0,0 @@ import java.util.Set; - import java.util.concurrent.CompletableFuture; - import java.util.concurrent.Executor; - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ArraySetSorted; - import net.minecraft.util.thread.Mailbox; - import net.minecraft.world.level.ChunkCoordIntPair; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkStatus; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import org.spigotmc.AsyncCatcher; // Paper - - public abstract class ChunkMapDistance { - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - private final ChunkTaskQueueSorter i; - private final Mailbox> j; - private final Mailbox k; -- private final LongSet l = new LongOpenHashSet(); -+ private final LongSet l = new LongOpenHashSet(); public final LongSet getOnPlayerTicketAddQueue() { return l; } // Paper - OBFHELPER - private final Executor m; - private long currentTick; - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - } - - private static int getLowestTicketLevel(ArraySetSorted> arraysetsorted) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper - return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.b()).b() : PlayerChunkMap.GOLDEN_TICKET + 1; - } - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - - public boolean a(PlayerChunkMap playerchunkmap) { - //this.f.a(); // Paper - no longer used -+ AsyncCatcher.catchOp("DistanceManagerTick"); // Paper - this.g.a(); - int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - - // Paper start - if (!this.pendingChunkUpdates.isEmpty()) { -+ this.pollingPendingChunkUpdates = true; try { - while(!this.pendingChunkUpdates.isEmpty()) { - PlayerChunk remove = this.pendingChunkUpdates.remove(); - remove.isUpdateQueued = false; - remove.a(playerchunkmap); - } -+ } finally { this.pollingPendingChunkUpdates = false; } - // Paper end - return true; - } else { -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - return flag; - } - } -+ boolean pollingPendingChunkUpdates = false; // Paper - - private boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper - ArraySetSorted> arraysetsorted = this.e(i); - int j = getLowestTicketLevel(arraysetsorted); - Ticket ticket1 = (Ticket) arraysetsorted.a(ticket); // CraftBukkit - decompile error -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - } - - private boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean -+ AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper - ArraySetSorted> arraysetsorted = this.e(i); -+ int oldLevel = getLowestTicketLevel(arraysetsorted); // Paper - - boolean removed = false; // CraftBukkit - if (arraysetsorted.remove(ticket)) { -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - this.tickets.remove(i); - } - -- this.ticketLevelTracker.update(i, getLowestTicketLevel(arraysetsorted), false); -+ int newLevel = getLowestTicketLevel(arraysetsorted); // Paper -+ if (newLevel > oldLevel) this.ticketLevelTracker.update(i, newLevel, false); // Paper - return removed; // CraftBukkit - } - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - this.addTicketAtLevel(tickettype, chunkcoordintpair, i, t0); - } - -+ // Paper start -+ public static final int PRIORITY_TICKET_LEVEL = PlayerChunkMap.GOLDEN_TICKET; -+ public static final int URGENT_PRIORITY = 29; -+ public boolean delayDistanceManagerTick = false; -+ public boolean markUrgent(ChunkCoordIntPair coords) { -+ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); -+ } -+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ return addPriorityTicket(coords, TicketType.PRIORITY, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { -+ delayDistanceManagerTick = true; -+ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); -+ int finalPriority = priority; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { -+ delayDistanceManagerTick = true; -+ MCUtil.getSpiralOutChunks(center.asPosition(), radius).forEach(coords -> { -+ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ }); -+ delayDistanceManagerTick = false; -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ -+ private boolean hasPlayerTicket(ChunkCoordIntPair coords, int level) { -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null || tickets.isEmpty()) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ private boolean addPriorityTicket(ChunkCoordIntPair coords, TicketType ticketType, int priority) { -+ AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); -+ long pair = coords.pair(); -+ PlayerChunk chunk = chunkMap.getUpdatingChunk(pair); -+ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); -+ -+ if (needsTicket) { -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); -+ getOnPlayerTicketAddQueue().add(pair); -+ addTicket(pair, ticket); -+ } -+ if ((chunk != null && chunk.isFullChunkReady())) { -+ if (needsTicket) { -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ } -+ return needsTicket; -+ } -+ -+ boolean success; -+ if (!(success = updatePriorityTicket(coords, ticketType, priority))) { -+ Ticket ticket = new Ticket(ticketType, PRIORITY_TICKET_LEVEL, coords); -+ ticket.priority = priority; -+ success = this.addTicket(pair, ticket); -+ } else { -+ if (chunk == null) { -+ chunk = chunkMap.getUpdatingChunk(pair); -+ } -+ chunkMap.queueHolderUpdate(chunk); -+ } -+ -+ //chunkMap.world.getWorld().spawnParticle(priority <= 15 ? org.bukkit.Particle.EXPLOSION_HUGE : org.bukkit.Particle.EXPLOSION_NORMAL, chunkMap.world.getWorld().getPlayers(), null, coords.x << 4, 70, coords.z << 4, 2, 0, 0, 0, 1, null, true); -+ -+ chunkMap.world.getChunkProvider().tickDistanceManager(); -+ -+ return success; -+ } -+ -+ private boolean updatePriorityTicket(ChunkCoordIntPair coords, TicketType type, int priority) { -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null) { -+ return false; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == type) { -+ // We only support increasing, not decreasing, too complicated -+ ticket.setCurrentTick(this.currentTick); -+ ticket.priority = Math.max(ticket.priority, priority); -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ public int getChunkPriority(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); -+ ArraySetSorted> tickets = this.tickets.get(coords.pair()); -+ if (tickets == null) { -+ return 0; -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.URGENT) { -+ return URGENT_PRIORITY; -+ } -+ } -+ for (Ticket ticket : tickets) { -+ if (ticket.getTicketType() == TicketType.PRIORITY && ticket.priority > 0) { -+ return ticket.priority; -+ } -+ } -+ return 0; -+ } -+ -+ public void clearPriorityTickets(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); -+ this.removeTicket(coords.pair(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ -+ public void clearUrgent(ChunkCoordIntPair coords) { -+ AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); -+ this.removeTicket(coords.pair(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); -+ } -+ // Paper end - public boolean addTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkcoordintpair, int level, T identifier) { - return this.addTicket(chunkcoordintpair.pair(), new Ticket<>(ticketType, level, identifier)); - // CraftBukkit end -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - - class c extends ChunkMapDistance.b { - -- private int e = 0; -+ private int e = 0; private int getViewDistance() { return e; } private void setViewDistance(int value) { this.e = value; } // Paper - OBFHELPER - private final Long2IntMap f = Long2IntMaps.synchronize(new Long2IntOpenHashMap()); - private final LongSet g = new LongOpenHashSet(); - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - - public void a(int i) { - ObjectIterator objectiterator = this.a.long2ByteEntrySet().iterator(); -+ // Paper start - set the view distance before scheduling chunk loads/unloads -+ int lastViewDistance = getViewDistance(); -+ setViewDistance(i); -+ // Paper end - - while (objectiterator.hasNext()) { - Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (Long2ByteMap.Entry) objectiterator.next(); // Paper - decompile fix - byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); - long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); - -- this.a(j, b0, this.c(b0), b0 <= i - 2); -+ this.a(j, b0, b0 <= lastViewDistance - 2, this.c(b0)); // Paper - } - -- this.e = i; -+ //this.e = i; // Paper - view distance is now set further up - } - - private void a(long i, int j, boolean flag, boolean flag1) { - if (flag != flag1) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance -+ ChunkCoordIntPair coords = new ChunkCoordIntPair(i); // Paper -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance - - if (flag1) { -- ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { -+ scheduleChunkLoad(i, MinecraftServer.currentTick, j, (priority) -> { // Paper - smarter ticket delay based on frustum and distance -+ // Paper start - recheck its still valid if not cancel -+ if (!isChunkInRange(i)) { -+ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { -+ ChunkMapDistance.this.m.execute(() -> { -+ ChunkMapDistance.this.removeTicket(i, ticket); -+ ChunkMapDistance.this.clearPriorityTickets(coords); -+ }); -+ }, i, false)); -+ return; -+ } -+ // abort early if we got a ticket already -+ if (hasPlayerTicket(coords, 33)) return; -+ // skip player ticket throttle for near chunks -+ if (priority <= 3) { -+ ChunkMapDistance.this.addTicket(i, ticket); -+ ChunkMapDistance.this.l.add(i); -+ return; -+ } -+ // Paper end -+ ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error - ChunkMapDistance.this.m.execute(() -> { -- if (this.c(this.c(i))) { -+ if (isChunkInRange(i)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it - ChunkMapDistance.this.addTicket(i, ticket); - ChunkMapDistance.this.l.add(i); -- } else { -- ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { -+ }} else { // Paper -+ ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error - }, i, false)); - } - - }); - }, i, () -> { -- return j; -+ return Math.min(PlayerChunkMap.GOLDEN_TICKET, priority); // Paper - })); -+ }); // Paper - } else { - ChunkMapDistance.this.k.a(ChunkTaskQueueSorter.a(() -> { - ChunkMapDistance.this.m.execute(() -> { - ChunkMapDistance.this.removeTicket(i, ticket); -+ ChunkMapDistance.this.clearPriorityTickets(coords); // Paper - }); - }, i, true)); - } -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - - } - -+ // Paper start - smart scheduling of player tickets -+ private boolean isChunkInRange(long i) { -+ return this.isLoadedChunkLevel(this.getChunkLevel(i)); -+ } -+ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { -+ long elapsed = MinecraftServer.currentTick - startTick; -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(i); -+ PlayerChunk updatingChunk = chunkMap.getUpdatingChunk(i); -+ if ((updatingChunk != null && updatingChunk.isFullChunkReady()) || !isChunkInRange(i) || getChunkPriority(chunkPos) > 0) { // Copied from above -+ // no longer needed -+ task.accept(1); -+ return; -+ } -+ -+ int desireDelay = 0; -+ double minDist = Double.MAX_VALUE; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(i); -+ if (elapsed == 0 && initialDistance <= 4) { -+ // Aim for no delay on initial 6 chunk radius tickets save on performance of the below code to only > 6 -+ minDist = initialDistance; -+ } else if (players != null) { -+ Object[] backingSet = players.getBackingSet(); -+ -+ BlockPosition blockPos = chunkPos.asPosition(); -+ -+ boolean isFront = false; -+ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ if (!(backingSet[index] instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) backingSet[index]; -+ -+ ChunkCoordIntPair pointInFront = player.getChunkInFront(5); -+ pos.setValues(pointInFront.x << 4, 0, pointInFront.z << 4); -+ double frontDist = MCUtil.distanceSq(pos, blockPos); -+ -+ pos.setValues(player.locX(), 0, player.locZ()); -+ double center = MCUtil.distanceSq(pos, blockPos); -+ -+ double dist = Math.min(frontDist, center); -+ if (!isFront) { -+ ChunkCoordIntPair pointInBack = player.getChunkInFront(-7); -+ pos.setValues(pointInBack.x << 4, 0, pointInBack.z << 4); -+ double backDist = MCUtil.distanceSq(pos, blockPos); -+ if (frontDist < backDist) { -+ isFront = true; -+ } -+ } -+ if (dist < minDist) { -+ minDist = dist; -+ } -+ } -+ if (minDist == Double.MAX_VALUE) { -+ minDist = 15; -+ } else { -+ minDist = Math.sqrt(minDist) / 16; -+ } -+ if (minDist > 4) { -+ int desiredTimeDelayMax = isFront ? -+ (minDist < 10 ? 7 : 15) : // Front -+ (minDist < 10 ? 15 : 45); // Back -+ desireDelay += (desiredTimeDelayMax * 20) * (minDist / 32); -+ } -+ } else { -+ minDist = initialDistance; -+ desireDelay = 1; -+ } -+ long delay = desireDelay - elapsed; -+ if (delay <= 0 && minDist > 4 && minDist < Double.MAX_VALUE) { -+ boolean hasAnyNeighbor = false; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) continue; -+ long pair = ChunkCoordIntPair.pair(chunkPos.x + x, chunkPos.z + z); -+ PlayerChunk neighbor = chunkMap.getUpdatingChunk(pair); -+ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; -+ if (current != null && current.isAtLeastStatus(ChunkStatus.LIGHT)) { -+ hasAnyNeighbor = true; -+ } -+ } -+ } -+ if (!hasAnyNeighbor) { -+ delay += 20; -+ } -+ } -+ if (delay <= 0) { -+ task.accept((int) minDist); -+ } else { -+ int taskDelay = (int) Math.min(delay, minDist >= 10 ? 40 : (minDist < 6 ? 5 : 20)); -+ MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); -+ } -+ } -+ // Paper end -+ - @Override - public void a() { - super.a(); -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - - } - -+ private boolean isLoadedChunkLevel(int i) { return c(i); } // Paper - OBFHELPER - private boolean c(int i) { - return i <= this.e - 2; - } -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - this.a.defaultReturnValue((byte) (i + 2)); - } - -+ protected final int getChunkLevel(long i) { return c(i); } // Paper - OBFHELPER - @Override - protected int c(long i) { - return this.a.get(i); -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - public void removeTicketAtLevel(TicketType ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) { - this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); - } -+ -+ public boolean markUrgent(ChunkCoordIntPair coords) { -+ return this.chunkMapDistance.markUrgent(coords); -+ } -+ -+ public boolean markHighPriority(ChunkCoordIntPair coords, int priority) { -+ return this.chunkMapDistance.markHighPriority(coords, priority); -+ } -+ -+ public void markAreaHighPriority(ChunkCoordIntPair center, int priority, int radius) { -+ this.chunkMapDistance.markAreaHighPriority(center, priority, radius); -+ } -+ -+ public void clearAreaPriorityTickets(ChunkCoordIntPair center, int radius) { -+ this.chunkMapDistance.clearAreaPriorityTickets(center, radius); -+ } -+ -+ public void clearPriorityTickets(ChunkCoordIntPair coords) { -+ this.chunkMapDistance.clearPriorityTickets(coords); -+ } - // Paper end - - @Nullable -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - - if (!completablefuture.isDone()) { // Paper - // Paper start - async chunk io/loading -+ ChunkCoordIntPair pair = new ChunkCoordIntPair(x, z); -+ this.chunkMapDistance.markUrgent(pair); - this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); - // Paper end -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - this.serverThreadQueue.awaitTasks(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug - this.world.timings.syncChunkLoad.stopTiming(); // Paper -+ this.chunkMapDistance.clearPriorityTickets(pair); // Paper -+ this.chunkMapDistance.clearUrgent(pair); // Paper - } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - if (flag && !currentlyUnloading) { - // CraftBukkit end - this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); -+ if (isUrgent) this.chunkMapDistance.markUrgent(chunkcoordintpair); // Paper - if (this.a(playerchunk, l)) { - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - - gameprofilerfiller.enter("chunkLoad"); -+ chunkMapDistance.delayDistanceManagerTick = false; // Paper - ensure this is never false - this.tickDistanceManager(); - playerchunk = this.getChunk(k); - gameprofilerfiller.exit(); -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } - } - } -- -- return this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); -+ // Paper start -+ CompletableFuture> future = this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap); -+ if (isUrgent) { -+ future.thenAccept(either -> this.chunkMapDistance.clearUrgent(chunkcoordintpair)); -+ } -+ return future; -+ // Paper end - } - - private boolean a(@Nullable PlayerChunk playerchunk, int i) { -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } - - public boolean tickDistanceManager() { // Paper - private -> public -+ if (chunkMapDistance.delayDistanceManagerTick) return false; // Paper - boolean flag = this.chunkMapDistance.a(this.playerChunkMap); - boolean flag1 = this.playerChunkMap.b(); - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.AdvancementDataPlayer; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.network.ITextFilter; - import net.minecraft.server.network.PlayerConnection; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private int lastArmorScored = Integer.MIN_VALUE; - private int lastExpLevelScored = Integer.MIN_VALUE; - private int lastExpTotalScored = Integer.MIN_VALUE; -+ public long lastHighPriorityChecked; // Paper -+ public void forceCheckHighPriority() { -+ lastHighPriorityChecked = -1; -+ getWorldServer().getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); -+ } -+ public boolean isRealPlayer; // Paper - private float lastHealthSent = -1.0E8F; - private int lastFoodSent = -99999999; - private boolean lastSentSaturationZero = true; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.maxHealthCache = this.getMaxHealth(); - this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } -+ // Paper start -+ public BlockPosition getPointInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason -+ final double x = locX() + inFront * Math.cos(rads); -+ final double z = locZ() + inFront * Math.sin(rads); -+ return new BlockPosition(x, locY(), z); -+ } -+ -+ public ChunkCoordIntPair getChunkInFront(double inFront) { -+ double rads = Math.toRadians(MCUtil.normalizeYaw(this.yaw+90)); // MC rotates yaw 90 for some odd reason -+ final double x = locX() + (inFront * 16) * Math.cos(rads); -+ final double z = locZ() + (inFront * 16) * Math.sin(rads); -+ return new ChunkCoordIntPair(MathHelper.floor(x) >> 4, MathHelper.floor(z) >> 4); -+ } -+ // Paper end - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. - // If this is an issue, PRs are welcome -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (valid && !this.isSpectator() || this.world.isLoaded(this.getChunkCoordinates())) { // Paper - don't tick dead players that are not in the world currently (pending respawn) - super.tick(); - } -+ if (valid && isAlive() && playerConnection != null) ((WorldServer)world).getChunkProvider().playerChunkMap.checkHighPriorityChunks(this); // Paper - - for (int i = 0; i < this.inventory.getSize(); ++i) { - ItemStack itemstack = this.inventory.getItem(i); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Either; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - import it.unimi.dsi.fastutil.shorts.ShortArraySet; - import it.unimi.dsi.fastutil.shorts.ShortSet; - import java.util.List; -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockChange; - import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.util.MathHelper; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; -@@ -0,0 +0,0 @@ public class PlayerChunk { - private CompletableFuture chunkSave; - public int oldTicketLevel; - private int ticketLevel; -- private int n; -- final ChunkCoordIntPair location; // Paper - private -> package -+ volatile int n; public final int getCurrentPriority() { return n; } // Paper - OBFHELPER - make volatile since this is concurrently accessed -+ public final ChunkCoordIntPair location; // Paper - private -> public - private boolean p; - private final ShortSet[] dirtyBlocks; - private int r; -@@ -0,0 +0,0 @@ public class PlayerChunk { - private boolean x; - - private final PlayerChunkMap chunkMap; // Paper -+ public WorldServer getWorld() { return chunkMap.world; } // Paper - - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave -@@ -0,0 +0,0 @@ public class PlayerChunk { - return null; - } - // Paper end - no-tick view distance -+ // Paper start - Chunk gen/load priority system -+ volatile int neighborPriority = -1; -+ volatile int priorityBoost = 0; -+ public final java.util.concurrent.ConcurrentHashMap neighbors = new java.util.concurrent.ConcurrentHashMap<>(); -+ public final Long2ObjectOpenHashMap neighborPriorities = new Long2ObjectOpenHashMap<>(); -+ -+ private int getDemandedPriority() { -+ int priority = neighborPriority; // if we have a neighbor priority, use it -+ int myPriority = getMyPriority(); -+ -+ if (priority == -1 || (ticketLevel <= 33 && priority > myPriority)) { -+ priority = myPriority; -+ } -+ -+ return Math.max(1, Math.min(Math.max(ticketLevel, PlayerChunkMap.GOLDEN_TICKET), priority)); -+ } -+ -+ private int getMyPriority() { -+ if (priorityBoost == ChunkMapDistance.URGENT_PRIORITY) { -+ return 2; // Urgent - ticket level isn't always 31 so 33-30 = 3, but allow 1 more tasks to go below this for dependents -+ } -+ return ticketLevel - priorityBoost; -+ } -+ -+ private int getNeighborsPriority() { -+ return (neighborPriorities.isEmpty() ? getMyPriority() : getDemandedPriority()) + 1; -+ } -+ -+ public void onNeighborRequest(PlayerChunk neighbor, ChunkStatus status) { -+ neighbor.setNeighborPriority(this, getNeighborsPriority()); -+ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { -+ if (currentWantedStatus == null || !currentWantedStatus.isAtLeastStatus(status)) { -+ //System.out.println(this + " request " + neighbor + " at " + status + " currently " + currentWantedStatus); -+ return status; -+ } else { -+ //System.out.println(this + " requested " + neighbor + " at " + status + " but thats lower than other wanted status " + currentWantedStatus); -+ return currentWantedStatus; -+ } -+ }); -+ -+ } -+ -+ public void onNeighborDone(PlayerChunk neighbor, ChunkStatus chunkstatus, IChunkAccess chunk) { -+ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { -+ if (wantedStatus != null && chunkstatus.isAtLeastStatus(wantedStatus)) { -+ //System.out.println(this + " neighbor done at " + neighbor + " for status " + chunkstatus + " wanted " + wantedStatus); -+ neighbor.removeNeighborPriority(this); -+ return null; -+ } else { -+ //System.out.println(this + " neighbor finished our previous request at " + neighbor + " for status " + chunkstatus + " but we now want instead " + wantedStatus); -+ return wantedStatus; -+ } -+ }); -+ } -+ -+ private void removeNeighborPriority(PlayerChunk requester) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.remove(requester.location.pair()); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ -+ private void setNeighborPriority(PlayerChunk requester, int priority) { -+ synchronized (neighborPriorities) { -+ neighborPriorities.put(requester.location.pair(), Integer.valueOf(priority)); -+ recalcNeighborPriority(); -+ } -+ checkPriority(); -+ } -+ -+ private void recalcNeighborPriority() { -+ neighborPriority = -1; -+ if (!neighborPriorities.isEmpty()) { -+ synchronized (neighborPriorities) { -+ for (Integer neighbor : neighborPriorities.values()) { -+ if (neighbor < neighborPriority || neighborPriority == -1) { -+ neighborPriority = neighbor; -+ } -+ } -+ } -+ } -+ } -+ private void checkPriority() { -+ if (getCurrentPriority() != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); -+ } -+ -+ public final double getDistance(EntityPlayer player) { -+ return getDistance(player.locX(), player.locZ()); -+ } -+ public final double getDistance(double blockX, double blockZ) { -+ int cx = MCUtil.fastFloor(blockX) >> 4; -+ int cz = MCUtil.fastFloor(blockZ) >> 4; -+ final double x = location.x - cx; -+ final double z = location.z - cz; -+ return (x * x) + (z * z); -+ } -+ -+ public final double getDistanceFrom(BlockPosition pos) { -+ return getDistance(pos.getX(), pos.getZ()); -+ } -+ -+ @Override -+ public String toString() { -+ return "PlayerChunk{" + -+ "location=" + location + -+ ", ticketLevel=" + ticketLevel + "/" + getChunkStatus(this.ticketLevel) + -+ ", chunkHolderStatus=" + getChunkHolderStatus() + -+ ", neighborPriority=" + getNeighborsPriority() + -+ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + getCurrentPriority() + -+ '}'; -+ } -+ // Paper end - - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - return null; - } -+ public static ChunkStatus getNextStatus(ChunkStatus status) { -+ if (status == ChunkStatus.FULL) { -+ return status; -+ } -+ return CHUNK_STATUSES.get(status.getStatusIndex() + 1); -+ } -+ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { -+ return ensureMain(getStatusFutureUnchecked(chunkstatus)); -+ } -+ public CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); -+ } - // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -@@ -0,0 +0,0 @@ public class PlayerChunk { - return this.n; - } - -+ private void setPriority(int i) { d(i); } // Paper - OBFHELPER - private void d(int i) { - this.n = i; - } -@@ -0,0 +0,0 @@ public class PlayerChunk { - // CraftBukkit start - // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. - if (playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && !playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { -- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - Chunk chunk = (Chunk)either.left().orElse(null); - if (chunk != null) { - playerchunkmap.callbackExecutor.execute(() -> { -@@ -0,0 +0,0 @@ public class PlayerChunk { - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -- this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { -+ this.fullChunkFuture = playerchunkmap.b(this); ensureMain(this.fullChunkFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk fullChunk = either.left().get(); - PlayerChunk.this.isFullChunkReady = true; - fullChunk.playerChunk = PlayerChunk.this; -+ this.chunkMap.chunkDistanceManager.clearPriorityTickets(location); - - - } -@@ -0,0 +0,0 @@ public class PlayerChunk { - - if (!flag4 && flag5) { - // Paper start - cache ticking ready status -- this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { -+ this.tickingFuture = playerchunkmap.a(this); ensureMain(this.tickingFuture).thenAccept((either) -> { // Paper - ensure main - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk tickingChunk = either.left().get(); -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - - // Paper start - cache ticking ready status -- this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { -+ this.entityTickingFuture = playerchunkmap.b(this.location); ensureMain(this.entityTickingFuture).thenAccept((either) -> { // Paper ensureMain - if (either.left().isPresent()) { - // note: Here is a very good place to add callbacks to logic waiting on this. - Chunk entityTickingChunk = either.left().get(); -@@ -0,0 +0,0 @@ public class PlayerChunk { - this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -- this.u.a(this.location, this::k, this.ticketLevel, this::d); -+ // Paper start - raise IO/load priority if priority changes, use our preferred priority -+ priorityBoost = chunkMap.chunkDistanceManager.getChunkPriority(location); -+ int priority = getDemandedPriority(); -+ if (getCurrentPriority() > priority) { -+ int ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ if (priority <= 10) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (priority <= 20) { -+ ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); -+ } -+ if (getCurrentPriority() != priority) { -+ this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -+ int neighborsPriority = getNeighborsPriority(); -+ this.neighbors.forEach((neighbor, neighborDesired) -> neighbor.setNeighborPriority(this, neighborsPriority)); -+ } -+ // Paper end - this.oldTicketLevel = this.ticketLevel; - // CraftBukkit start - // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins. - if (!playerchunk_state.isAtLeast(PlayerChunk.State.BORDER) && playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER)) { -- this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> { -+ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main - Chunk chunk = (Chunk)either.left().orElse(null); - if (chunk != null) { - playerchunkmap.callbackExecutor.execute(() -> { -@@ -0,0 +0,0 @@ public class PlayerChunk { - - public interface c { - -+ default void changePriority(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer) { a(chunkcoordintpair, intsupplier, i, intconsumer); } // Paper - OBFHELPER - void a(ChunkCoordIntPair chunkcoordintpair, IntSupplier intsupplier, int i, IntConsumer intconsumer); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; - import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ByteMap; - import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; // Paper - import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongIterator; -@@ -0,0 +0,0 @@ import net.minecraft.CrashReport; - import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.SystemUtils; -+import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - import org.bukkit.entity.Player; // CraftBukkit -+import org.spigotmc.AsyncCatcher; - - public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final WorldServer world; - private final LightEngineThreaded lightEngine; - private final IAsyncTaskHandler executor; -+ final java.util.concurrent.Executor mainInvokingExecutor; // Paper - public final ChunkGenerator chunkGenerator; - private final Supplier l; public final Supplier getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER - private final VillagePlace m; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public void execute(Runnable runnable) { -+ AsyncCatcher.catchOp("Callback Executor execute"); - if (queued == null) { - queued = new java.util.ArrayDeque<>(); - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public void run() { -+ AsyncCatcher.catchOp("Callback Executor run"); - if (queued == null) { - return; - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.world = worldserver; - this.chunkGenerator = chunkgenerator; - this.executor = iasynctaskhandler; -+ // Paper start -+ this.mainInvokingExecutor = (run) -> { -+ if (MCUtil.isMainThread()) { -+ run.run(); -+ } else { -+ iasynctaskhandler.execute(run); -+ } -+ }; -+ // Paper end - ThreadedMailbox threadedmailbox = ThreadedMailbox.a(executor, "worldgen"); - - iasynctaskhandler.getClass(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, - com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ checkHighPriorityChunks(player); - if (newState.size() != 1) { - return; - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); - PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -- }); -+ PlayerChunkMap.this.world.getChunkProvider().clearPriorityTickets(chunkPos); -+ }, (player, prevPos, newPos) -> { -+ player.lastHighPriorityChecked = -1; // reset and recheck -+ checkHighPriorityChunks(player); -+ }); - this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, - (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }); - // Paper end - no-tick view distance - } -+ // Paper start - Chunk Prioritization -+ public void queueHolderUpdate(PlayerChunk playerchunk) { -+ Runnable runnable = () -> { -+ if (isUnloading(playerchunk)) { -+ return; // unloaded -+ } -+ chunkDistanceManager.pendingChunkUpdates.add(playerchunk); -+ if (!chunkDistanceManager.pollingPendingChunkUpdates) { -+ world.getChunkProvider().tickDistanceManager(); -+ } -+ }; -+ if (MCUtil.isMainThread()) { -+ // We can't use executor here because it will not execute tasks if its currently in the middle of executing tasks... -+ runnable.run(); -+ } else { -+ executor.execute(runnable); -+ } -+ } -+ -+ private boolean isUnloading(PlayerChunk playerchunk) { -+ return playerchunk == null || unloadQueue.contains(playerchunk.location.pair()); -+ } -+ -+ private void updateChunkPriorityMap(Long2IntOpenHashMap map, long chunk, int level) { -+ int prev = map.getOrDefault(chunk, -1); -+ if (level > prev) { -+ map.put(chunk, level); -+ } -+ } -+ -+ public void checkHighPriorityChunks(EntityPlayer player) { -+ int currentTick = MinecraftServer.currentTick; -+ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players -+ return; -+ } -+ player.lastHighPriorityChecked = currentTick; -+ Long2IntOpenHashMap priorities = new Long2IntOpenHashMap(); -+ -+ int viewDistance = getEffectiveNoTickViewDistance(); -+ BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(); -+ -+ // Prioritize circular near -+ double playerChunkX = MathHelper.floor(player.locX()) >> 4; -+ double playerChunkZ = MathHelper.floor(player.locZ()) >> 4; -+ pos.setValues(player.locX(), 0, player.locZ()); -+ double twoThirdModifier = 2D / 3D; -+ MCUtil.getSpiralOutChunks(pos, Math.min(6, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ // Prioritize immediate -+ if (dist <= 4) { -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (27 - dist)); -+ return; -+ } -+ -+ // Prioritize nearby chunks -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (20 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 3 -+ ChunkCoordIntPair front3 = player.getChunkInFront(3); -+ pos.setValues(front3.x << 4, 0, front3.z << 4); -+ MCUtil.getSpiralOutChunks(pos, Math.min(5, viewDistance)).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ -+ // Prioritize Frustum near 5 -+ if (viewDistance > 4) { -+ ChunkCoordIntPair front5 = player.getChunkInFront(5); -+ pos.setValues(front5.x << 4, 0, front5.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 4).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) return; -+ -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ // Prioritize Frustum far 7 -+ if (viewDistance > 6) { -+ ChunkCoordIntPair front7 = player.getChunkInFront(7); -+ pos.setValues(front7.x << 4, 0, front7.z << 4); -+ MCUtil.getSpiralOutChunks(pos, 3).forEach(coord -> { -+ if (shouldSkipPrioritization(coord)) { -+ return; -+ } -+ double dist = MCUtil.distance(playerChunkX, 0, playerChunkZ, coord.x, 0, coord.z); -+ updateChunkPriorityMap(priorities, coord.pair(), (int) (25 - dist * twoThirdModifier)); -+ }); -+ } -+ -+ if (priorities.isEmpty()) return; -+ chunkDistanceManager.delayDistanceManagerTick = true; -+ priorities.long2IntEntrySet().fastForEach(entry -> chunkDistanceManager.markHighPriority(new ChunkCoordIntPair(entry.getLongKey()), entry.getIntValue())); -+ chunkDistanceManager.delayDistanceManagerTick = false; -+ world.getChunkProvider().tickDistanceManager(); -+ -+ } -+ -+ private boolean shouldSkipPrioritization(ChunkCoordIntPair coord) { -+ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.pair()) == null) return true; -+ PlayerChunk chunk = getUpdatingChunk(coord.pair()); -+ return chunk != null && (chunk.isFullChunkReady()); -+ } -+ // Paper end - - public void updatePlayerMobTypeMap(Entity entity) { - if (!this.world.paperConfig.perPlayerMobSpawns) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - List>> list = Lists.newArrayList(); - int j = chunkcoordintpair.x; - int k = chunkcoordintpair.z; -+ PlayerChunk requestingNeighbor = getUpdatingChunk(chunkcoordintpair.pair()); // Paper - - for (int l = -i; l <= i; ++l) { - for (int i1 = -i; i1 <= i; ++i1) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1); - CompletableFuture> completablefuture = playerchunk.a(chunkstatus, this); -+ // Paper start -+ if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) { -+ requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus); -+ completablefuture.thenAccept(either -> { -+ requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null)); -+ }); -+ } -+ // Paper end - - list.add(completablefuture); - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - - CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); -+ PlayerChunk playerChunk = getUpdatingChunk(chunkcoordintpair.pair()); -+ int chunkPriority = playerChunk != null ? playerChunk.getCurrentPriority() : 33; -+ int priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY; -+ -+ if (chunkPriority <= 10) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; -+ } else if (chunkPriority <= 20) { -+ priority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; -+ } -+ boolean isHighestPriority = priority == com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY; - if (chunkSaveFuture != null) { -- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); -- this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); - } else { -- this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, -- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, priority, chunkHolderConsumer, isHighestPriority); - } -+ this.world.asyncChunkTaskManager.raisePriority(chunkcoordintpair.x, chunkcoordintpair.z, priority); - return ret; - // Paper end - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - long i = playerchunk.i().pair(); - - playerchunk.getClass(); -- mailbox.a(ChunkTaskQueueSorter.a(runnable, i, playerchunk::getTicketLevel)); -+ mailbox.a(ChunkTaskQueueSorter.a(runnable, i, () -> 1)); // Paper - final loads are always urgent! - }); - } - -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -0,0 +0,0 @@ public final class Ticket implements Comparable> { - private final int b; - public final T identifier; public final T getObjectReason() { return this.identifier; } // Paper - OBFHELPER - private long d; public final long getCreationTick() { return this.d; } // Paper - OBFHELPER -+ public int priority = 0; // Paper - - protected Ticket(TicketType tickettype, int i, T t0) { - this.a = tickettype; -@@ -0,0 +0,0 @@ public final class Ticket implements Comparable> { - return this.b; - } - -+ public final void setCurrentTick(long i) { this.a(i); } // Paper - OBFHELPER - protected void a(long i) { - this.d = i; - } -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -0,0 +0,0 @@ public class TicketType { - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit - public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper - public static final TicketType ASYNC_LOAD = a("async_load", Long::compareTo); // Paper -+ public static final TicketType PRIORITY = a("priority", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper -+ public static final TicketType URGENT = a("urgent", Comparator.comparingLong(ChunkCoordIntPair::pair), 300); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.A = this.e; - this.player.setLocation(d0, d1, d2, f, f1); -+ this.player.forceCheckHighPriority(); // Paper - this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); - } - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); - PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; - playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); -- worldserver1.getChunkProvider().tickDistanceManager(); -- worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ worldserver1.getChunkProvider().markAreaHighPriority(pos, 28, 3); -+ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { - PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); - if (updatingChunk != null) { - return updatingChunk.getEntityTickingFuture(); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - SocketAddress socketaddress = loginlistener.networkManager.getSocketAddress(); - - EntityPlayer entity = new EntityPlayer(this.server, this.server.getWorldServer(World.OVERWORLD), gameprofile, new PlayerInteractManager(this.server.getWorldServer(World.OVERWORLD))); -+ entity.isRealPlayer = true; // Paper - Player player = entity.getBukkitEntity(); - PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.networkManager.getRawAddress()).getAddress()); - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // CraftBukkit end - - worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper -+ entityplayer1.forceCheckHighPriority(); // Player - while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { - entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); - } -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -0,0 +0,0 @@ public class ChunkCoordIntPair { - return "[" + this.x + ", " + this.z + "]"; - } - -+ public final BlockPosition asPosition() { return l(); } // Paper - OBFHELPER - public BlockPosition l() { - return new BlockPosition(this.d(), 0, this.e()); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - return future; - } - -+ if (!urgent) { -+ // if not urgent, at least use a slightly boosted priority -+ world.getChunkProvider().markHighPriority(new ChunkCoordIntPair(x, z), 1); -+ } - return this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { - net.minecraft.world.level.chunk.Chunk chunk = (net.minecraft.world.level.chunk.Chunk) either.left().orElse(null); - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.server.players.WhiteListEntry; -+import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityExperienceOrb; - import net.minecraft.world.entity.EntityLiving; -@@ -0,0 +0,0 @@ import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); - } - -+ // Paper start -+ @Override -+ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { -+ ((CraftWorld)loc.getWorld()).getHandle().getChunkProvider().markAreaHighPriority(new ChunkCoordIntPair(MathHelper.floor(loc.getX()) >> 4, MathHelper.floor(loc.getZ()) >> 4), 28, 3); // Paper - load area high priority -+ return super.teleportAsync(loc, cause); -+ } -+ // Paper end -+ - @Override - public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) { - Preconditions.checkArgument(location != null, "location"); diff --git a/Spigot-Server-Patches/Implement-CraftBlockSoundGroup.patch b/Spigot-Server-Patches/Implement-CraftBlockSoundGroup.patch deleted file mode 100644 index 1e3cf7690a..0000000000 --- a/Spigot-Server-Patches/Implement-CraftBlockSoundGroup.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: simpleauthority -Date: Tue, 28 May 2019 03:48:51 -0700 -Subject: [PATCH] Implement CraftBlockSoundGroup - - -diff --git a/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/block/CraftBlockSoundGroup.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.block; -+ -+import net.minecraft.world.level.block.SoundEffectType; -+import org.bukkit.Sound; -+import org.bukkit.craftbukkit.CraftSound; -+ -+public class CraftBlockSoundGroup implements BlockSoundGroup { -+ private final SoundEffectType soundEffectType; -+ -+ public CraftBlockSoundGroup(SoundEffectType soundEffectType) { -+ this.soundEffectType = soundEffectType; -+ } -+ -+ @Override -+ public Sound getBreakSound() { -+ return CraftSound.getBukkit(soundEffectType.getBreakSound()); -+ } -+ -+ @Override -+ public Sound getStepSound() { -+ return CraftSound.getBukkit(soundEffectType.getStepSound()); -+ } -+ -+ @Override -+ public Sound getPlaceSound() { -+ return CraftSound.getBukkit(soundEffectType.getPlaceSound()); -+ } -+ -+ @Override -+ public Sound getHitSound() { -+ return CraftSound.getBukkit(soundEffectType.getHitSound()); -+ } -+ -+ @Override -+ public Sound getFallSound() { -+ return CraftSound.getBukkit(soundEffectType.getFallSound()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -+++ b/src/main/java/net/minecraft/world/level/block/SoundEffectType.java -@@ -0,0 +0,0 @@ public class SoundEffectType { - public static final SoundEffectType U = new SoundEffectType(1.0F, 1.0F, SoundEffects.BLOCK_GILDED_BLACKSTONE_BREAK, SoundEffects.BLOCK_GILDED_BLACKSTONE_STEP, SoundEffects.BLOCK_GILDED_BLACKSTONE_PLACE, SoundEffects.BLOCK_GILDED_BLACKSTONE_HIT, SoundEffects.BLOCK_GILDED_BLACKSTONE_FALL); - public final float volume; - public final float pitch; -- public final SoundEffect breakSound; -+ public final SoundEffect breakSound; public final SoundEffect getBreakSound() { return this.breakSound; } // Paper - OBFHELPER // PAIL private -> public, rename breakSound - private final SoundEffect stepSound; - private final SoundEffect placeSound; -- public final SoundEffect hitSound; -+ public final SoundEffect hitSound; public final SoundEffect getHitSound() { return this.hitSound; } // Paper - OBFHELPER // PAIL private -> public, rename hitSound - private final SoundEffect fallSound; - - public SoundEffectType(float f, float f1, SoundEffect soundeffect, SoundEffect soundeffect1, SoundEffect soundeffect2, SoundEffect soundeffect3, SoundEffect soundeffect4) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - AxisAlignedBB aabb = shape.getBoundingBox(); - return new BoundingBox(getX() + aabb.minX, getY() + aabb.minY, getZ() + aabb.minZ, getX() + aabb.maxX, getY() + aabb.maxY, getZ() + aabb.maxZ); - } -+ -+ // Paper start -+ @Override -+ public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { -+ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Implement-EntityKnockbackByEntityEvent.patch b/Spigot-Server-Patches/Implement-EntityKnockbackByEntityEvent.patch deleted file mode 100644 index 4a2c341244..0000000000 --- a/Spigot-Server-Patches/Implement-EntityKnockbackByEntityEvent.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Mon, 18 Jun 2018 15:46:23 +0200 -Subject: [PATCH] Implement EntityKnockbackByEntityEvent - -This event is called when an entity receives knockback by another entity. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - - if (flag) { - if (f1 > 0.0F && entity instanceof EntityLiving) { -- ((EntityLiving) entity).a(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ ((EntityLiving) entity).doKnockback(f1 * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - this.ap = (float) (MathHelper.d(d1, d0) * 57.2957763671875D - (double) this.yaw); -- this.a(0.4F, d0, d1); -+ this.doKnockback(0.4F, d0, d1, entity1); // Paper - } else { - this.ap = (float) ((int) (Math.random() * 2.0D) * 180); - } -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - protected void e(EntityLiving entityliving) { -- entityliving.a(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ()); -+ entityliving.doKnockback(0.5F, entityliving.locX() - this.locX(), entityliving.locZ() - this.locZ(), this); // Paper - } - - private boolean f(DamageSource damagesource) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - public void a(float f, double d0, double d1) { -+ // Paper start - add knockbacking entity parameter -+ this.doKnockback(f, d0, d1, null); -+ } -+ public void doKnockback(float f, double d0, double d1, Entity knockingBackEntity) { -+ // Paper end - add knockbacking entity parameter - f = (float) ((double) f * (1.0D - this.b(GenericAttributes.KNOCKBACK_RESISTANCE))); - if (f > 0.0F) { - this.impulse = true; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - Vec3D vec3d1 = (new Vec3D(d0, 0.0D, d1)).d().a((double) f); - - this.setMot(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + (double) f) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); -+ -+ // Paper start - call EntityKnockbackByEntityEvent -+ Vec3D currentMot = this.getMot(); -+ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMot.x - vec3d.x, currentMot.y - vec3d.y, currentMot.z - vec3d.z); -+ // Restore old velocity to be able to access it in the event -+ this.setMot(vec3d); -+ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), f, delta).callEvent()) { -+ this.setMot(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); -+ } -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - if (flag5) { - if (i > 0) { - if (entity instanceof EntityLiving) { -- ((EntityLiving) entity).a((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ ((EntityLiving) entity).doKnockback((float) i * 0.5F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - } else { - entity.i((double) (-MathHelper.sin(this.yaw * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (MathHelper.cos(this.yaw * 0.017453292F) * (float) i * 0.5F)); - } -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - if (entityliving != this && entityliving != entity && !this.r(entityliving) && (!(entityliving instanceof EntityArmorStand) || !((EntityArmorStand) entityliving).isMarker()) && this.h((Entity) entityliving) < 9.0D) { - // CraftBukkit start - Only apply knockback if the damage hits - if (entityliving.damageEntity(DamageSource.playerAttack(this).sweep(), f4)) { -- entityliving.a(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F))); -+ entityliving.doKnockback(0.4F, (double) MathHelper.sin(this.yaw * 0.017453292F), (double) (-MathHelper.cos(this.yaw * 0.017453292F)), this); // Paper - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/Implement-EntityTeleportEndGatewayEvent.patch b/Spigot-Server-Patches/Implement-EntityTeleportEndGatewayEvent.patch deleted file mode 100644 index c056b09c51..0000000000 --- a/Spigot-Server-Patches/Implement-EntityTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jun 2018 14:08:39 +0200 -Subject: [PATCH] Implement EntityTeleportEndGatewayEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -0,0 +0,0 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - - } - // CraftBukkit end -+ // Paper start - EntityTeleportEndGatewayEvent - replicated from above -+ org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity = entity.getBukkitEntity(); -+ org.bukkit.Location location = new Location(world.getWorld(), (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ location.setPitch(bukkitEntity.getLocation().getPitch()); -+ location.setYaw(bukkitEntity.getLocation().getYaw()); -+ -+ com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent event = new com.destroystokyo.paper.event.entity.EntityTeleportEndGatewayEvent(bukkitEntity, bukkitEntity.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); -+ if (!event.callEvent()) { -+ return; -+ } -+ // Paper end - - entity1.resetPortalCooldown(); -- entity1.enderTeleportAndLoad((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D); -+ entity1.enderTeleportAndLoad(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper - } - - this.h(); diff --git a/Spigot-Server-Patches/Implement-Expanded-ArmorStand-API.patch b/Spigot-Server-Patches/Implement-Expanded-ArmorStand-API.patch deleted file mode 100644 index 74ffbf06ae..0000000000 --- a/Spigot-Server-Patches/Implement-Expanded-ArmorStand-API.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: willies952002 -Date: Thu, 26 Jul 2018 02:25:46 -0400 -Subject: [PATCH] Implement Expanded ArmorStand API - -Add the following: -- Add proper methods for getting and setting items in both hands. Deprecates old methods -- Enable/Disable slot interactions - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - return enumitemslot; - } - -+ public final boolean isSlotDisabled(EnumItemSlot slot) { return this.d(slot); } // Paper - OBFHELPER - private boolean d(EnumItemSlot enumitemslot) { - return (this.disabledSlots & 1 << enumitemslot.getSlotFlag()) != 0 || enumitemslot.a() == EnumItemSlot.Function.HAND && !this.hasArms(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - - import net.minecraft.core.Vector3f; -+import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.entity.decoration.EntityArmorStand; - import org.bukkit.craftbukkit.CraftEquipmentSlot; - import org.bukkit.craftbukkit.CraftServer; -@@ -0,0 +0,0 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { - public void setCanMove(boolean move) { - getHandle().canMove = move; - } -+ -+ @Override -+ public ItemStack getItem(org.bukkit.inventory.EquipmentSlot slot) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ return getHandle().getEquipment(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); -+ } -+ -+ @Override -+ public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack item) { -+ com.google.common.base.Preconditions.checkNotNull(slot, "slot"); -+ switch (slot) { -+ case HAND: -+ getEquipment().setItemInMainHand(item); -+ return; -+ case OFF_HAND: -+ getEquipment().setItemInOffHand(item); -+ return; -+ case FEET: -+ setBoots(item); -+ return; -+ case LEGS: -+ setLeggings(item); -+ return; -+ case CHEST: -+ setChestplate(item); -+ return; -+ case HEAD: -+ setHelmet(item); -+ return; -+ } -+ throw new UnsupportedOperationException(slot.name()); -+ } -+ -+ @Override -+ public java.util.Set getDisabledSlots() { -+ java.util.Set disabled = new java.util.HashSet<>(); -+ for (org.bukkit.inventory.EquipmentSlot slot : org.bukkit.inventory.EquipmentSlot.values()) { -+ if (this.isSlotDisabled(slot)) { -+ disabled.add(slot); -+ } -+ } -+ return disabled; -+ } -+ -+ @Override -+ public void setDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ int disabled = 0; -+ for (org.bukkit.inventory.EquipmentSlot slot : slots) { -+ if (slot == org.bukkit.inventory.EquipmentSlot.OFF_HAND) continue; -+ EnumItemSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); -+ disabled += (1 << nmsSlot.getSlotFlag()) + (1 << (nmsSlot.getSlotFlag() + 8)) + (1 << (nmsSlot.getSlotFlag() + 16)); -+ } -+ getHandle().disabledSlots = disabled; -+ } -+ -+ @Override -+ public void addDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ java.util.Collections.addAll(disabled, slots); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public void removeDisabledSlots(org.bukkit.inventory.EquipmentSlot... slots) { -+ java.util.Set disabled = getDisabledSlots(); -+ for (final org.bukkit.inventory.EquipmentSlot slot : slots) disabled.remove(slot); -+ setDisabledSlots(disabled.toArray(new org.bukkit.inventory.EquipmentSlot[0])); -+ } -+ -+ @Override -+ public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { -+ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Implement-Keyed-on-World.patch b/Spigot-Server-Patches/Implement-Keyed-on-World.patch deleted file mode 100644 index ff688072ed..0000000000 --- a/Spigot-Server-Patches/Implement-Keyed-on-World.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 6 Jan 2021 00:34:04 -0800 -Subject: [PATCH] Implement Keyed on World - - -diff --git a/src/main/java/net/minecraft/core/IRegistry.java b/src/main/java/net/minecraft/core/IRegistry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/IRegistry.java -+++ b/src/main/java/net/minecraft/core/IRegistry.java -@@ -0,0 +0,0 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - public static final ResourceKey> I = a("loot_function_type"); - public static final ResourceKey> J = a("loot_condition_type"); - public static final ResourceKey> K = a("dimension_type"); -- public static final ResourceKey> L = a("dimension"); -+ public static final ResourceKey> L = a("dimension"); public static final ResourceKey> getWorldRegistry() { return L; } // Paper - OBFHELPER - public static final ResourceKey> M = a("dimension"); - public static final IRegistry SOUND_EVENT = a(IRegistry.g, () -> { - return SoundEffects.ENTITY_ITEM_PICKUP; -@@ -0,0 +0,0 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - MinecraftKey minecraftkey = resourcekey.a(); - - IRegistry.a.put(minecraftkey, supplier); -- IRegistryWritable iregistrywritable = IRegistry.e; -+ IRegistryWritable iregistrywritable = IRegistry.e; // Paper - decompile fix - -- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); -+ return (R) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); // Paper - decompile fix - } - - protected IRegistry(ResourceKey> resourcekey, Lifecycle lifecycle) { -@@ -0,0 +0,0 @@ public abstract class IRegistry implements Codec, Keyable, Registry { - } - - public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { -- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); -+ return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix - } - - public static T a(IRegistry iregistry, int i, String s, T t0) { -- return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); -+ return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); // Paper - decompile fix - } - - static { -diff --git a/src/main/java/net/minecraft/resources/ResourceKey.java b/src/main/java/net/minecraft/resources/ResourceKey.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/resources/ResourceKey.java -+++ b/src/main/java/net/minecraft/resources/ResourceKey.java -@@ -0,0 +0,0 @@ public class ResourceKey { - private final MinecraftKey b; - private final MinecraftKey c; - -+ public static ResourceKey newResourceKey(ResourceKey> registryKey, MinecraftKey minecraftKey) { return a(registryKey, minecraftKey); } // Paper - OBFHELPER - public static ResourceKey a(ResourceKey> resourcekey, MinecraftKey minecraftkey) { - return a(resourcekey.c, minecraftkey); - } -@@ -0,0 +0,0 @@ public class ResourceKey { - return this.b.equals(resourcekey.a()); - } - -+ public MinecraftKey getLocation() { return a(); } // Paper - OBFHELPER - public MinecraftKey a() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } else if (name.equals(levelName + "_the_end")) { - worldKey = net.minecraft.world.level.World.THE_END; - } else { -- worldKey = ResourceKey.a(IRegistry.L, new MinecraftKey(name.toLowerCase(java.util.Locale.ENGLISH))); -+ worldKey = ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), new net.minecraft.resources.MinecraftKey(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper - } - - WorldServer internal = (WorldServer) new WorldServer(console, console.executorService, worldSession, worlddata, worldKey, dimensionmanager, getServer().worldLoadListenerFactory.create(11), -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return null; - } - -+ // Paper start -+ @Override -+ public World getWorld(NamespacedKey worldKey) { -+ WorldServer worldServer = console.getWorldServer(ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); -+ if (worldServer == null) return null; -+ return worldServer.getWorld(); -+ } -+ // Paper end -+ - public void addWorld(World world) { - // Check if a World already exists with the UID. - if (getWorld(world.getUID()) != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); - }, net.minecraft.server.MinecraftServer.getServer()); - } -+ -+ @Override -+ public org.bukkit.NamespacedKey getKey() { -+ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.getDimensionKey().getLocation()); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/Implement-Mob-Goal-API.patch b/Spigot-Server-Patches/Implement-Mob-Goal-API.patch deleted file mode 100644 index 7aac3dcedd..0000000000 --- a/Spigot-Server-Patches/Implement-Mob-Goal-API.patch +++ /dev/null @@ -1,1170 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger | Martin -Date: Fri, 3 Jan 2020 16:26:19 +0100 -Subject: [PATCH] Implement Mob Goal API - - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - 1.3 - test - -+ -+ -+ io.github.classgraph -+ classgraph -+ 4.8.47 -+ test -+ - - - -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/MobGoalHelper.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import com.destroystokyo.paper.entity.RangedEntity; -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; -+import com.google.common.collect.BiMap; -+import com.google.common.collect.HashBiMap; -+import java.lang.reflect.Constructor; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.EntityAgeable; -+import net.minecraft.world.entity.EntityCreature; -+import net.minecraft.world.entity.EntityFlying; -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.EntityTameableAnimal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ambient.EntityAmbient; -+import net.minecraft.world.entity.ambient.EntityBat; -+import net.minecraft.world.entity.animal.EntityAnimal; -+import net.minecraft.world.entity.animal.EntityBee; -+import net.minecraft.world.entity.animal.EntityCat; -+import net.minecraft.world.entity.animal.EntityChicken; -+import net.minecraft.world.entity.animal.EntityCod; -+import net.minecraft.world.entity.animal.EntityCow; -+import net.minecraft.world.entity.animal.EntityDolphin; -+import net.minecraft.world.entity.animal.EntityFish; -+import net.minecraft.world.entity.animal.EntityFishSchool; -+import net.minecraft.world.entity.animal.EntityFox; -+import net.minecraft.world.entity.animal.EntityGolem; -+import net.minecraft.world.entity.animal.EntityIronGolem; -+import net.minecraft.world.entity.animal.EntityMushroomCow; -+import net.minecraft.world.entity.animal.EntityOcelot; -+import net.minecraft.world.entity.animal.EntityPanda; -+import net.minecraft.world.entity.animal.EntityParrot; -+import net.minecraft.world.entity.animal.EntityPerchable; -+import net.minecraft.world.entity.animal.EntityPig; -+import net.minecraft.world.entity.animal.EntityPolarBear; -+import net.minecraft.world.entity.animal.EntityPufferFish; -+import net.minecraft.world.entity.animal.EntityRabbit; -+import net.minecraft.world.entity.animal.EntitySalmon; -+import net.minecraft.world.entity.animal.EntitySheep; -+import net.minecraft.world.entity.animal.EntitySnowman; -+import net.minecraft.world.entity.animal.EntitySquid; -+import net.minecraft.world.entity.animal.EntityTropicalFish; -+import net.minecraft.world.entity.animal.EntityTurtle; -+import net.minecraft.world.entity.animal.EntityWaterAnimal; -+import net.minecraft.world.entity.animal.EntityWolf; -+import net.minecraft.world.entity.animal.horse.EntityHorse; -+import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; -+import net.minecraft.world.entity.animal.horse.EntityHorseChestedAbstract; -+import net.minecraft.world.entity.animal.horse.EntityHorseDonkey; -+import net.minecraft.world.entity.animal.horse.EntityHorseMule; -+import net.minecraft.world.entity.animal.horse.EntityHorseSkeleton; -+import net.minecraft.world.entity.animal.horse.EntityHorseZombie; -+import net.minecraft.world.entity.animal.horse.EntityLlama; -+import net.minecraft.world.entity.animal.horse.EntityLlamaTrader; -+import net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon; -+import net.minecraft.world.entity.boss.wither.EntityWither; -+import net.minecraft.world.entity.monster.EntityBlaze; -+import net.minecraft.world.entity.monster.EntityCaveSpider; -+import net.minecraft.world.entity.monster.EntityCreeper; -+import net.minecraft.world.entity.monster.EntityDrowned; -+import net.minecraft.world.entity.monster.EntityEnderman; -+import net.minecraft.world.entity.monster.EntityEndermite; -+import net.minecraft.world.entity.monster.EntityEvoker; -+import net.minecraft.world.entity.monster.EntityGhast; -+import net.minecraft.world.entity.monster.EntityGiantZombie; -+import net.minecraft.world.entity.monster.EntityGuardian; -+import net.minecraft.world.entity.monster.EntityGuardianElder; -+import net.minecraft.world.entity.monster.EntityIllagerAbstract; -+import net.minecraft.world.entity.monster.EntityIllagerIllusioner; -+import net.minecraft.world.entity.monster.EntityIllagerWizard; -+import net.minecraft.world.entity.monster.EntityMagmaCube; -+import net.minecraft.world.entity.monster.EntityMonster; -+import net.minecraft.world.entity.monster.EntityMonsterPatrolling; -+import net.minecraft.world.entity.monster.EntityPhantom; -+import net.minecraft.world.entity.monster.EntityPigZombie; -+import net.minecraft.world.entity.monster.EntityPillager; -+import net.minecraft.world.entity.monster.EntityRavager; -+import net.minecraft.world.entity.monster.EntityShulker; -+import net.minecraft.world.entity.monster.EntitySilverfish; -+import net.minecraft.world.entity.monster.EntitySkeleton; -+import net.minecraft.world.entity.monster.EntitySkeletonAbstract; -+import net.minecraft.world.entity.monster.EntitySkeletonStray; -+import net.minecraft.world.entity.monster.EntitySkeletonWither; -+import net.minecraft.world.entity.monster.EntitySlime; -+import net.minecraft.world.entity.monster.EntitySpider; -+import net.minecraft.world.entity.monster.EntityStrider; -+import net.minecraft.world.entity.monster.EntityVex; -+import net.minecraft.world.entity.monster.EntityVindicator; -+import net.minecraft.world.entity.monster.EntityWitch; -+import net.minecraft.world.entity.monster.EntityZoglin; -+import net.minecraft.world.entity.monster.EntityZombie; -+import net.minecraft.world.entity.monster.EntityZombieHusk; -+import net.minecraft.world.entity.monster.EntityZombieVillager; -+import net.minecraft.world.entity.monster.IRangedEntity; -+import net.minecraft.world.entity.monster.hoglin.EntityHoglin; -+import net.minecraft.world.entity.monster.piglin.EntityPiglin; -+import net.minecraft.world.entity.monster.piglin.EntityPiglinAbstract; -+import net.minecraft.world.entity.monster.piglin.EntityPiglinBrute; -+import net.minecraft.world.entity.npc.EntityVillager; -+import net.minecraft.world.entity.npc.EntityVillagerAbstract; -+import net.minecraft.world.entity.npc.EntityVillagerTrader; -+import net.minecraft.world.entity.raid.EntityRaider; -+import org.bukkit.NamespacedKey; -+import org.bukkit.entity.AbstractHorse; -+import org.bukkit.entity.AbstractVillager; -+import org.bukkit.entity.Ageable; -+import org.bukkit.entity.Ambient; -+import org.bukkit.entity.Animals; -+import org.bukkit.entity.Bat; -+import org.bukkit.entity.Bee; -+import org.bukkit.entity.Blaze; -+import org.bukkit.entity.Cat; -+import org.bukkit.entity.CaveSpider; -+import org.bukkit.entity.ChestedHorse; -+import org.bukkit.entity.Chicken; -+import org.bukkit.entity.Cod; -+import org.bukkit.entity.Cow; -+import org.bukkit.entity.Creature; -+import org.bukkit.entity.Creeper; -+import org.bukkit.entity.Dolphin; -+import org.bukkit.entity.Donkey; -+import org.bukkit.entity.Drowned; -+import org.bukkit.entity.ElderGuardian; -+import org.bukkit.entity.EnderDragon; -+import org.bukkit.entity.Enderman; -+import org.bukkit.entity.Endermite; -+import org.bukkit.entity.Evoker; -+import org.bukkit.entity.Fish; -+import org.bukkit.entity.Flying; -+import org.bukkit.entity.Fox; -+import org.bukkit.entity.Ghast; -+import org.bukkit.entity.Giant; -+import org.bukkit.entity.Golem; -+import org.bukkit.entity.Guardian; -+import org.bukkit.entity.Hoglin; -+import org.bukkit.entity.Horse; -+import org.bukkit.entity.Husk; -+import org.bukkit.entity.Illager; -+import org.bukkit.entity.Illusioner; -+import org.bukkit.entity.IronGolem; -+import org.bukkit.entity.Llama; -+import org.bukkit.entity.MagmaCube; -+import org.bukkit.entity.Mob; -+import org.bukkit.entity.Monster; -+import org.bukkit.entity.Mule; -+import org.bukkit.entity.MushroomCow; -+import org.bukkit.entity.Ocelot; -+import org.bukkit.entity.Panda; -+import org.bukkit.entity.Parrot; -+import org.bukkit.entity.Phantom; -+import org.bukkit.entity.Pig; -+import org.bukkit.entity.PigZombie; -+import org.bukkit.entity.Piglin; -+import org.bukkit.entity.PiglinAbstract; -+import org.bukkit.entity.PiglinBrute; -+import org.bukkit.entity.Pillager; -+import org.bukkit.entity.PolarBear; -+import org.bukkit.entity.PufferFish; -+import org.bukkit.entity.Rabbit; -+import org.bukkit.entity.Raider; -+import org.bukkit.entity.Ravager; -+import org.bukkit.entity.Salmon; -+import org.bukkit.entity.Sheep; -+import org.bukkit.entity.Shulker; -+import org.bukkit.entity.Silverfish; -+import org.bukkit.entity.Skeleton; -+import org.bukkit.entity.SkeletonHorse; -+import org.bukkit.entity.Slime; -+import org.bukkit.entity.Snowman; -+import org.bukkit.entity.Spellcaster; -+import org.bukkit.entity.Spider; -+import org.bukkit.entity.Squid; -+import org.bukkit.entity.Stray; -+import org.bukkit.entity.Strider; -+import org.bukkit.entity.Tameable; -+import org.bukkit.entity.TraderLlama; -+import org.bukkit.entity.TropicalFish; -+import org.bukkit.entity.Turtle; -+import org.bukkit.entity.Vex; -+import org.bukkit.entity.Villager; -+import org.bukkit.entity.Vindicator; -+import org.bukkit.entity.WanderingTrader; -+import org.bukkit.entity.WaterMob; -+import org.bukkit.entity.Witch; -+import org.bukkit.entity.Wither; -+import org.bukkit.entity.WitherSkeleton; -+import org.bukkit.entity.Wolf; -+import org.bukkit.entity.Zoglin; -+import org.bukkit.entity.Zombie; -+import org.bukkit.entity.ZombieHorse; -+import org.bukkit.entity.ZombieVillager; -+ -+public class MobGoalHelper { -+ -+ private static final BiMap deobfuscationMap = HashBiMap.create(); -+ private static final Map, Class> entityClassCache = new HashMap<>(); -+ private static final Map, Class> bukkitMap = new HashMap<>(); -+ -+ static final Set ignored = new HashSet<>(); -+ -+ static { -+ // TODO these kinda should be checked on each release, in case obfuscation changes -+ deobfuscationMap.put("bee_b", "bee_attack"); -+ deobfuscationMap.put("bee_c", "bee_become_angry"); -+ deobfuscationMap.put("bee_d", "bee_enter_hive"); -+ deobfuscationMap.put("bee_e", "bee_go_to_hive"); -+ deobfuscationMap.put("bee_f", "bee_go_to_known_flower"); -+ deobfuscationMap.put("bee_g", "bee_grow_crop"); -+ deobfuscationMap.put("bee_h", "bee_hurt_by_other"); -+ deobfuscationMap.put("bee_i", "bee_locate_hive"); -+ deobfuscationMap.put("bee_k", "bee_pollinate"); -+ deobfuscationMap.put("bee_l", "bee_wander"); -+ deobfuscationMap.put("cat_a", "cat_avoid_entity"); -+ deobfuscationMap.put("cat_b", "cat_relax_on_owner"); -+ deobfuscationMap.put("dolphin_b", "dolphin_swim_to_treasure"); -+ deobfuscationMap.put("dolphin_c", "dolphin_swim_with_player"); -+ deobfuscationMap.put("dolphin_d", "dolphin_play_with_items"); -+ deobfuscationMap.put("drowned_a", "drowned_attack"); -+ deobfuscationMap.put("drowned_b", "drowned_goto_beach"); -+ deobfuscationMap.put("drowned_c", "drowned_goto_water"); -+ deobfuscationMap.put("drowned_e", "drowned_swim_up"); -+ deobfuscationMap.put("drowned_f", "drowned_trident_attack"); -+ deobfuscationMap.put("enderman_a", "enderman_freeze_when_looked_at"); -+ deobfuscationMap.put("evoker_a", "evoker_attack_spell"); -+ deobfuscationMap.put("evoker_b", "evoker_cast_spell"); -+ deobfuscationMap.put("evoker_c", "evoker_summon_spell"); -+ deobfuscationMap.put("evoker_d", "evoker_wololo_spell"); -+ deobfuscationMap.put("fish_b", "fish_swim"); -+ deobfuscationMap.put("fox_a", "fox_defend_trusted"); -+ deobfuscationMap.put("fox_b", "fox_faceplant"); -+ deobfuscationMap.put("fox_e", "fox_breed"); -+ deobfuscationMap.put("fox_f", "fox_eat_berries"); -+ deobfuscationMap.put("fox_g", "fox_float"); -+ deobfuscationMap.put("fox_h", "fox_follow_parent"); -+ deobfuscationMap.put("fox_j", "fox_look_at_player"); -+ deobfuscationMap.put("fox_l", "fox_melee_attack"); -+ deobfuscationMap.put("fox_n", "fox_panic"); -+ deobfuscationMap.put("fox_o", "fox_pounce"); -+ deobfuscationMap.put("fox_p", "fox_search_for_items"); -+ deobfuscationMap.put("fox_q", "fox_stroll_through_village"); -+ deobfuscationMap.put("fox_r", "fox_perch_and_search"); -+ deobfuscationMap.put("fox_s", "fox_seek_shelter"); -+ deobfuscationMap.put("fox_t", "fox_sleep"); -+ deobfuscationMap.put("fox_u", "fox_stalk_prey"); -+ deobfuscationMap.put("illager_abstract_b", "raider_open_door"); -+ deobfuscationMap.put("illager_illusioner_a", "illusioner_blindness_spell"); -+ deobfuscationMap.put("illager_illusioner_b", "illusioner_mirror_spell"); -+ deobfuscationMap.put("illager_wizard_b", "spellcaster_cast_spell"); -+ deobfuscationMap.put("llama_a", "llama_attack_wolf"); -+ deobfuscationMap.put("llama_c", "llama_hurt_by"); -+ deobfuscationMap.put("llama_trader_a", "llamatrader_defended_wandering_trader"); -+ deobfuscationMap.put("monster_patrolling_a", "long_distance_patrol"); -+ deobfuscationMap.put("ocelot_a", "ocelot_avoid_entity"); -+ deobfuscationMap.put("ocelot_b", "ocelot_tempt"); -+ deobfuscationMap.put("panda_b", "panda_attack"); -+ deobfuscationMap.put("panda_c", "panda_avoid"); -+ deobfuscationMap.put("panda_d", "panda_breed"); -+ deobfuscationMap.put("panda_e", "panda_hurt_by_target"); -+ deobfuscationMap.put("panda_f", "panda_lie_on_back"); -+ deobfuscationMap.put("panda_g", "panda_look_at_player"); -+ deobfuscationMap.put("panda_i", "panda_panic"); -+ deobfuscationMap.put("panda_j", "panda_roll"); -+ deobfuscationMap.put("panda_k", "panda_sit"); -+ deobfuscationMap.put("panda_l", "panda_sneeze"); -+ deobfuscationMap.put("phantom_b", "phantom_attack_player"); -+ deobfuscationMap.put("phantom_c", "phantom_attack_strategy"); -+ deobfuscationMap.put("phantom_e", "phantom_circle_around_anchor"); -+ deobfuscationMap.put("phantom_i", "phantom_sweep_attack"); -+ deobfuscationMap.put("polar_bear_a", "polarbear_attack_players"); -+ deobfuscationMap.put("polar_bear_b", "polarbear_hurt_by"); -+ deobfuscationMap.put("polar_bear_c", "polarbear_melee"); -+ deobfuscationMap.put("polar_bear_d", "polarbear_panic"); -+ deobfuscationMap.put("puffer_fish_a", "pufferfish_puff"); -+ deobfuscationMap.put("raider_a", "raider_hold_ground"); -+ deobfuscationMap.put("raider_b", "raider_obtain_banner"); -+ deobfuscationMap.put("raider_c", "raider_celebration"); -+ deobfuscationMap.put("raider_d", "raider_move_through_village"); -+ deobfuscationMap.put("ravager_a", "ravager_melee_attack"); -+ deobfuscationMap.put("shulker_a", "shulker_attack"); -+ deobfuscationMap.put("shulker_c", "shulker_defense"); -+ deobfuscationMap.put("shulker_d", "shulker_nearest"); -+ deobfuscationMap.put("shulker_e", "shulker_peek"); -+ deobfuscationMap.put("squid_a", "squid_flee"); -+ deobfuscationMap.put("skeleton_abstract_1", "skeleton_melee"); -+ deobfuscationMap.put("strider_a", "strider_go_to_lava"); -+ deobfuscationMap.put("turtle_a", "turtle_breed"); -+ deobfuscationMap.put("turtle_b", "turtle_go_home"); -+ deobfuscationMap.put("turtle_c", "turtle_goto_water"); -+ deobfuscationMap.put("turtle_d", "turtle_lay_egg"); -+ deobfuscationMap.put("turtle_f", "turtle_panic"); -+ deobfuscationMap.put("turtle_h", "turtle_random_stroll"); -+ deobfuscationMap.put("turtle_i", "turtle_tempt"); -+ deobfuscationMap.put("turtle_j", "turtle_travel"); -+ deobfuscationMap.put("vex_a", "vex_charge_attack"); -+ deobfuscationMap.put("vex_b", "vex_copy_target_of_owner"); -+ deobfuscationMap.put("vex_d", "vex_random_move"); -+ deobfuscationMap.put("villager_trader_a", "villagertrader_wander_to_position"); -+ deobfuscationMap.put("vindicator_a", "vindicator_break_door"); -+ deobfuscationMap.put("vindicator_b", "vindicator_johnny_attack"); -+ deobfuscationMap.put("vindicator_c", "vindicator_melee_attack"); -+ deobfuscationMap.put("wither_a", "wither_do_nothing"); -+ deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); -+ deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); -+ -+ ignored.add("selector_1"); -+ ignored.add("selector_2"); -+ ignored.add("wrapped"); -+ -+ bukkitMap.put(EntityInsentient.class, Mob.class); -+ bukkitMap.put(EntityAgeable.class, Ageable.class); -+ bukkitMap.put(EntityAmbient.class, Ambient.class); -+ bukkitMap.put(EntityAnimal.class, Animals.class); -+ bukkitMap.put(EntityBat.class, Bat.class); -+ bukkitMap.put(EntityBee.class, Bee.class); -+ bukkitMap.put(EntityBlaze.class, Blaze.class); -+ bukkitMap.put(EntityCat.class, Cat.class); -+ bukkitMap.put(EntityCaveSpider.class, CaveSpider.class); -+ bukkitMap.put(EntityChicken.class, Chicken.class); -+ bukkitMap.put(EntityCod.class, Cod.class); -+ bukkitMap.put(EntityCow.class, Cow.class); -+ bukkitMap.put(EntityCreature.class, Creature.class); -+ bukkitMap.put(EntityCreeper.class, Creeper.class); -+ bukkitMap.put(EntityDolphin.class, Dolphin.class); -+ bukkitMap.put(EntityDrowned.class, Drowned.class); -+ bukkitMap.put(EntityEnderDragon.class, EnderDragon.class); -+ bukkitMap.put(EntityEnderman.class, Enderman.class); -+ bukkitMap.put(EntityEndermite.class, Endermite.class); -+ bukkitMap.put(EntityEvoker.class, Evoker.class); -+ bukkitMap.put(EntityFish.class, Fish.class); -+ bukkitMap.put(EntityFishSchool.class, Fish.class); // close enough -+ bukkitMap.put(EntityFlying.class, Flying.class); -+ bukkitMap.put(EntityFox.class, Fox.class); -+ bukkitMap.put(EntityGhast.class, Ghast.class); -+ bukkitMap.put(EntityGiantZombie.class, Giant.class); -+ bukkitMap.put(EntityGolem.class, Golem.class); -+ bukkitMap.put(EntityGuardian.class, Guardian.class); -+ bukkitMap.put(EntityGuardianElder.class, ElderGuardian.class); -+ bukkitMap.put(EntityHorse.class, Horse.class); -+ bukkitMap.put(EntityHorseAbstract.class, AbstractHorse.class); -+ bukkitMap.put(EntityHorseChestedAbstract.class, ChestedHorse.class); -+ bukkitMap.put(EntityHorseDonkey.class, Donkey.class); -+ bukkitMap.put(EntityHorseMule.class, Mule.class); -+ bukkitMap.put(EntityHorseSkeleton.class, SkeletonHorse.class); -+ bukkitMap.put(EntityHorseZombie.class, ZombieHorse.class); -+ bukkitMap.put(EntityIllagerAbstract.class, Illager.class); -+ bukkitMap.put(EntityIllagerIllusioner.class, Illusioner.class); -+ bukkitMap.put(EntityIllagerWizard.class, Spellcaster.class); -+ bukkitMap.put(EntityIronGolem.class, IronGolem.class); -+ bukkitMap.put(EntityLlama.class, Llama.class); -+ bukkitMap.put(EntityLlamaTrader.class, TraderLlama.class); -+ bukkitMap.put(EntityMagmaCube.class, MagmaCube.class); -+ bukkitMap.put(EntityMonster.class, Monster.class); -+ bukkitMap.put(EntityMonsterPatrolling.class, Monster.class); // close enough -+ bukkitMap.put(EntityMushroomCow.class, MushroomCow.class); -+ bukkitMap.put(EntityOcelot.class, Ocelot.class); -+ bukkitMap.put(EntityPanda.class, Panda.class); -+ bukkitMap.put(EntityParrot.class, Parrot.class); -+ bukkitMap.put(EntityPerchable.class, Parrot.class); // close enough -+ bukkitMap.put(EntityPhantom.class, Phantom.class); -+ bukkitMap.put(EntityPig.class, Pig.class); -+ bukkitMap.put(EntityPigZombie.class, PigZombie.class); -+ bukkitMap.put(EntityPillager.class, Pillager.class); -+ bukkitMap.put(EntityPolarBear.class, PolarBear.class); -+ bukkitMap.put(EntityPufferFish.class, PufferFish.class); -+ bukkitMap.put(EntityRabbit.class, Rabbit.class); -+ bukkitMap.put(EntityRaider.class, Raider.class); -+ bukkitMap.put(EntityRavager.class, Ravager.class); -+ bukkitMap.put(EntitySalmon.class, Salmon.class); -+ bukkitMap.put(EntitySheep.class, Sheep.class); -+ bukkitMap.put(EntityShulker.class, Shulker.class); -+ bukkitMap.put(EntitySilverfish.class, Silverfish.class); -+ bukkitMap.put(EntitySkeleton.class, Skeleton.class); -+ bukkitMap.put(EntitySkeletonAbstract.class, Skeleton.class); -+ bukkitMap.put(EntitySkeletonStray.class, Stray.class); -+ bukkitMap.put(EntitySkeletonWither.class, WitherSkeleton.class); -+ bukkitMap.put(EntitySlime.class, Slime.class); -+ bukkitMap.put(EntitySnowman.class, Snowman.class); -+ bukkitMap.put(EntitySpider.class, Spider.class); -+ bukkitMap.put(EntitySquid.class, Squid.class); -+ bukkitMap.put(EntityTameableAnimal.class, Tameable.class); -+ bukkitMap.put(EntityTropicalFish.class, TropicalFish.class); -+ bukkitMap.put(EntityTurtle.class, Turtle.class); -+ bukkitMap.put(EntityVex.class, Vex.class); -+ bukkitMap.put(EntityVillager.class, Villager.class); -+ bukkitMap.put(EntityVillagerAbstract.class, AbstractVillager.class); -+ bukkitMap.put(EntityVillagerTrader.class, WanderingTrader.class); -+ bukkitMap.put(EntityVindicator.class, Vindicator.class); -+ bukkitMap.put(EntityWaterAnimal.class, WaterMob.class); -+ bukkitMap.put(EntityWitch.class, Witch.class); -+ bukkitMap.put(EntityWither.class, Wither.class); -+ bukkitMap.put(EntityWolf.class, Wolf.class); -+ bukkitMap.put(EntityZombie.class, Zombie.class); -+ bukkitMap.put(EntityZombieHusk.class, Husk.class); -+ bukkitMap.put(EntityZombieVillager.class, ZombieVillager.class); -+ bukkitMap.put(EntityHoglin.class, Hoglin.class); -+ bukkitMap.put(EntityPiglin.class, Piglin.class); -+ bukkitMap.put(EntityPiglinAbstract.class, PiglinAbstract.class); -+ bukkitMap.put(EntityPiglinBrute.class, PiglinBrute.class); -+ bukkitMap.put(EntityStrider.class, Strider.class); -+ bukkitMap.put(EntityZoglin.class, Zoglin.class); -+ } -+ -+ public static String getUsableName(Class clazz) { -+ String name = clazz.getName(); -+ name = name.substring(name.lastIndexOf(".") + 1); -+ boolean flag = false; -+ // inner classes -+ if (name.contains("$")) { -+ String cut = name.substring(name.indexOf("$") + 1); -+ if (cut.length() <= 2) { -+ name = name.replace("Entity", ""); -+ name = name.replace("$", "_"); -+ flag = true; -+ } else { -+ // mapped, wooo -+ name = cut; -+ } -+ } -+ name = name.replace("PathfinderGoal", ""); -+ StringBuilder sb = new StringBuilder(); -+ for (char c : name.toCharArray()) { -+ if (c >= 'A' && c <= 'Z') { -+ sb.append("_"); -+ sb.append(Character.toLowerCase(c)); -+ } else { -+ sb.append(c); -+ } -+ } -+ name = sb.toString(); -+ name = name.replaceFirst("_", ""); -+ -+ if (flag && !deobfuscationMap.containsKey(name.toLowerCase()) && !ignored.contains(name)) { -+ System.out.println("need to map " + clazz.getName() + " (" + name.toLowerCase() + ")"); -+ } -+ -+ // did we rename this key? -+ return deobfuscationMap.getOrDefault(name, name); -+ } -+ -+ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { -+ EnumSet goals = EnumSet.noneOf(GoalType.class); -+ for (GoalType type : GoalType.values()) { -+ if (types.hasElement(paperToVanilla(type))) { -+ goals.add(type); -+ } -+ } -+ return goals; -+ } -+ -+ public static GoalType vanillaToPaper(PathfinderGoal.Type type) { -+ switch (type) { -+ case MOVE: -+ return GoalType.MOVE; -+ case LOOK: -+ return GoalType.LOOK; -+ case JUMP: -+ return GoalType.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return GoalType.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return GoalType.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown vanilla mob goal type " + type.name()); -+ } -+ } -+ -+ public static EnumSet paperToVanilla(EnumSet types) { -+ EnumSet goals = EnumSet.noneOf(PathfinderGoal.Type.class); -+ for (GoalType type : types) { -+ goals.add(paperToVanilla(type)); -+ } -+ return goals; -+ } -+ -+ public static PathfinderGoal.Type paperToVanilla(GoalType type) { -+ switch (type) { -+ case MOVE: -+ return PathfinderGoal.Type.MOVE; -+ case LOOK: -+ return PathfinderGoal.Type.LOOK; -+ case JUMP: -+ return PathfinderGoal.Type.JUMP; -+ case UNKNOWN_BEHAVIOR: -+ return PathfinderGoal.Type.UNKNOWN_BEHAVIOR; -+ case TARGET: -+ return PathfinderGoal.Type.TARGET; -+ default: -+ throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); -+ } -+ } -+ -+ public static GoalKey getKey(Class goalClass) { -+ String name = getUsableName(goalClass); -+ if (ignored.contains(name)) { -+ //noinspection unchecked -+ return (GoalKey) GoalKey.of(Mob.class, NamespacedKey.minecraft(name)); -+ } -+ return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); -+ } -+ -+ public static Class getEntity(Class goalClass) { -+ //noinspection unchecked -+ return (Class) entityClassCache.computeIfAbsent(goalClass, key -> { -+ for (Constructor ctor : key.getDeclaredConstructors()) { -+ for (int i = 0; i < ctor.getParameterCount(); i++) { -+ Class param = ctor.getParameterTypes()[i]; -+ if (EntityInsentient.class.isAssignableFrom(param)) { -+ //noinspection unchecked -+ return toBukkitClass((Class) param); -+ } else if (IRangedEntity.class.isAssignableFrom(param)) { -+ return RangedEntity.class; -+ } -+ } -+ } -+ throw new RuntimeException("Can't figure out applicable entity for mob goal " + goalClass); // maybe just return EntityInsentient? -+ }); -+ } -+ -+ public static Class toBukkitClass(Class nmsClass) { -+ Class bukkitClass = bukkitMap.get(nmsClass); -+ if (bukkitClass == null) { -+ throw new RuntimeException("Can't figure out applicable bukkit entity for nms entity " + nmsClass); // maybe just return Mob? -+ } -+ return bukkitClass; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperCustomGoal.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps api in vanilla -+ */ -+public class PaperCustomGoal extends PathfinderGoal { -+ -+ private final Goal handle; -+ -+ public PaperCustomGoal(Goal handle) { -+ this.handle = handle; -+ -+ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); -+ if (this.getGoalTypes().size() == 0) { -+ this.getGoalTypes().addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void onTaskReset() { -+ handle.stop(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ public Goal getHandle() { -+ return handle; -+ } -+ -+ public GoalKey getKey() { -+ return handle.getKey(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperMobGoals.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import java.util.Collection; -+import java.util.EnumSet; -+import java.util.HashMap; -+import java.util.HashSet; -+import java.util.LinkedList; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalSelector; -+import net.minecraft.world.entity.ai.goal.PathfinderGoalWrapped; -+import org.bukkit.craftbukkit.entity.CraftMob; -+import org.bukkit.entity.Mob; -+ -+public class PaperMobGoals implements MobGoals { -+ -+ private final Map> instanceCache = new HashMap<>(); -+ -+ @Override -+ public void addGoal(T mob, int priority, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ getHandle(craftMob, goal.getTypes()).addGoal(priority, new PaperCustomGoal<>(goal)); -+ } -+ -+ @Override -+ public void removeGoal(T mob, Goal goal) { -+ CraftMob craftMob = (CraftMob) mob; -+ if (goal instanceof PaperCustomGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal((PathfinderGoal) goal); -+ } else if (goal instanceof PaperVanillaGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(((PaperVanillaGoal) goal).getHandle()); -+ } else { -+ List toRemove = new LinkedList<>(); -+ for (PathfinderGoalWrapped item : getHandle(craftMob, goal.getTypes()).getTasks()) { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { -+ toRemove.add(item.getGoal()); -+ } -+ } -+ } -+ -+ for (PathfinderGoal g : toRemove) { -+ getHandle(craftMob, goal.getTypes()).removeGoal(g); -+ } -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob) { -+ for (GoalType type : GoalType.values()) { -+ removeAllGoals(mob, type); -+ } -+ } -+ -+ @Override -+ public void removeAllGoals(T mob, GoalType type) { -+ for (Goal goal : getAllGoals(mob, type)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public void removeGoal(T mob, GoalKey key) { -+ for (Goal goal : getGoals(mob, key)) { -+ removeGoal(mob, goal); -+ } -+ } -+ -+ @Override -+ public boolean hasGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ @Override -+ public Goal getGoal(T mob, GoalKey key) { -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ return g; -+ } -+ } -+ return null; -+ } -+ -+ @Override -+ public Collection> getGoals(T mob, GoalKey key) { -+ Set> goals = new HashSet<>(); -+ for (Goal g : getAllGoals(mob)) { -+ if (g.getKey().equals(key)) { -+ goals.add(g); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getAllGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (PathfinderGoalWrapped item : getHandle(craftMob, type).getTasks()) { -+ if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getAllGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ for (PathfinderGoalWrapped item : getHandle(craftMob, internalType).getTasks()) { -+ if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { -+ continue; -+ } -+ -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ } -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob) { -+ Set> goals = new HashSet<>(); -+ for (GoalType type : GoalType.values()) { -+ goals.addAll(getRunningGoals(mob, type)); -+ } -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoals(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ getHandle(craftMob, type).getExecutingGoals() -+ .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ return goals; -+ } -+ -+ @Override -+ public Collection> getRunningGoalsWithout(T mob, GoalType type) { -+ CraftMob craftMob = (CraftMob) mob; -+ Set> goals = new HashSet<>(); -+ for (GoalType internalType : GoalType.values()) { -+ if (internalType == type) { -+ continue; -+ } -+ getHandle(craftMob, internalType).getExecutingGoals() -+ .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) -+ .forEach(item -> { -+ if (item.getGoal() instanceof PaperCustomGoal) { -+ //noinspection unchecked -+ goals.add(((PaperCustomGoal) item.getGoal()).getHandle()); -+ } else { -+ //noinspection unchecked -+ goals.add((Goal) instanceCache.computeIfAbsent(item.getGoal(), PaperVanillaGoal::new)); -+ } -+ }); -+ } -+ return goals; -+ } -+ -+ private PathfinderGoalSelector getHandle(CraftMob mob, EnumSet types) { -+ if (types.contains(GoalType.TARGET)) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+ -+ private PathfinderGoalSelector getHandle(CraftMob mob, GoalType type) { -+ if (type == GoalType.TARGET) { -+ return mob.getHandle().targetSelector; -+ } else { -+ return mob.getHandle().goalSelector; -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/ai/PaperVanillaGoal.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import java.util.EnumSet; -+ -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.bukkit.entity.Mob; -+ -+/** -+ * Wraps vanilla in api -+ */ -+public class PaperVanillaGoal implements VanillaGoal { -+ -+ private final PathfinderGoal handle; -+ private final GoalKey key; -+ -+ private final EnumSet types; -+ -+ public PaperVanillaGoal(PathfinderGoal handle) { -+ this.handle = handle; -+ this.key = MobGoalHelper.getKey(handle.getClass()); -+ this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); -+ } -+ -+ public PathfinderGoal getHandle() { -+ return handle; -+ } -+ -+ @Override -+ public boolean shouldActivate() { -+ return handle.shouldActivate2(); -+ } -+ -+ @Override -+ public boolean shouldStayActive() { -+ return handle.shouldStayActive2(); -+ } -+ -+ @Override -+ public void start() { -+ handle.start(); -+ } -+ -+ @Override -+ public void stop() { -+ handle.onTaskReset(); -+ } -+ -+ @Override -+ public void tick() { -+ handle.tick(); -+ } -+ -+ @Override -+ public GoalKey getKey() { -+ return key; -+ } -+ -+ @Override -+ public EnumSet getTypes() { -+ return types; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -0,0 +0,0 @@ public final class OptimizedSmallEnumSet> { - public boolean hasCommonElements(final OptimizedSmallEnumSet other) { - return (other.backingSet & this.backingSet) != 0; - } -+ -+ public boolean hasElement(final E element) { -+ return (this.backingSet & (1L << element.ordinal())) != 0; -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -0,0 +0,0 @@ public abstract class PathfinderGoal { - private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - -- public PathfinderGoal() {} -+ // Paper start make sure goaltypes is never empty -+ public PathfinderGoal() { -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } -+ } -+ // paper end - -- public abstract boolean a(); -+ public boolean a() { return this.shouldActivate(); } public boolean shouldActivate() { return false;} public boolean shouldActivate2() { return a(); } // Paper - OBFHELPER, for both directions... - -- public boolean b() { -+ public boolean b() { return this.shouldStayActive(); } public boolean shouldStayActive2() { return b(); } public boolean shouldStayActive() { // Paper - OBFHELPER, for both directions... - return this.a(); - } - -@@ -0,0 +0,0 @@ public abstract class PathfinderGoal { - return true; - } - -- public void c() {} -+ public void c() { this.start(); } public void start() {} // Paper - OBFHELPER - - public void d() { - onTaskReset(); // Paper - } - public void onTaskReset() {} // Paper - -- public void e() {} -+ public void e() { this.tick(); } public void tick() {} // Paper OBFHELPER - -- public void a(EnumSet enumset) { -+ public void a(EnumSet enumset) { this.setTypes(enumset); } public void setTypes(EnumSet enumset) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - this.goalTypes.clear(); - this.goalTypes.addAllUnchecked(enumset); -+ // make sure its never empty -+ if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); -+ } - // Paper end - remove streams from pathfindergoalselector - } - -@@ -0,0 +0,0 @@ public abstract class PathfinderGoal { - - public static enum Type { - -- MOVE, LOOK, JUMP, TARGET; -+ MOVE, LOOK, JUMP, TARGET, UNKNOWN_BEHAVIOR; // Paper - add unknown - - private Type() {} - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - } - }; - private final Map c = new EnumMap(PathfinderGoal.Type.class); -- private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER -+ private final Set d = Sets.newLinkedHashSet(); public final Set getTasks() { return d; }// Paper - OBFHELPER // Paper - private -> public - private final Supplier e; - private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. - private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - this.e = supplier; - } - -- public void a(int i, PathfinderGoal pathfindergoal) { -+ public void addGoal(int priority, PathfinderGoal goal) {a(priority, goal);} public void a(int i, PathfinderGoal pathfindergoal) { // Paper - OBFHELPER - this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); - } - -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - } - // Paper end - -- public void a(PathfinderGoal pathfindergoal) { -+ public void removeGoal(PathfinderGoal goal) {a(goal);} public void a(PathfinderGoal pathfindergoal) { // Paper - OBFHELPER - // Paper start - remove streams from pathfindergoalselector - for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { - PathfinderGoalWrapped goalWrapped = iterator.next(); -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - gameprofilerfiller.exit(); - } - -+ public final Stream getExecutingGoals() { return d(); } // Paper - OBFHELPER - public Stream d() { - return this.d.stream().filter(PathfinderGoalWrapped::g); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -0,0 +0,0 @@ import javax.annotation.Nullable; - - public class PathfinderGoalWrapped extends PathfinderGoal { - -- private final PathfinderGoal a; -- private final int b; -+ private final PathfinderGoal a; public PathfinderGoal getGoal() {return a;} // Paper - OBFHELPER -+ private final int b; public int getPriority() {return b;} // Paper - OBFHELPER - private boolean c; - - public PathfinderGoalWrapped(int i, PathfinderGoal pathfindergoal) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - public boolean isStopping() { - return net.minecraft.server.MinecraftServer.getServer().hasStopped(); - } -+ -+ private com.destroystokyo.paper.entity.ai.MobGoals mobGoals = new com.destroystokyo.paper.entity.ai.PaperMobGoals(); -+ @Override -+ public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { -+ return mobGoals; -+ } - // Paper end - } -diff --git a/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/test/java/com/destroystokyo/paper/entity/ai/VanillaMobGoalTest.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity.ai; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; -+import org.junit.Assert; -+import org.junit.Test; -+ -+import java.lang.reflect.Field; -+import java.lang.reflect.Modifier; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.List; -+import java.util.stream.Collectors; -+ -+import org.bukkit.entity.Mob; -+ -+import io.github.classgraph.ClassGraph; -+import io.github.classgraph.ScanResult; -+ -+public class VanillaMobGoalTest { -+ -+ @Test -+ public void testKeys() { -+ List> deprecated = new ArrayList<>(); -+ List> keys = new ArrayList<>(); -+ for (Field field : VanillaGoal.class.getFields()) { -+ if (field.getType().equals(GoalKey.class)) { -+ try { -+ GoalKey goalKey = (GoalKey) field.get(null); -+ if (field.getAnnotation(Deprecated.class) != null) { -+ deprecated.add(goalKey); -+ } else { -+ keys.add(goalKey); -+ } -+ } catch (IllegalAccessException e) { -+ System.out.println("Skipping " + field.getName() + ": " + e.getMessage()); -+ } -+ } -+ } -+ -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { -+ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); -+ } -+ -+ List> vanillaNames = classes.stream() -+ .filter(VanillaMobGoalTest::hasNoEnclosingClass) -+ .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) -+ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) -+ .collect(Collectors.toList()); -+ -+ List> missingFromAPI = new ArrayList<>(vanillaNames); -+ missingFromAPI.removeAll(keys); -+ missingFromAPI.removeIf(k -> MobGoalHelper.ignored.contains(k.getNamespacedKey().getKey())); -+ List> missingFromVanilla = new ArrayList<>(keys); -+ missingFromVanilla.removeAll(vanillaNames); -+ -+ boolean shouldFail = false; -+ if (missingFromAPI.size() != 0) { -+ System.out.println("Missing from API: "); -+ for (GoalKey key : missingFromAPI) { -+ System.out.println("GoalKey<" + key.getEntityClass().getSimpleName() + "> " + key.getNamespacedKey().getKey().toUpperCase() + -+ " = GoalKey.of(" + key.getEntityClass().getSimpleName() + ".class, NamespacedKey.minecraft(\"" + key.getNamespacedKey().getKey() + "\"));"); -+ } -+ shouldFail = true; -+ } -+ if (missingFromVanilla.size() != 0) { -+ System.out.println("Missing from vanilla: "); -+ missingFromVanilla.forEach(System.out::println); -+ shouldFail = true; -+ } -+ -+ if (deprecated.size() != 0) { -+ System.out.println("Deprecated (might want to remove them at some point): "); -+ deprecated.forEach(System.out::println); -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+ -+ private static boolean hasNoEnclosingClass(Class clazz) { -+ return clazz.getEnclosingClass() == null || hasNoEnclosingClass(clazz.getSuperclass()); -+ } -+ -+ @Test -+ public void testBukkitMap() { -+ List> classes; -+ try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft.world.entity").scan()) { -+ classes = scanResult.getSubclasses("net.minecraft.world.entity.EntityInsentient").loadClasses(); -+ } -+ Assert.assertNotEquals("There are supposed to be more than 0 entity types!", Collections.emptyList(), classes); -+ -+ boolean shouldFail = false; -+ for (Class nmsClass : classes) { -+ Class bukkitClass = MobGoalHelper.toBukkitClass((Class) nmsClass); -+ if (bukkitClass == null) { -+ shouldFail = true; -+ System.out.println("Missing bukkitMap.put(" + nmsClass.getSimpleName() + ".class, " + nmsClass.getSimpleName().replace("Entity", "") + ".class);"); -+ } -+ } -+ -+ if (shouldFail) Assert.fail("See above"); -+ } -+} diff --git a/Spigot-Server-Patches/Implement-Paper-VersionChecker.patch b/Spigot-Server-Patches/Implement-Paper-VersionChecker.patch deleted file mode 100644 index 37d1f0441a..0000000000 --- a/Spigot-Server-Patches/Implement-Paper-VersionChecker.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Mon, 27 May 2019 03:40:05 -0500 -Subject: [PATCH] Implement Paper VersionChecker - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import com.destroystokyo.paper.util.VersionFetcher; -+import com.google.common.base.Charsets; -+import com.google.common.io.Resources; -+import com.google.gson.*; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.format.NamedTextColor; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.io.*; -+import java.net.HttpURLConnection; -+import java.net.URL; -+import java.util.stream.StreamSupport; -+ -+public class PaperVersionFetcher implements VersionFetcher { -+ private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end -+ private static final String GITHUB_BRANCH_NAME = "master"; -+ private static @Nullable String mcVer; -+ -+ @Override -+ public long getCacheTime() { -+ return 720000; -+ } -+ -+ @Nonnull -+ @Override -+ public Component getVersionMessage(@Nonnull String serverVersion) { -+ String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); -+ return getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); -+ } -+ -+ private static @Nullable String getMinecraftVersion() { -+ if (mcVer == null) { -+ java.util.regex.Matcher matcher = VER_PATTERN.matcher(org.bukkit.Bukkit.getBukkitVersion()); -+ if (matcher.find()) { -+ String result = matcher.group(); -+ mcVer = result.substring(0, result.length() - 2); // strip 'R' anchor and trailing '-' -+ } else { -+ org.bukkit.Bukkit.getLogger().warning("Unable to match version to pattern! Report to PaperMC!"); -+ org.bukkit.Bukkit.getLogger().warning("Pattern: " + VER_PATTERN.toString()); -+ org.bukkit.Bukkit.getLogger().warning("Version: " + org.bukkit.Bukkit.getBukkitVersion()); -+ } -+ } -+ -+ return mcVer; -+ } -+ -+ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { -+ int distance; -+ try { -+ int jenkinsBuild = Integer.parseInt(versionInfo); -+ distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); -+ } catch (NumberFormatException ignored) { -+ versionInfo = versionInfo.replace("\"", ""); -+ distance = fetchDistanceFromGitHub(repo, branch, versionInfo); -+ } -+ -+ switch (distance) { -+ case -1: -+ return Component.text("Error obtaining version information", NamedTextColor.YELLOW); -+ case 0: -+ return Component.text("You are running the latest version", NamedTextColor.GREEN); -+ case -2: -+ return Component.text("Unknown version", NamedTextColor.YELLOW); -+ default: -+ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW); -+ } -+ } -+ -+ private static int fetchDistanceFromSiteApi(int jenkinsBuild, @Nullable String siteApiVersion) { -+ if (siteApiVersion == null) { return -1; } -+ try { -+ try (BufferedReader reader = Resources.asCharSource( -+ new URL("https://papermc.io/api/v2/projects/paper/versions/" + siteApiVersion), -+ Charsets.UTF_8 -+ ).openBufferedStream()) { -+ JsonObject json = new Gson().fromJson(reader, JsonObject.class); -+ JsonArray builds = json.getAsJsonArray("builds"); -+ int latest = StreamSupport.stream(builds.spliterator(), false) -+ .mapToInt(e -> e.getAsInt()) -+ .max() -+ .getAsInt(); -+ return latest - jenkinsBuild; -+ } catch (JsonSyntaxException ex) { -+ ex.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+ -+ // Contributed by Techcable in GH-65 -+ private static int fetchDistanceFromGitHub(@Nonnull String repo, @Nonnull String branch, @Nonnull String hash) { -+ try { -+ HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + repo + "/compare/" + branch + "..." + hash).openConnection(); -+ connection.connect(); -+ if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) return -2; // Unknown commit -+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) { -+ JsonObject obj = new Gson().fromJson(reader, JsonObject.class); -+ String status = obj.get("status").getAsString(); -+ switch (status) { -+ case "identical": -+ return 0; -+ case "behind": -+ return obj.get("behind_by").getAsInt(); -+ default: -+ return -1; -+ } -+ } catch (JsonSyntaxException | NumberFormatException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return -1; -+ } -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public String getTimingsServerName() { - return com.destroystokyo.paper.PaperConfig.timingsServerName; - } -+ -+ @Override -+ public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { -+ return new com.destroystokyo.paper.PaperVersionFetcher(); -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/Implement-Player-Client-Options-API.patch b/Spigot-Server-Patches/Implement-Player-Client-Options-API.patch deleted file mode 100644 index e9d8ac3c3e..0000000000 --- a/Spigot-Server-Patches/Implement-Player-Client-Options-API.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger | Martin -Date: Mon, 20 Jan 2020 21:38:15 +0100 -Subject: [PATCH] Implement Player Client Options API - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperSkinParts.java b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperSkinParts.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Objects; -+ -+import java.util.StringJoiner; -+ -+public class PaperSkinParts implements SkinParts { -+ -+ private final int raw; -+ -+ public PaperSkinParts(int raw) { -+ this.raw = raw; -+ } -+ -+ public boolean hasCapeEnabled() { -+ return (raw & 1) == 1; -+ } -+ -+ public boolean hasJacketEnabled() { -+ return (raw >> 1 & 1) == 1; -+ } -+ -+ public boolean hasLeftSleeveEnabled() { -+ return (raw >> 2 & 1) == 1; -+ } -+ -+ public boolean hasRightSleeveEnabled() { -+ return (raw >> 3 & 1) == 1; -+ } -+ -+ public boolean hasLeftPantsEnabled() { -+ return (raw >> 4 & 1) == 1; -+ } -+ -+ public boolean hasRightPantsEnabled() { -+ return (raw >> 5 & 1) == 1; -+ } -+ -+ public boolean hasHatsEnabled() { -+ return (raw >> 6 & 1) == 1; -+ } -+ -+ @Override -+ public int getRaw() { -+ return raw; -+ } -+ -+ @Override -+ public boolean equals(Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ PaperSkinParts that = (PaperSkinParts) o; -+ return raw == that.raw; -+ } -+ -+ @Override -+ public int hashCode() { -+ return Objects.hashCode(raw); -+ } -+ -+ @Override -+ public String toString() { -+ return new StringJoiner(", ", PaperSkinParts.class.getSimpleName() + "[", "]") -+ .add("raw=" + raw) -+ .add("cape=" + hasCapeEnabled()) -+ .add("jacket=" + hasJacketEnabled()) -+ .add("leftSleeve=" + hasLeftSleeveEnabled()) -+ .add("rightSleeve=" + hasRightSleeveEnabled()) -+ .add("leftPants=" + hasLeftPantsEnabled()) -+ .add("rightPants=" + hasRightPantsEnabled()) -+ .add("hats=" + hasHatsEnabled()) -+ .toString(); -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInSettings.java -@@ -0,0 +0,0 @@ public class PacketPlayInSettings implements Packet { - packetlistenerplayin.a(this); - } - -+ public EnumChatVisibility getChatVisibility() { return d(); } // Paper - OBFHELPER - public EnumChatVisibility d() { - return this.c; - } - -+ public boolean hasChatColorsEnabled() { return e(); } // Paper - OBFHELPER - public boolean e() { - return this.d; - } - -+ public int getSkinParts() { return f(); } // Paper - OBFHELPER - public int f() { - return this.e; - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ package net.minecraft.server.level; - - import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; - import com.google.common.collect.Lists; -+import com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent; // Paper - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; - import com.mojang.serialization.DataResult; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int lastSentExp = -99999999; - public int invulnerableTicks = 60; - private EnumChatVisibility bY; -- private boolean bZ = true; -+ private boolean bZ = true; public boolean hasChatColorsEnabled() { return this.bZ; } // Paper - OBFHELPER - private long ca = SystemUtils.getMonotonicMillis(); - private Entity spectatedEntity; - public boolean worldChangeInvuln; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null - public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { -+ new PlayerClientOptionsChangeEvent(getBukkitEntity(), packetplayinsettings.locale, packetplayinsettings.viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(packetplayinsettings.getChatVisibility().name()), packetplayinsettings.hasChatColorsEnabled(), new com.destroystokyo.paper.PaperSkinParts(packetplayinsettings.getSkinParts()), packetplayinsettings.getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT).callEvent(); // Paper - settings event - // CraftBukkit start - if (getMainHand() != packetplayinsettings.getMainHand()) { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - private static final Map b = ImmutableMap.builder().put(EntityPose.STANDING, EntityHuman.bh).put(EntityPose.SLEEPING, EntityHuman.ah).put(EntityPose.FALL_FLYING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntitySize.b(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntitySize.b(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntitySize.b(0.6F, 1.5F)).put(EntityPose.DYING, EntitySize.c(0.2F, 0.2F)).build(); - private static final DataWatcherObject c = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.c); - private static final DataWatcherObject d = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.b); -- protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); -+ protected static final DataWatcherObject bi = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); public static DataWatcherObject getSkinPartsWatcher() { return bi; } // Paper - OBFHELPER - protected static final DataWatcherObject bj = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.a); - protected static final DataWatcherObject bk = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); - protected static final DataWatcherObject bl = DataWatcher.a(EntityHuman.class, DataWatcherRegistry.p); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.ClientOption.ChatVisibility; -+import com.destroystokyo.paper.PaperSkinParts; -+import com.destroystokyo.paper.ClientOption; - import com.destroystokyo.paper.Title; - import com.google.common.base.Preconditions; - import com.google.common.collect.ImmutableSet; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void setViewDistance(int viewDistance) { - throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO - } -+ -+ @Override -+ public T getClientOption(ClientOption type) { -+ if(ClientOption.SKIN_PARTS.equals(type)) { -+ return type.getType().cast(new PaperSkinParts(getHandle().getDataWatcher().get(EntityHuman.getSkinPartsWatcher()))); -+ } else if(ClientOption.CHAT_COLORS_ENABLED.equals(type)) { -+ return type.getType().cast(getHandle().hasChatColorsEnabled()); -+ } else if(ClientOption.CHAT_VISIBILITY.equals(type)) { -+ return type.getType().cast(getHandle().getChatFlags() == null ? ChatVisibility.UNKNOWN : ChatVisibility.valueOf(getHandle().getChatFlags().name())); -+ } else if(ClientOption.LOCALE.equals(type)) { -+ return type.getType().cast(getLocale()); -+ } else if(ClientOption.MAIN_HAND.equals(type)) { -+ return type.getType().cast(getMainHand()); -+ } else if(ClientOption.VIEW_DISTANCE.equals(type)) { -+ return type.getType().cast(getClientViewDistance()); -+ } -+ throw new RuntimeException("Unknown settings type"); -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/Implement-PlayerFlowerPotManipulateEvent.patch b/Spigot-Server-Patches/Implement-PlayerFlowerPotManipulateEvent.patch deleted file mode 100644 index 63b16a0876..0000000000 --- a/Spigot-Server-Patches/Implement-PlayerFlowerPotManipulateEvent.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Tue, 13 Aug 2019 19:45:06 -0700 -Subject: [PATCH] Implement PlayerFlowerPotManipulateEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFlowerPot.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.shapes.VoxelShape; - import net.minecraft.world.phys.shapes.VoxelShapeCollision; - -+import io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent; // Paper -+ - public class BlockFlowerPot extends Block { - - private static final Map b = Maps.newHashMap(); -@@ -0,0 +0,0 @@ public class BlockFlowerPot extends Block { - boolean flag1 = this.c == Blocks.AIR; - - if (flag != flag1) { -+ // Paper start -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) entityhuman.getBukkitEntity(); -+ boolean placing = flag1; -+ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition); -+ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack); -+ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(c); -+ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); -+ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; -+ -+ PlayerFlowerPotManipulateEvent event = new PlayerFlowerPotManipulateEvent(player, bukkitblock, whichitem, placing); -+ player.getServer().getPluginManager().callEvent(event); -+ -+ if (event.isCancelled()) { -+ // Update client -+ player.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); -+ player.updateInventory(); -+ -+ return EnumInteractionResult.PASS; -+ } -+ // Paper end -+ - if (flag1) { - world.setTypeAndData(blockposition, block.getBlockData(), 3); - entityhuman.a(StatisticList.POT_FLOWER); diff --git a/Spigot-Server-Patches/Implement-PlayerLocaleChangeEvent.patch b/Spigot-Server-Patches/Implement-PlayerLocaleChangeEvent.patch deleted file mode 100644 index 551a52c013..0000000000 --- a/Spigot-Server-Patches/Implement-PlayerLocaleChangeEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Isaac Moore -Date: Tue, 19 Apr 2016 14:09:31 -0500 -Subject: [PATCH] Implement PlayerLocaleChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return s; - } - -- public String locale = "en_us"; // CraftBukkit - add, lowercase -+ public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null - public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { - // CraftBukkit start -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); - this.server.server.getPluginManager().callEvent(event); - } -- if (!this.locale.equals(packetplayinsettings.locale)) { -+ if (this.locale == null || !this.locale.equals(packetplayinsettings.locale)) { // Paper - check for null - PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packetplayinsettings.locale); - this.server.server.getPluginManager().callEvent(event); -+ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packetplayinsettings.locale).callEvent(); // Paper - } - this.locale = packetplayinsettings.locale; - // Paper start -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public String getLocale() { -- return getHandle().locale; -- -+ // Paper start - Locale change event -+ final String locale = getHandle().locale; -+ return locale != null ? locale : "en_us"; -+ // Paper end - } - - // Paper start diff --git a/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch b/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch deleted file mode 100644 index 1c48e3be5d..0000000000 --- a/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MisterVector -Date: Fri, 26 Oct 2018 21:31:00 -0700 -Subject: [PATCH] Implement PlayerPostRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // this.a(entityplayer1, entityplayer, worldserver1); // CraftBukkit - removed - boolean flag2 = false; - -+ // Paper start -+ boolean isBedSpawn = false; -+ boolean isRespawn = false; -+ // Paper end -+ - // CraftBukkit start - fire PlayerRespawnEvent - if (location == null) { -- boolean isBedSpawn = false; -+ // boolean isBedSpawn = false; // Paper - moved up - WorldServer worldserver1 = this.server.getWorldServer(entityplayer.getSpawnDimension()); - if (worldserver1 != null) { - Optional optional; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - location = respawnEvent.getRespawnLocation(); - if (!flag) entityplayer.reset(); // SPIGOT-4785 -+ isRespawn = true; // Paper - } else { - location.setWorld(worldserver.getWorld()); - } -@@ -0,0 +0,0 @@ public abstract class PlayerList { - if (entityplayer.playerConnection.isDisconnected()) { - this.savePlayerFile(entityplayer); - } -+ -+ // Paper start -+ if (isRespawn) { -+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(entityplayer.getBukkitEntity(), location, isBedSpawn)); -+ } -+ // Paper end -+ - // CraftBukkit end - return entityplayer1; - } diff --git a/Spigot-Server-Patches/Implement-TargetHitEvent.patch b/Spigot-Server-Patches/Implement-TargetHitEvent.patch deleted file mode 100644 index 888f960e03..0000000000 --- a/Spigot-Server-Patches/Implement-TargetHitEvent.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Wed, 25 Nov 2020 23:20:44 -0800 -Subject: [PATCH] Implement TargetHitEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTarget.java b/src/main/java/net/minecraft/world/level/block/BlockTarget.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTarget.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTarget.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block; - -+import io.papermc.paper.event.block.TargetHitEvent; // Paper - Need to import because 'io' class exists in nms - import java.util.Random; - import net.minecraft.advancements.CriterionTriggers; - import net.minecraft.core.BlockPosition; -@@ -0,0 +0,0 @@ public class BlockTarget extends Block { - @Override - public void a(World world, IBlockData iblockdata, MovingObjectPositionBlock movingobjectpositionblock, IProjectile iprojectile) { - int i = a((GeneratorAccess) world, iblockdata, movingobjectpositionblock, (Entity) iprojectile); -+ // Paper start -+ } -+ private static void awardTargetHitCriteria(IProjectile iprojectile, MovingObjectPositionBlock movingobjectpositionblock, int i) { -+ // Paper end - Entity entity = iprojectile.getShooter(); - - if (entity instanceof EntityPlayer) { -@@ -0,0 +0,0 @@ public class BlockTarget extends Block { - int i = a(movingobjectpositionblock, movingobjectpositionblock.getPos()); - int j = entity instanceof EntityArrow ? 20 : 8; - -+ // Paper start -+ if (entity instanceof IProjectile) { -+ final IProjectile projectile = (IProjectile) entity; -+ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(generatoraccess, movingobjectpositionblock.getBlockPosition()); -+ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(movingobjectpositionblock.getDirection()); -+ final TargetHitEvent targetHitEvent = new TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); -+ if (targetHitEvent.callEvent()) { -+ i = targetHitEvent.getSignalStrength(); -+ awardTargetHitCriteria(projectile, movingobjectpositionblock, i); -+ } else { -+ return i; -+ } -+ } -+ // Paper end - if (!generatoraccess.getBlockTickList().a(movingobjectpositionblock.getBlockPosition(), iblockdata.getBlock())) { - a(generatoraccess, iblockdata, i, movingobjectpositionblock.getBlockPosition(), j); - } diff --git a/Spigot-Server-Patches/Implement-World.getEntity-UUID-API.patch b/Spigot-Server-Patches/Implement-World.getEntity-UUID-API.patch deleted file mode 100644 index 401e353db7..0000000000 --- a/Spigot-Server-Patches/Implement-World.getEntity-UUID-API.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 3 Jul 2018 16:08:14 +0200 -Subject: [PATCH] Implement World.getEntity(UUID) API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - return list; - } - -+ // Paper start - getEntity by UUID API -+ @Override -+ public Entity getEntity(UUID uuid) { -+ Validate.notNull(uuid, "UUID cannot be null"); -+ net.minecraft.world.entity.Entity entity = world.getEntity(uuid); -+ return entity == null ? null : entity.getBukkitEntity(); -+ } -+ // Paper end -+ - @Override - public void save() { - org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot diff --git a/Spigot-Server-Patches/Implement-alternative-item-despawn-rate.patch b/Spigot-Server-Patches/Implement-alternative-item-despawn-rate.patch deleted file mode 100644 index bbd21c7d53..0000000000 --- a/Spigot-Server-Patches/Implement-alternative-item-despawn-rate.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 3 Jun 2019 02:02:39 -0400 -Subject: [PATCH] Implement alternative item-despawn-rate - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper; - - import java.util.Arrays; -+import java.util.EnumMap; -+import java.util.HashMap; - import java.util.List; -+import java.util.Map; - - import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; - import org.bukkit.Bukkit; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void disableRelativeProjectileVelocity() { - disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); - } -+ -+ public boolean altItemDespawnRateEnabled; -+ public Map altItemDespawnRateMap; -+ private void altItemDespawnRate() { -+ String path = "alt-item-despawn-rate"; -+ -+ altItemDespawnRateEnabled = getBoolean(path + ".enabled", false); -+ -+ Map altItemDespawnRateMapDefault = new EnumMap<>(Material.class); -+ altItemDespawnRateMapDefault.put(Material.COBBLESTONE, 300); -+ for (Material key : altItemDespawnRateMapDefault.keySet()) { -+ config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); -+ } -+ -+ Map rawMap = new HashMap<>(); -+ try { -+ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); -+ if (mapSection == null) { -+ mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); -+ } -+ for (String key : mapSection.getKeys(false)) { -+ int val = mapSection.getInt(key); -+ rawMap.put(key, val); -+ } -+ } -+ catch (Exception e) { -+ logError("alt-item-despawn-rate was malformatted"); -+ altItemDespawnRateEnabled = false; -+ } -+ -+ altItemDespawnRateMap = new EnumMap<>(Material.class); -+ if (!altItemDespawnRateEnabled) { -+ return; -+ } -+ -+ for(String key : rawMap.keySet()) { -+ try { -+ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); -+ } catch (Exception e) { -+ logError("Could not add item " + key + " to altItemDespawnRateMap: " + e.getMessage()); -+ } -+ } -+ if(altItemDespawnRateEnabled) { -+ for(Material key : altItemDespawnRateMap.keySet()) { -+ log("Alternative item despawn rate of " + key + ": " + altItemDespawnRateMap.get(key)); -+ } -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.Vec3D; - - // CraftBukkit start - import net.minecraft.server.MinecraftServer; -+import org.bukkit.Material; // Paper - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - } - } - -- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end - -- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper - // CraftBukkit start - fire ItemDespawnEvent - if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - this.age = 0; -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - - public void s() { - this.o(); -- this.age = world.spigotConfig.itemDespawnRate - 1; // Spigot -+ this.age = this.getDespawnRate() - 1; // Spigot // Paper - } - -+ // Paper start -+ public int getDespawnRate(){ -+ Material material = this.getItemStack().getBukkitStack().getType(); -+ return world.paperConfig.altItemDespawnRateMap.getOrDefault(material, world.spigotConfig.itemDespawnRate); -+ } -+ // Paper end -+ - @Override - public Packet P() { - return new PacketPlayOutSpawnEntity(this); diff --git a/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch deleted file mode 100644 index a220233e9c..0000000000 --- a/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch +++ /dev/null @@ -1,446 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Wed, 12 Sep 2018 18:53:55 +0300 -Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values - - -diff --git a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -+++ b/src/main/java/net/minecraft/commands/arguments/blocks/ArgumentBlock.java -@@ -0,0 +0,0 @@ public class ArgumentBlock { - private final boolean j; - private final Map, Comparable> k = Maps.newLinkedHashMap(); // CraftBukkit - stable - private final Map l = Maps.newHashMap(); -- private MinecraftKey m = new MinecraftKey(""); -+ private MinecraftKey m = new MinecraftKey(""); public final MinecraftKey getBlockKey() { return this.m; } // Paper - OBFHELPER - private BlockStateList n; - private IBlockData o; - @Nullable -@@ -0,0 +0,0 @@ public class ArgumentBlock { - return this.p; - } - -+ public final @Nullable MinecraftKey getTagKey() { return d(); } // Paper - OBFHELPER - @Nullable - public MinecraftKey d() { - return this.q; - } - -+ public final ArgumentBlock parse(boolean parseTile) throws CommandSyntaxException { return this.a(parseTile); } // Paper - OBFHELPER - public ArgumentBlock a(boolean flag) throws CommandSyntaxException { - this.s = this::l; - if (this.i.canRead() && this.i.peek() == '#') { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -0,0 +0,0 @@ import java.util.logging.Level; - import java.util.logging.Logger; - import javax.annotation.Nonnull; - import javax.annotation.Nullable; -+import net.minecraft.commands.arguments.blocks.ArgumentBlock; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTCompressedStreamTools; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.ChatComponentText; -+import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.entity.EnumItemSlot; - import net.minecraft.world.item.ItemBlock; - import org.apache.commons.codec.binary.Base64; -@@ -0,0 +0,0 @@ import org.bukkit.persistence.PersistentDataContainer; - import static org.spigotmc.ValidateUtils.*; - // Spigot end - -+// Paper start -+import com.destroystokyo.paper.Namespaced; -+import com.destroystokyo.paper.NamespacedTag; -+import java.util.Collections; -+// Paper end -+ - /** - * Children must include the following: - * -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Specific(Specific.To.NBT) - static final ItemMetaKey BLOCK_DATA = new ItemMetaKey("BlockStateTag"); - static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues"); -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy"); -+ static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn"); -+ // Paper end - - // We store the raw original JSON representation of all text data. See SPIGOT-5063, SPIGOT-5656, SPIGOT-5304 - private String displayName; -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - private int hideFlag; - private boolean unbreakable; - private int damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ private Set placeableKeys = Sets.newHashSet(); -+ private Set destroyableKeys = Sets.newHashSet(); -+ // Paper end - - private static final Set HANDLED_TAGS = Sets.newHashSet(); - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.hideFlag = meta.hideFlag; - this.unbreakable = meta.unbreakable; - this.damage = meta.damage; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (meta.hasPlaceableKeys()) { -+ this.placeableKeys = new java.util.HashSet<>(meta.placeableKeys); -+ } -+ -+ if (meta.hasDestroyableKeys()) { -+ this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys); -+ } -+ // Paper end - this.unhandledTags.putAll(meta.unhandledTags); - this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); - -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - persistentDataContainer.put(key, compound.get(key)); - } - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (tag.hasKey(CAN_DESTROY.NBT)) { -+ NBTTagList list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(namespaced); -+ } -+ } -+ -+ if (tag.hasKey(CAN_PLACE_ON.NBT)) { -+ NBTTagList list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); -+ for (int i = 0; i < list.size(); i++) { -+ Namespaced namespaced = this.deserializeNamespaced(list.getString(i)); -+ if (namespaced == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(namespaced); -+ } -+ } -+ // Paper end - - Set keys = tag.getKeys(); - for (String key : keys) { -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - setDamage(damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ Iterable canPlaceOnSerialized = SerializableMeta.getObject(Iterable.class, map, CAN_PLACE_ON.BUKKIT, true); -+ if (canPlaceOnSerialized != null) { -+ for (Object canPlaceOnElement : canPlaceOnSerialized) { -+ String canPlaceOnRaw = (String) canPlaceOnElement; -+ Namespaced value = this.deserializeNamespaced(canPlaceOnRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.placeableKeys.add(value); -+ } -+ } -+ -+ Iterable canDestroySerialized = SerializableMeta.getObject(Iterable.class, map, CAN_DESTROY.BUKKIT, true); -+ if (canDestroySerialized != null) { -+ for (Object canDestroyElement : canDestroySerialized) { -+ String canDestroyRaw = (String) canDestroyElement; -+ Namespaced value = this.deserializeNamespaced(canDestroyRaw); -+ if (value == null) { -+ continue; -+ } -+ -+ this.destroyableKeys.add(value); -+ } -+ } -+ // Paper end -+ - String internal = SerializableMeta.getString(map, "internal", true); - if (internal != null) { - ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(internal)); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (hasDamage()) { - itemTag.setInt(DAMAGE.NBT, damage); - } -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List items = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.set(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List items = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ itemTag.set(CAN_DESTROY.NBT, createNonComponentStringList(items)); -+ } -+ // Paper end - - for (Map.Entry e : unhandledTags.entrySet()) { - itemTag.set(e.getKey(), e.getValue()); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // Paper start -+ static NBTTagList createNonComponentStringList(List list) { -+ if (list == null || list.isEmpty()) { -+ return null; -+ } -+ -+ NBTTagList tagList = new NBTTagList(); -+ for (String value : list) { -+ tagList.add(NBTTagString.a(value)); // Paper - NBTTagString.of(String str) -+ } -+ -+ return tagList; -+ } -+ // Paper end -+ - NBTTagList createStringList(List list) { - if (list == null) { - return null; -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - - @Overridden - boolean isEmpty() { -- return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers()); -+ return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || (lore != null) || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers() || hasPlaceableKeys() || hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values - } - - // Paper start -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hideFlag == that.hideFlag) - && (this.isUnbreakable() == that.isUnbreakable()) - && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -- && (this.version == that.version); -+ && (this.version == that.version) -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ && (this.hasPlaceableKeys() ? that.hasPlaceableKeys() && this.placeableKeys.equals(that.placeableKeys) : !that.hasPlaceableKeys()) -+ && (this.hasDestroyableKeys() ? that.hasDestroyableKeys() && this.destroyableKeys.equals(that.destroyableKeys) : !that.hasDestroyableKeys()); -+ // Paper end - } - - /** -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (hasDamage() ? this.damage : 0); - hash = 61 * hash + (hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); - hash = 61 * hash + version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ hash = 61 * hash + (hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); -+ hash = 61 * hash + (hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); -+ // Paper end - return hash; - } - -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - clone.unbreakable = this.unbreakable; - clone.damage = this.damage; - clone.version = this.version; -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (this.placeableKeys != null) { -+ clone.placeableKeys = Sets.newHashSet(this.placeableKeys); -+ } -+ if (this.destroyableKeys != null) { -+ clone.destroyableKeys = Sets.newHashSet(this.destroyableKeys); -+ } -+ // Paper end - return clone; - } catch (CloneNotSupportedException e) { - throw new Error(e); -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - builder.put(DAMAGE.BUKKIT, damage); - } - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { -+ List cerealPlaceable = this.placeableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); -+ } -+ -+ if (hasDestroyableKeys()) { -+ List cerealDestroyable = this.destroyableKeys.stream() -+ .map(this::serializeNamespaced) -+ .collect(java.util.stream.Collectors.toList()); -+ -+ builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); -+ } -+ // Paper end -+ - final Map internalTags = new HashMap(unhandledTags); - serializeInternal(internalTags); - if (!internalTags.isEmpty()) { -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - CraftMetaArmorStand.SHOW_ARMS.NBT, - CraftMetaArmorStand.SMALL.NBT, - CraftMetaArmorStand.MARKER.NBT, -+ CAN_DESTROY.NBT, -+ CAN_PLACE_ON.NBT, - // Paper end - CraftMetaCompass.LODESTONE_DIMENSION.NBT, - CraftMetaCompass.LODESTONE_POS.NBT, -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - // Paper end - -+ // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanDestroy() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.destroyableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanDestroy(Set canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.destroyableKeys, canDestroy); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public Set getCanPlaceOn() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : legacyGetMatsFromKeys(this.placeableKeys); -+ } -+ -+ @Override -+ @SuppressWarnings("deprecation") -+ public void setCanPlaceOn(Set canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null set!"); -+ legacyClearAndReplaceKeys(this.placeableKeys, canPlaceOn); -+ } -+ -+ @Override -+ public Set getDestroyableKeys() { -+ return !hasDestroyableKeys() ? Collections.emptySet() : Sets.newHashSet(this.destroyableKeys); -+ } -+ -+ @Override -+ public void setDestroyableKeys(Collection canDestroy) { -+ Validate.notNull(canDestroy, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.destroyableKeys.clear(); -+ this.destroyableKeys.addAll(canDestroy); -+ } -+ -+ @Override -+ public Set getPlaceableKeys() { -+ return !hasPlaceableKeys() ? Collections.emptySet() : Sets.newHashSet(this.placeableKeys); -+ } -+ -+ @Override -+ public void setPlaceableKeys(Collection canPlaceOn) { -+ Validate.notNull(canPlaceOn, "Cannot replace with null collection!"); -+ Validate.isTrue(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); -+ this.placeableKeys.clear(); -+ this.placeableKeys.addAll(canPlaceOn); -+ } -+ -+ @Override -+ public boolean hasPlaceableKeys() { -+ return this.placeableKeys != null && !this.placeableKeys.isEmpty(); -+ } -+ -+ @Override -+ public boolean hasDestroyableKeys() { -+ return this.destroyableKeys != null && !this.destroyableKeys.isEmpty(); -+ } -+ -+ @Deprecated -+ private void legacyClearAndReplaceKeys(Collection toUpdate, Collection beingSet) { -+ if (beingSet.stream().anyMatch(Material::isLegacy)) { -+ throw new IllegalArgumentException("Set must not contain any legacy materials!"); -+ } -+ -+ toUpdate.clear(); -+ toUpdate.addAll(beingSet.stream().map(Material::getKey).collect(java.util.stream.Collectors.toSet())); -+ } -+ -+ @Deprecated -+ private Set legacyGetMatsFromKeys(Collection names) { -+ Set mats = Sets.newHashSet(); -+ for (Namespaced key : names) { -+ if (!(key instanceof org.bukkit.NamespacedKey)) { -+ continue; -+ } -+ -+ Material material = Material.matchMaterial(key.toString(), false); -+ if (material != null) { -+ mats.add(material); -+ } -+ } -+ -+ return mats; -+ } -+ -+ private @Nullable Namespaced deserializeNamespaced(String raw) { -+ boolean isTag = raw.length() > 0 && raw.codePointAt(0) == '#'; -+ ArgumentBlock blockParser = new ArgumentBlock(new com.mojang.brigadier.StringReader(raw), true); -+ try { -+ blockParser = blockParser.parse(false); -+ } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { -+ e.printStackTrace(); -+ return null; -+ } -+ -+ MinecraftKey key; -+ if (isTag) { -+ key = blockParser.getTagKey(); -+ } else { -+ key = blockParser.getBlockKey(); -+ } -+ -+ if (key == null) { -+ return null; -+ } -+ -+ // don't DC the player if something slips through somehow -+ Namespaced resource = null; -+ try { -+ if (isTag) { -+ resource = new NamespacedTag(key.getNamespace(), key.getKey()); -+ } else { -+ resource = CraftNamespacedKey.fromMinecraft(key); -+ } -+ } catch (IllegalArgumentException ex) { -+ org.bukkit.Bukkit.getLogger().warning("Namespaced resource does not validate: " + key.toString()); -+ ex.printStackTrace(); -+ } -+ -+ return resource; -+ } -+ -+ private @Nonnull String serializeNamespaced(Namespaced resource) { -+ return resource.toString(); -+ } -+ -+ // not a fan of this -+ private boolean ofAcceptableType(Collection namespacedResources) { -+ -+ for (Namespaced resource : namespacedResources) { -+ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Implement-ensureServerConversions-API.patch b/Spigot-Server-Patches/Implement-ensureServerConversions-API.patch deleted file mode 100644 index d45cbbe21a..0000000000 --- a/Spigot-Server-Patches/Implement-ensureServerConversions-API.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 22:43:12 -0400 -Subject: [PATCH] Implement ensureServerConversions API - -This will take a Bukkit ItemStack and run it through any conversions a server process would perform on it, -to ensure it meets latest minecraft expectations. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory { - public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { - return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).displayName()); - } -+ -+ // Paper start -+ @Override -+ public ItemStack ensureServerConversions(ItemStack item) { -+ return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch b/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch deleted file mode 100644 index 99abd416e6..0000000000 --- a/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 15:56:26 +0200 -Subject: [PATCH] Implement extended PaperServerListPingEvent - - -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperServerListPingEventImpl.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; -+import org.bukkit.entity.Player; -+import org.bukkit.util.CachedServerIcon; -+ -+import javax.annotation.Nullable; -+ -+class PaperServerListPingEventImpl extends PaperServerListPingEvent { -+ -+ private final MinecraftServer server; -+ -+ PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { -+ super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), -+ server.getServerModName() + ' ' + server.getVersion(), protocolVersion, icon); -+ this.server = server; -+ } -+ -+ @Override -+ protected final Object[] getOnlinePlayers() { -+ return this.server.getPlayerList().players.toArray(); -+ } -+ -+ @Override -+ protected final Player getBukkitPlayer(Object player) { -+ return ((EntityPlayer) player).getBukkitEntity(); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/PaperStatusClient.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.network; -+ -+import net.minecraft.network.NetworkManager; -+ -+class PaperStatusClient extends PaperNetworkClient implements StatusClient { -+ -+ PaperStatusClient(NetworkManager networkManager) { -+ super(networkManager); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.network; -+ -+import com.destroystokyo.paper.profile.CraftPlayerProfile; -+import com.destroystokyo.paper.profile.PlayerProfile; -+import com.google.common.base.MoreObjects; -+import com.google.common.base.Strings; -+import com.mojang.authlib.GameProfile; -+import io.papermc.paper.adventure.AdventureComponent; -+import java.util.List; -+import java.util.UUID; -+import javax.annotation.Nonnull; -+import net.minecraft.network.NetworkManager; -+import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; -+import net.minecraft.network.protocol.status.ServerPing; -+import net.minecraft.server.MinecraftServer; -+ -+public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { -+ -+ private static final GameProfile[] EMPTY_PROFILES = new GameProfile[0]; -+ private static final UUID FAKE_UUID = new UUID(0, 0); -+ -+ private GameProfile[] originalSample; -+ -+ private StandardPaperServerListPingEventImpl(MinecraftServer server, NetworkManager networkManager, ServerPing ping) { -+ super(server, new PaperStatusClient(networkManager), ping.getServerData() != null ? ping.getServerData().getProtocolVersion() : -1, server.server.getServerIcon()); -+ this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE -+ } -+ -+ @Nonnull -+ @Override -+ public List getPlayerSample() { -+ List sample = super.getPlayerSample(); -+ -+ if (this.originalSample != null) { -+ for (GameProfile profile : this.originalSample) { -+ sample.add(CraftPlayerProfile.asBukkitCopy(profile)); -+ } -+ this.originalSample = null; -+ } -+ -+ return sample; -+ } -+ -+ private GameProfile[] getPlayerSampleHandle() { -+ if (this.originalSample != null) { -+ return this.originalSample; -+ } -+ -+ List entries = super.getPlayerSample(); -+ if (entries.isEmpty()) { -+ return EMPTY_PROFILES; -+ } -+ -+ GameProfile[] profiles = new GameProfile[entries.size()]; -+ for (int i = 0; i < profiles.length; i++) { -+ /* -+ * Avoid null UUIDs/names since that will make the response invalid -+ * on the client. -+ * Instead, fall back to a fake/empty UUID and an empty string as name. -+ * This can be used to create custom lines in the player list that do not -+ * refer to a specific player. -+ */ -+ -+ PlayerProfile profile = entries.get(i); -+ if (profile.getId() != null && profile.getName() != null) { -+ profiles[i] = CraftPlayerProfile.asAuthlib(profile); -+ } else { -+ profiles[i] = new GameProfile(MoreObjects.firstNonNull(profile.getId(), FAKE_UUID), Strings.nullToEmpty(profile.getName())); -+ } -+ } -+ -+ return profiles; -+ } -+ -+ @SuppressWarnings("deprecation") -+ public static void processRequest(MinecraftServer server, NetworkManager networkManager) { -+ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getServerPing()); -+ server.server.getPluginManager().callEvent(event); -+ -+ // Close connection immediately if event is cancelled -+ if (event.isCancelled()) { -+ networkManager.close(null); -+ return; -+ } -+ -+ // Setup response -+ ServerPing ping = new ServerPing(); -+ -+ // Description -+ ping.setMOTD(new AdventureComponent(event.motd())); -+ -+ // Players -+ if (!event.shouldHidePlayers()) { -+ ping.setPlayerSample(new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), event.getNumPlayers())); -+ ping.getPlayers().setSample(event.getPlayerSampleHandle()); -+ } -+ -+ // Version -+ ping.setServerInfo(new ServerPing.ServerData(event.getVersion(), event.getProtocolVersion())); -+ -+ // Favicon -+ if (event.getServerIcon() != null) { -+ ping.setFavicon(event.getServerIcon().getData()); -+ } -+ -+ // Send response -+ networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -+++ b/src/main/java/net/minecraft/network/protocol/status/PacketStatusOutServerInfo.java -@@ -0,0 +0,0 @@ package net.minecraft.network.protocol.status; - - import com.google.gson.Gson; - import com.google.gson.GsonBuilder; -+import io.papermc.paper.adventure.AdventureComponent; // Paper - import java.io.IOException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.chat.ChatModifier; -@@ -0,0 +0,0 @@ import net.minecraft.util.ChatTypeAdapterFactory; - - public class PacketStatusOutServerInfo implements Packet { - -- private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()).create(); -+ private static final Gson a = (new GsonBuilder()).registerTypeAdapter(ServerPing.ServerData.class, new ServerPing.ServerData.Serializer()).registerTypeAdapter(ServerPing.ServerPingPlayerSample.class, new ServerPing.ServerPingPlayerSample.Serializer()).registerTypeAdapter(ServerPing.class, new ServerPing.Serializer()).registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()).registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()).registerTypeAdapterFactory(new ChatTypeAdapterFactory()) -+ .registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()) -+ .create(); - private ServerPing b; - - public PacketStatusOutServerInfo() {} -diff --git a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -+++ b/src/main/java/net/minecraft/network/protocol/status/ServerPing.java -@@ -0,0 +0,0 @@ public class ServerPing { - this.a = ichatbasecomponent; - } - -+ public ServerPingPlayerSample getPlayers() { return b(); } // Paper - OBFHELPER - public ServerPing.ServerPingPlayerSample b() { - return this.b; - } -@@ -0,0 +0,0 @@ public class ServerPing { - return this.b; - } - -+ public GameProfile[] getSample() { return c(); } // Paper - OBFHELPER - public GameProfile[] c() { - return this.c; - } - -+ public void setSample(GameProfile[] sample) { a(sample); } // Paper - OBFHELPER - public void a(GameProfile[] agameprofile) { - this.c = agameprofile; - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ package net.minecraft.server; - - import com.google.common.base.Splitter; - import com.google.common.collect.ImmutableList; -+import co.aikar.timings.Timings; -+import com.destroystokyo.paper.event.server.PaperServerListPingEvent; -+import com.google.common.base.Stopwatch; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= 5000000000L) { - this.T = i; - this.serverPing.setPlayerSample(new ServerPing.ServerPingPlayerSample(this.getMaxPlayers(), this.getPlayerCount())); -- GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), 12)]; -+ GameProfile[] agameprofile = new GameProfile[Math.min(this.getPlayerCount(), org.spigotmc.SpigotConfig.playerSample)]; // Paper - int j = MathHelper.nextInt(this.r, 0, this.getPlayerCount() - agameprofile.length); - - for (int k = 0; k < agameprofile.length; ++k) { -diff --git a/src/main/java/net/minecraft/server/network/PacketStatusListener.java b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PacketStatusListener.java -+++ b/src/main/java/net/minecraft/server/network/PacketStatusListener.java -@@ -0,0 +0,0 @@ public class PacketStatusListener implements PacketStatusInListener { - this.networkManager.close(PacketStatusListener.a); - } else { - this.d = true; -+ // Paper start - Replace everything -+ /* - // CraftBukkit start - // this.networkManager.sendPacket(new PacketStatusOutServerInfo(this.minecraftServer.getServerPing())); - final Object[] players = minecraftServer.getPlayerList().players.toArray(); -@@ -0,0 +0,0 @@ public class PacketStatusListener implements PacketStatusInListener { - ping.setServerInfo(new ServerPing.ServerData(minecraftServer.getServerModName() + " " + minecraftServer.getVersion(), version)); - - this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); -+ */ -+ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.minecraftServer, this.networkManager); -+ // Paper end - } - // CraftBukkit end - } -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -0,0 +0,0 @@ public class SpigotConfig - public static int playerSample; - private static void playerSample() - { -- playerSample = getInt( "settings.sample-count", 12 ); -+ playerSample = Math.max( getInt( "settings.sample-count", 12 ), 0 ); // Paper - Avoid negative counts - Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger - } - diff --git a/Spigot-Server-Patches/Implement-furnace-cook-speed-multiplier-API.patch b/Spigot-Server-Patches/Implement-furnace-cook-speed-multiplier-API.patch deleted file mode 100644 index 6ab78f1b46..0000000000 --- a/Spigot-Server-Patches/Implement-furnace-cook-speed-multiplier-API.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Tassu -Date: Thu, 13 Sep 2018 08:45:21 +0300 -Subject: [PATCH] Implement furnace cook speed multiplier API - -Signed-off-by: Tassu - -Fixed an issue where a furnace's cook-speed multiplier rounds down -to the nearest Integer when updating its current cook time. - -Modified by: Eric Su - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.phys.Vec3D; - - // CraftBukkit start -+import java.util.List; - import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.craftbukkit.inventory.CraftItemStack; -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - protected NonNullList items; - public int burnTime; - private int ticksForCurrentFuel; -+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API - public int cookTime; - public int cookTimeTotal; - protected final IContainerProperties b; -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - this.n.put(new MinecraftKey(s), nbttagcompound1.getInt(s)); - } - -+ // Paper start - cook speed API -+ if (nbttagcompound.hasKey("Paper.CookSpeedMultiplier")) { -+ this.cookSpeedMultiplier = nbttagcompound.getDouble("Paper.CookSpeedMultiplier"); -+ } -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - nbttagcompound.setShort("BurnTime", (short) this.burnTime); - nbttagcompound.setShort("CookTime", (short) this.cookTime); - nbttagcompound.setShort("CookTimeTotal", (short) this.cookTimeTotal); -+ nbttagcompound.setDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API - ContainerUtil.a(nbttagcompound, this.items); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - - if (this.isBurning() && this.canBurn(irecipe)) { - ++this.cookTime; -- if (this.cookTime == this.cookTimeTotal) { -+ if (this.cookTime >= this.cookTimeTotal) { // Paper - cook speed multiplier API - this.cookTime = 0; - this.cookTimeTotal = this.getRecipeCookingTime(); - this.burn(irecipe); -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - } - } - -- protected int getRecipeCookingTime() { -- return (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ // Paper begin - Expose this function so CraftFurnace can correctly scale the total cooking time to a new multiplier -+ public int getRecipeCookingTime() { -+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ -+ int cookTime = (this.hasWorld()) ? (Integer) this.world.getCraftingManager().craft((Recipes) this.c, this, this.world).map(RecipeCooking::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail -+ return (int) Math.ceil (cookTime / this.cookSpeedMultiplier); - } -+ // Paper end - - public static boolean isFuel(ItemStack itemstack) { - return f().containsKey(itemstack.getItem()); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java -@@ -0,0 +0,0 @@ public abstract class CraftFurnace extends CraftCon - public void setCookTimeTotal(int cookTimeTotal) { - this.getSnapshot().cookTimeTotal = cookTimeTotal; - } -+ -+ // Paper start - cook speed multiplier API -+ @Override -+ public double getCookSpeedMultiplier() { -+ return this.getSnapshot().cookSpeedMultiplier; -+ } -+ -+ @Override -+ public void setCookSpeedMultiplier(double multiplier) { -+ com.google.common.base.Preconditions.checkArgument(multiplier >= 0, "Furnace speed multiplier cannot be negative"); -+ com.google.common.base.Preconditions.checkArgument(multiplier <= 200, "Furnace speed multiplier cannot more than 200"); -+ T snapshot = this.getSnapshot(); -+ snapshot.cookSpeedMultiplier = multiplier; -+ snapshot.cookTimeTotal = snapshot.getRecipeCookingTime(); // Update the snapshot's current total cook time to scale with the newly set multiplier -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Implement-getI18NDisplayName.patch b/Spigot-Server-Patches/Implement-getI18NDisplayName.patch deleted file mode 100644 index 9990e53298..0000000000 --- a/Spigot-Server-Patches/Implement-getI18NDisplayName.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 May 2016 23:59:38 -0400 -Subject: [PATCH] Implement getI18NDisplayName - -Gets the Display name as seen in the Client. -Currently the server only supports the English language. To override this, -You must replace the language file embedded in the server jar. - -diff --git a/src/main/java/net/minecraft/locale/LocaleLanguage.java b/src/main/java/net/minecraft/locale/LocaleLanguage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/locale/LocaleLanguage.java -+++ b/src/main/java/net/minecraft/locale/LocaleLanguage.java -@@ -0,0 +0,0 @@ public abstract class LocaleLanguage { - - private static LocaleLanguage c() { - Builder builder = ImmutableMap.builder(); -- BiConsumer biconsumer = builder::put; -+ BiConsumer biconsumer = builder::put; // Paper - decompile fix - - try { - InputStream inputstream = LocaleLanguage.class.getResourceAsStream("/assets/minecraft/lang/en_us.json"); -@@ -0,0 +0,0 @@ public abstract class LocaleLanguage { - - } - -+ public static LocaleLanguage getInstance() { return a(); } // Paper - OBFHELPER - public static LocaleLanguage a() { - return LocaleLanguage.d; - } - -+ public String translateKey(String key) { return a(key); } // Paper - OBFHELPER - public abstract String a(String s); - - public abstract boolean b(String s); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -@@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory { - public ItemStack ensureServerConversions(ItemStack item) { - return CraftItemStack.asCraftMirror(CraftItemStack.asNMSCopy(item)); - } -+ -+ @Override -+ public String getI18NDisplayName(ItemStack item) { -+ net.minecraft.world.item.ItemStack nms = null; -+ if (item instanceof CraftItemStack) { -+ nms = ((CraftItemStack) item).handle; -+ } -+ if (nms == null) { -+ nms = CraftItemStack.asNMSCopy(item); -+ } -+ -+ return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch b/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch deleted file mode 100644 index 6faedaa799..0000000000 --- a/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Sat, 24 Apr 2021 02:09:32 -0700 -Subject: [PATCH] Implement methods to convert between Component and - Brigadier's Message - - -diff --git a/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/brigadier/PaperBrigadierProviderImpl.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.brigadier; -+ -+import com.mojang.brigadier.Message; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.ComponentLike; -+import net.minecraft.network.chat.ChatComponentUtils; -+import org.checkerframework.checker.nullness.qual.NonNull; -+ -+import static java.util.Objects.requireNonNull; -+ -+public enum PaperBrigadierProviderImpl implements PaperBrigadierProvider { -+ INSTANCE; -+ -+ PaperBrigadierProviderImpl() { -+ PaperBrigadierProvider.initialize(this); -+ } -+ -+ @Override -+ public @NonNull Message message(final @NonNull ComponentLike componentLike) { -+ requireNonNull(componentLike, "componentLike"); -+ return PaperAdventure.asVanilla(componentLike.asComponent()); -+ } -+ -+ @Override -+ public @NonNull Component componentFromMessage(final @NonNull Message message) { -+ requireNonNull(message, "message"); -+ return PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(message)); -+ } -+} -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 IMinecraftServer - } - com.destroystokyo.paper.PaperConfig.registerCommands(); - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now -+ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider - // Paper end - - this.setPVP(dedicatedserverproperties.pvp); diff --git a/Spigot-Server-Patches/Implemented-BlockFailedDispenseEvent.patch b/Spigot-Server-Patches/Implemented-BlockFailedDispenseEvent.patch deleted file mode 100644 index 5f1cd02f52..0000000000 --- a/Spigot-Server-Patches/Implemented-BlockFailedDispenseEvent.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheViperShow <29604693+TheViperShow@users.noreply.github.com> -Date: Wed, 22 Apr 2020 09:40:38 +0200 -Subject: [PATCH] Implemented BlockFailedDispenseEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDispenser.java -@@ -0,0 +0,0 @@ public class BlockDispenser extends BlockTileEntity { - int i = tileentitydispenser.h(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here - worldserver.triggerEffect(1001, blockposition, 0); - } else { - ItemStack itemstack = tileentitydispenser.getItem(i); -diff --git a/src/main/java/net/minecraft/world/level/block/BlockDropper.java b/src/main/java/net/minecraft/world/level/block/BlockDropper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockDropper.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockDropper.java -@@ -0,0 +0,0 @@ public class BlockDropper extends BlockDispenser { - int i = tileentitydispenser.h(); - - if (i < 0) { -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(worldserver, blockposition)) // Paper - BlockFailedDispenseEvent is called here - worldserver.triggerEffect(1001, blockposition, 0); - } else { - ItemStack itemstack = tileentitydispenser.getItem(i); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ import com.google.common.base.Function; - import com.google.common.base.Functions; - import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Either; -+import io.papermc.paper.event.block.BlockFailedDispenseEvent; - import java.net.InetAddress; - import java.util.ArrayList; - import java.util.Collections; -@@ -0,0 +0,0 @@ import org.bukkit.entity.ThrownPotion; - import org.bukkit.entity.Vehicle; - import org.bukkit.entity.Villager; - import org.bukkit.entity.Villager.Profession; --import org.bukkit.entity.ExperienceOrb; // Paper - import org.bukkit.event.Cancellable; - import org.bukkit.event.Event; - import org.bukkit.event.Event.Result; -@@ -0,0 +0,0 @@ public class CraftEventFactory { - Bukkit.getPluginManager().callEvent(event); - return event; - } -+ -+ // Paper start -+ public static boolean handleBlockFailedDispenseEvent(WorldServer worldserver, BlockPosition blockposition) { -+ org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ BlockFailedDispenseEvent event = new BlockFailedDispenseEvent(block); -+ return event.callEvent(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Import-fastutil-classes.patch b/Spigot-Server-Patches/Import-fastutil-classes.patch deleted file mode 100644 index 67ca893d47..0000000000 --- a/Spigot-Server-Patches/Import-fastutil-classes.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 12 Aug 2020 11:33:04 +0200 -Subject: [PATCH] Import fastutil classes - - -diff --git a/src/main/java/net/minecraft/network/syncher/DataWatcher.java b/src/main/java/net/minecraft/network/syncher/DataWatcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/syncher/DataWatcher.java -+++ b/src/main/java/net/minecraft/network/syncher/DataWatcher.java -@@ -0,0 +0,0 @@ import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.world.entity.Entity; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper - import org.apache.commons.lang3.ObjectUtils; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -0,0 +0,0 @@ public class DataWatcher { - private static final Logger LOGGER = LogManager.getLogger(); - private static final Map, Integer> b = Maps.newHashMap(); - private final Entity entity; -- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL -+ private final Int2ObjectOpenHashMap> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL - // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required - private boolean f = true; - private boolean g; diff --git a/Spigot-Server-Patches/Improve-BlockPosition-inlining.patch b/Spigot-Server-Patches/Improve-BlockPosition-inlining.patch deleted file mode 100644 index b4f67f97ea..0000000000 --- a/Spigot-Server-Patches/Improve-BlockPosition-inlining.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 30 Nov 2016 20:56:58 -0600 -Subject: [PATCH] Improve BlockPosition inlining - -Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. -If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. -But if two types are encountered commonly, then the JVM can't inline them both, and the call overhead remains. - -This scenario also occurs with BlockPos and MutableBlockPos. -The variables in BlockPos are final, so MutableBlockPos can't modify them. -MutableBlockPos fixes this by adding custom mutable variables, and overriding the getters to access them. - -This approach with utility methods that operate on MutableBlockPos and BlockPos. -Specific examples are BlockPosition.up(), and World.isValidLocation(). -It makes these simple methods much slower than they need to be. - -This should result in an across the board speedup in anything that accesses blocks or does logic with positions. - -This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. -They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. - -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -0,0 +0,0 @@ public class BaseBlockPosition implements Comparable { - this(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } - -- public boolean equals(Object object) { -+ public final boolean equals(Object object) { // Paper - if (this == object) { - return true; - } else if (!(object instanceof BaseBlockPosition)) { -@@ -0,0 +0,0 @@ public class BaseBlockPosition implements Comparable { - } - } - -- public int hashCode() { -+ public final int hashCode() { // Paper - return (this.getY() + this.getZ() * 31) * 31 + this.getX(); - } - -@@ -0,0 +0,0 @@ public class BaseBlockPosition implements Comparable { - return this.getY() == baseblockposition.getY() ? (this.getZ() == baseblockposition.getZ() ? this.getX() - baseblockposition.getX() : this.getZ() - baseblockposition.getZ()) : this.getY() - baseblockposition.getY(); - } - -- public int getX() { -+ public final int getX() { // Paper - return this.a; - } - -- public int getY() { -+ public final int getY() { // Paper - return this.b; - } - -- public int getZ() { -+ public final int getZ() { // Paper - return this.e; - } - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - return a(this.getX(), this.getY(), this.getZ()); - } - -+ public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER - public static long a(int i, int j, int k) { - long l = 0L; - diff --git a/Spigot-Server-Patches/Improve-Chunk-Status-Transition-Speed.patch b/Spigot-Server-Patches/Improve-Chunk-Status-Transition-Speed.patch deleted file mode 100644 index 9f76c26f75..0000000000 --- a/Spigot-Server-Patches/Improve-Chunk-Status-Transition-Speed.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 23:32:14 -0400 -Subject: [PATCH] Improve Chunk Status Transition Speed - -When a chunk is loaded from disk that has already been generated, -the server has to promote the chunk through the system to reach -it's current desired status level. - -This results in every single status transition going from the main thread -to the world gen threads, only to discover it has no work it actually -needs to do.... and then it returns back to main. - -This back and forth costs a lot of time and can really delay chunk loads -when the server is under high TPS due to their being a lot of time in -between chunk load times, as well as hogs up the chunk threads from doing -actual generation and light work. - -Additionally, the whole task system uses a lot of CPU on the server threads anyways. - -So by optimizing status transitions for status's that are already complete, -we can run them to the desired level while on main thread (where it has -to happen anyways) instead of ever jumping to world gen thread. - -This will improve chunk loading effeciency to be reduced down to the following -scenario / path: - -1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue -2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread -3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue -4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks) -5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task -6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done -7) MAIN: Task returns to main, finish processing to FULL/TICKING status - -Previously would have hopped to SERVER around 12+ times there extra. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); - } - // Paper end - optimise isOutsideOfRange -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ public boolean canAdvanceStatus() { -+ ChunkStatus status = getChunkHolderStatus(); -+ IChunkAccess chunk = getAvailableChunkNow(); -+ return chunk != null && (status == null || chunk.getChunkStatus().isAtLeastStatus(getNextStatus(status))); -+ } -+ // Paper end - - // Paper start - no-tick view distance - public final Chunk getSendingChunk() { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return either.mapLeft((list) -> { - return (Chunk) list.get(list.size() / 2); - }); -- }, this.executor); -+ }, this.mainInvokingExecutor); // Paper - } - - @Nullable -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - IChunkAccess ichunkaccess = (IChunkAccess) optional.get(); - - if (ichunkaccess.getChunkStatus().b(chunkstatus)) { -- CompletableFuture completablefuture1; -+ CompletableFuture> completablefuture1; // Paper - - if (chunkstatus == ChunkStatus.LIGHT) { - completablefuture1 = this.b(playerchunk, chunkstatus); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return this.b(playerchunk, chunkstatus); - } - } -- }, this.executor); -+ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main - } - } - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return CompletableFuture.completedFuture(Either.right(playerchunk_failure)); - }); - }, (runnable) -> { -+ // Paper start - optimize chunk status progression without jumping through thread pool -+ if (playerchunk.canAdvanceStatus()) { -+ this.mainInvokingExecutor.execute(runnable); -+ return; -+ } -+ // Paper end - this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); - }); - } diff --git a/Spigot-Server-Patches/Improve-EntityShootBowEvent.patch b/Spigot-Server-Patches/Improve-EntityShootBowEvent.patch deleted file mode 100644 index 2759a893a3..0000000000 --- a/Spigot-Server-Patches/Improve-EntityShootBowEvent.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 15 Jun 2013 19:51:17 -0400 -Subject: [PATCH] Improve EntityShootBowEvent - -Adds missing call to Illagers and also adds Arrow ItemStack to skeltons - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityIllagerIllusioner.java -@@ -0,0 +0,0 @@ public class EntityIllagerIllusioner extends EntityIllagerWizard implements IRan - double d3 = (double) MathHelper.sqrt(d0 * d0 + d2 * d2); - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); -+ // Paper start -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, entityliving.getRaisedHand(), 0.8F, true); -+ if (event.isCancelled()) { -+ event.getProjectile().remove(); -+ return; -+ } -+ -+ if (event.getProjectile() == entityarrow.getBukkitEntity()) { -+ this.world.addEntity(entityarrow); -+ } - this.playSound(SoundEffects.ENTITY_SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); -- this.world.addEntity(entityarrow); -+ // Paper end - } - - class a extends EntityIllagerWizard.PathfinderGoalCastSpell { -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySkeletonAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntitySkeletonAbstract extends EntityMonster implements IR - - entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.world.getDifficulty().a() * 4)); - // CraftBukkit start -- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entityarrow.getOriginalItemStack(), entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); // Paper - if (event.isCancelled()) { - event.getProjectile().remove(); - return; diff --git a/Spigot-Server-Patches/Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/Spigot-Server-Patches/Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch deleted file mode 100644 index 13b95abc78..0000000000 --- a/Spigot-Server-Patches/Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 3 Jul 2020 15:03:33 -0700 -Subject: [PATCH] Improve EntityTargetLivingEntityEvent for 1.16 mobs - -CraftBukkit has a bug in their implementation and is incorrectly handling forget -Also adds more target reasons for why it forgot target. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorAttackTargetForget.java -@@ -0,0 +0,0 @@ public class BehaviorAttackTargetForget extends Beha - - protected void a(WorldServer worldserver, E e0, long i) { - if (a((EntityLiving) e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper - } else if (this.c(e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper - } else if (this.a(e0)) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper - } else if (!IEntitySelector.f.test(this.b(e0))) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } else if (this.b.test(this.b(e0))) { -- this.d(e0); -+ this.d(e0, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper - } - } - -@@ -0,0 +0,0 @@ public class BehaviorAttackTargetForget extends Beha - return optional.isPresent() && !((EntityLiving) optional.get()).isAlive(); - } - -- private void d(E e0) { -+ private void d(E e0, EntityTargetEvent.TargetReason reason) { - // CraftBukkit start -- EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, (old != null && !old.isAlive()) ? EntityTargetEvent.TargetReason.TARGET_DIED : EntityTargetEvent.TargetReason.FORGOT_TARGET); -+ // Paper start - fix this event -+ //EntityLiving old = e0.getBehaviorController().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); -+ EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(e0, null, reason); - if (event.isCancelled()) { - return; - } -- if (event.getTarget() != null) { -+ // comment out, bad logic - bad -+ /*if (event.getTarget() != null) { - e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); - return; -- } -+ }*/ -+ // Paper end - // CraftBukkit end - e0.getBehaviorController().removeMemory(MemoryModuleType.ATTACK_TARGET); - } diff --git a/Spigot-Server-Patches/Improve-Legacy-Component-serialization-size.patch b/Spigot-Server-Patches/Improve-Legacy-Component-serialization-size.patch deleted file mode 100644 index 004a3e112b..0000000000 --- a/Spigot-Server-Patches/Improve-Legacy-Component-serialization-size.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:08:41 -0400 -Subject: [PATCH] Improve Legacy Component serialization size - -Don't constantly send format: false for all formatting options when parent already -has it false - -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -0,0 +0,0 @@ public final class CraftChatMessage { - // Separate pattern with no group 3, new lines are part of previous string - private static final Pattern INCREMENTAL_PATTERN_KEEP_NEWLINES = Pattern.compile("(" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + "[0-9a-fk-orx])|((?:(?:https?):\\/\\/)?(?:[-\\w_\\.]{2,}\\.[a-z]{2,4}.*?(?=[\\.\\?!,;:]?(?:[" + String.valueOf(org.bukkit.ChatColor.COLOR_CHAR) + " ]|$))))", Pattern.CASE_INSENSITIVE); - // ChatColor.b does not explicitly reset, its more of empty -+ private static final ChatModifier EMPTY = ChatModifier.a.setItalic(false); // Paper - OBFHELPER - private static final ChatModifier RESET = ChatModifier.a.setBold(false).setItalic(false).setUnderline(false).setStrikethrough(false).setRandom(false); - - private final List list = new ArrayList(); -@@ -0,0 +0,0 @@ public final class CraftChatMessage { - Matcher matcher = (keepNewlines ? INCREMENTAL_PATTERN_KEEP_NEWLINES : INCREMENTAL_PATTERN).matcher(message); - String match = null; - boolean needsAdd = false; -+ boolean hasReset = false; // Paper - while (matcher.find()) { - int groupId = 0; - while ((match = matcher.group(++groupId)) == null) { -@@ -0,0 +0,0 @@ public final class CraftChatMessage { - throw new AssertionError("Unexpected message format"); - } - } else { // Color resets formatting -- modifier = RESET.setColor(format); -+ // Paper start - improve legacy formatting -+ ChatModifier previous = modifier; -+ modifier = (!hasReset ? RESET : EMPTY).setColor(format); -+ hasReset = true; -+ if (previous.isBold()) { -+ modifier = modifier.setBold(false); -+ } -+ if (previous.isItalic()) { -+ modifier = modifier.setItalic(false); -+ } -+ if (previous.isRandom()) { -+ modifier = modifier.setRandom(false); -+ } -+ if (previous.isStrikethrough()) { -+ modifier = modifier.setStrikethrough(false); -+ } -+ if (previous.isUnderlined()) { -+ modifier = modifier.setUnderline(false); -+ } -+ // Paper end - } - needsAdd = true; - break; diff --git a/Spigot-Server-Patches/Improve-Log4J-Configuration-Plugin-Loggers.patch b/Spigot-Server-Patches/Improve-Log4J-Configuration-Plugin-Loggers.patch deleted file mode 100644 index 4258e756b5..0000000000 --- a/Spigot-Server-Patches/Improve-Log4J-Configuration-Plugin-Loggers.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Sat, 23 Sep 2017 21:07:20 +0200 -Subject: [PATCH] Improve Log4J Configuration / Plugin Loggers - -Add full exceptions to log4j to not truncate stack traces - -Disable logger prefix for various plugins bypassing the plugin logger - -Some plugins bypass the plugin logger and add the plugin prefix -manually to the log message. Since they use other logger names -(e.g. qualified class names) these would now also appear in the -log. Disable the logger prefix for these plugins so the messages -show up correctly. - -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -0,0 +0,0 @@ - - - -- -+ - -- -+ -+ - - - - - -- -+ - -- -+ -+ - - - diff --git a/Spigot-Server-Patches/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/Spigot-Server-Patches/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch deleted file mode 100644 index 3758276b43..0000000000 --- a/Spigot-Server-Patches/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Apr 2016 20:02:00 -0400 -Subject: [PATCH] Improve Maps (in item frames) performance and bug fixes - -Maps used a modified version of rendering to support plugin controlled -imaging on maps. The Craft Map Renderer is much slower than Vanilla, -causing maps in item frames to cause a noticeable hit on server performance. - -This updates the map system to not use the Craft system if we detect that no -custom renderers are in use, defaulting to the much simpler Vanilla system. - -Additionally, numerous issues to player position tracking on maps has been fixed. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - { - if ( iter.next().trackee == entity ) - { -+ map.decorations.remove(entity.getDisplayName().getString()); // Paper - iter.remove(); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ import net.minecraft.world.item.ItemElytra; - import net.minecraft.world.item.ItemProjectileWeapon; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.ItemSword; -+import net.minecraft.world.item.ItemWorldMap; - import net.minecraft.world.item.Items; - import net.minecraft.world.item.crafting.IRecipe; - import net.minecraft.world.item.enchantment.EnchantmentManager; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.block.entity.TileEntityStructure; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.block.state.pattern.ShapeDetectorBlock; -+import net.minecraft.world.level.saveddata.maps.WorldMap; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.Vec3D; - import net.minecraft.world.scores.Scoreboard; -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - return null; - } - // CraftBukkit end -+ // Paper start - remove player from map on drop -+ if (itemstack.getItem() == Items.FILLED_MAP) { -+ WorldMap worldmap = ItemWorldMap.getSavedMap(itemstack, this.world); -+ worldmap.updateSeenPlayers(this, itemstack); -+ } -+ // Paper end - - return entityitem; - } -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - private final Map m = Maps.newHashMap(); - public final Map decorations = Maps.newLinkedHashMap(); - private final Map n = Maps.newHashMap(); -+ private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper - - // CraftBukkit start - public final CraftMapView mapView; -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - // CraftBukkit start - mapView = new CraftMapView(this); - server = (CraftServer) org.bukkit.Bukkit.getServer(); -+ vanillaRender.buffer = colors; // Paper - // CraftBukkit end - } - -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - this.m.put(mapiconbanner.f(), mapiconbanner); - this.a(mapiconbanner.c(), (GeneratorAccess) null, mapiconbanner.f(), (double) mapiconbanner.a().getX(), (double) mapiconbanner.a().getZ(), 180.0D, mapiconbanner.d()); - } -+ this.vanillaRender.buffer = colors; // Paper - - NBTTagList nbttaglist1 = nbttagcompound.getList("frames", 10); - -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - this.b(); - } - -+ public void updateSeenPlayers(EntityHuman entityhuman, ItemStack itemstack) { this.a(entityhuman, itemstack); } // Paper - OBFHELPER - public void a(EntityHuman entityhuman, ItemStack itemstack) { - if (!this.humans.containsKey(entityhuman)) { - WorldMap.WorldMapHumanTracker worldmap_worldmaphumantracker = new WorldMap.WorldMapHumanTracker(entityhuman); -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - - public class WorldMapHumanTracker { - -+ // Paper start -+ private void addSeenPlayers(java.util.Collection icons) { -+ org.bukkit.entity.Player player = (org.bukkit.entity.Player) trackee.getBukkitEntity(); -+ WorldMap.this.decorations.forEach((name, mapIcon) -> { -+ // If this cursor is for a player check visibility with vanish system -+ org.bukkit.entity.Player other = org.bukkit.Bukkit.getPlayerExact(name); // Spigot -+ if (other == null || player.canSee(other)) { -+ icons.add(mapIcon); -+ } -+ }); -+ } -+ private boolean shouldUseVanillaMap() { -+ return mapView.getRenderers().size() == 1 && mapView.getRenderers().get(0).getClass() == org.bukkit.craftbukkit.map.CraftMapRenderer.class; -+ } -+ // Paper end - public final EntityHuman trackee; - private boolean d = true; - private int e; -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - @Nullable - public Packet a(ItemStack itemstack) { - // CraftBukkit start -- org.bukkit.craftbukkit.map.RenderData render = WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()); // CraftBukkit -+ if (!this.d && this.i % 5 != 0) { this.i++; return null; } // Paper - this won't end up sending, so don't render it! -+ boolean vanillaMaps = shouldUseVanillaMap(); // Paper -+ org.bukkit.craftbukkit.map.RenderData render = !vanillaMaps ? WorldMap.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.trackee.getBukkitEntity()) : WorldMap.this.vanillaRender; // CraftBukkit // Paper - - java.util.Collection icons = new java.util.ArrayList(); -+ if (vanillaMaps) addSeenPlayers(icons); // Paper - - for ( org.bukkit.map.MapCursor cursor : render.cursors) { - -diff --git a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -+++ b/src/main/java/org/bukkit/craftbukkit/map/RenderData.java -@@ -0,0 +0,0 @@ import org.bukkit.map.MapCursor; - - public class RenderData { - -- public final byte[] buffer; -+ public byte[] buffer; // Paper - public final ArrayList cursors; - - public RenderData() { diff --git a/Spigot-Server-Patches/Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/Spigot-Server-Patches/Improve-Server-Thread-Pool-and-Thread-Priorities.patch deleted file mode 100644 index 195e19d032..0000000000 --- a/Spigot-Server-Patches/Improve-Server-Thread-Pool-and-Thread-Priorities.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 23 Oct 2018 23:14:38 -0400 -Subject: [PATCH] Improve Server Thread Pool and Thread Priorities - -Use a simple executor since Fork join is a much more complex pool -type and we are not using its capabilities. - -Set thread priorities so main thread has above normal priority over -server threads - -Allow usage of a single thread executor by not using ForkJoin so single core CPU's. - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -0,0 +0,0 @@ import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.DispenserRegistry; -+import net.minecraft.server.ServerWorkerThread; - import net.minecraft.util.MathHelper; - import net.minecraft.util.datafix.DataConverterRegistry; - import net.minecraft.world.level.block.state.properties.IBlockState; -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - public class SystemUtils { - - private static final AtomicInteger c = new AtomicInteger(1); -- private static final ExecutorService d = a("Bootstrap"); -- private static final ExecutorService e = a("Main"); -+ private static final ExecutorService d = a("Bootstrap", -2); // Paper - add -2 priority -+ private static final ExecutorService e = a("Main", -1); // Paper - add -1 priority - private static final ExecutorService f = n(); - public static LongSupplier a = System::nanoTime; - public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER -@@ -0,0 +0,0 @@ public class SystemUtils { - return Instant.now().toEpochMilli(); - } - -- private static ExecutorService a(String s) { -- int i = MathHelper.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); -- Object object; -+ private static ExecutorService a(String s, int priorityModifier) { // Paper - add priority -+ // Paper start - use simpler thread pool that allows 1 thread -+ int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1)); -+ i = Integer.getInteger("Paper.WorkerThreadCount", i); -+ ExecutorService object; - - if (i <= 0) { - object = MoreExecutors.newDirectExecutorService(); - } else { -- object = new ForkJoinPool(i, (forkjoinpool) -> { -- ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) { -+ object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); -+ } -+ /* - protected void onTermination(Throwable throwable) { - if (throwable != null) { - SystemUtils.LOGGER.warn("{} died", this.getName(), throwable); -@@ -0,0 +0,0 @@ public class SystemUtils { - return forkjoinworkerthread; - }, SystemUtils::a, true); - } -+ }*/ // Paper end - - return (ExecutorService) object; - } -@@ -0,0 +0,0 @@ public class SystemUtils { - }); - } - -+ public static void onThreadError(Thread thread, Throwable throwable) { a(thread, throwable); } // Paper - OBFHELPER - private static void a(Thread thread, Throwable throwable) { - c(throwable); - if (throwable instanceof CompletionException) { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sat, 3 Oct 2020 08:27:40 +0200 -Subject: [PATCH] Improve ServerGUI - -- Added logo to server frame -- Show tps in the server stats - -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -0,0 +0,0 @@ public class RAMDetails extends JList { - public void update() { - GraphData data = RAMGraph.DATA.peekLast(); - Vector vector = new Vector<>(); -+ -+ double[] tps = new double[] {server.tps1.getAverage(), server.tps5.getAverage(), server.tps15.getAverage()}; -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); - vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); - vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ vector.add("TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg)); -+ - setListData(vector); - } - -@@ -0,0 +0,0 @@ public class RAMDetails extends JList { - } - return ((double) total / (double) tickTimes.length) * 1.0E-6D; - } -+ -+ private static String format(double tps) -+ { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); -+ } - } -diff --git a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -+++ b/src/main/java/net/minecraft/server/gui/GuiStatsComponent.java -@@ -0,0 +0,0 @@ public class GuiStatsComponent extends JComponent { - }); - private final int[] b = new int[256]; - private int c; -- private final String[] d = new String[11]; -+ private final String[] d = new String[12]; public String[] getStatEntries() { return this.d; } // Paper - change size, OBFHELPER - private final MinecraftServer e; - private final Timer f; - -@@ -0,0 +0,0 @@ public class GuiStatsComponent extends JComponent { - private void b() { - long i = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - -+ // Paper start - Add tps entry -+ double[] tps = org.bukkit.Bukkit.getTPS(); -+ String[] tpsAvg = new String[tps.length]; -+ -+ for ( int g = 0; g < tps.length; g++) { -+ tpsAvg[g] = format( tps[g] ); -+ } - this.d[0] = "Memory use: " + i / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; - this.d[1] = "Avg tick: " + GuiStatsComponent.a.format(this.a(this.e.h) * 1.0E-6D) + " ms"; -+ getStatEntries()[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); -+ // Paper end -+ - this.b[this.c++ & 255] = (int) (i * 100L / Runtime.getRuntime().maxMemory()); - this.repaint(); - } -@@ -0,0 +0,0 @@ public class GuiStatsComponent extends JComponent { - public void a() { - this.f.stop(); - } -+ -+ // Paper - start Add tps entry -+ private static String format(double tps) { -+ return ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/gui/ServerGUI.java -+++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java -@@ -0,0 +0,0 @@ import net.minecraft.DefaultUncaughtExceptionHandler; - import net.minecraft.server.dedicated.DedicatedServer; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+// Paper start -+import java.io.IOException; -+import java.util.Objects; -+import javax.imageio.ImageIO; -+// Paper end - - public class ServerGUI extends JComponent { - -@@ -0,0 +0,0 @@ public class ServerGUI extends JComponent { - jframe.pack(); - jframe.setLocationRelativeTo((Component) null); - jframe.setVisible(true); -+ jframe.setName("Minecraft server"); // Paper -+ -+ // Paper start - Add logo as frame image -+ try { -+ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(ServerGUI.class.getClassLoader().getResourceAsStream("logo.png")))); -+ } catch (IOException ignore) { -+ } -+ // Paper end -+ - jframe.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent windowevent) { - if (!servergui.f.getAndSet(true)) { -diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 -GIT binary patch -literal 14310 -zcmXY21yoy2uugDycPmm{N^yd_Q`}vP7YOd|PH`>8wLo!q*HRn`6f5rV?*HD)IX5{c -zxpy-=`|Zxo_svGBD$Agwkf4A-AaprdNp;|J21vifLD%hMrT$lZeEex|7Xe0mqFAZArC{!qp)zJmbab@utqA`6 -z61Z~|e!k$IbXNT?PvGuuzT7G514$8e!}lsR>%nURMm+~pde``@(!O=ISt0%B93;Ez -za-qRi4n0Q>zQ2#2^_y08QOl3jT*!Ir5@<8VrFx(6f9sP|H8ttjftN;wrX>jP4BcG1;MfU5x^L`zc09u!bDBt#+ll=7@ -zB;}A$BKgu}V?#qfHvm`~pt%wG2y{MOc%B!8I`p|pc -zO#?sq!Zd&j8UPmvY4RQnfo>!6{a}GFV!}g@qu<3Wu$07X(O`vikNW$~q!ngF23Ls2 -z53p8js<-B_Qd?xX6rtq43Mdz(jOg2QXx#Wng_9^1^^~KqFNq{Kvb@Ap9}bf&xFA-C -z5+#cQ`#v$A=kd0O=agATcleBaxXf_(dnqbQz|cL9R&&Ni1omTs+6~YApmk)MCghxj -z1}mq&IU>1nEiF=q=PI`%jQbyRd=hVI83Sm{E-4uTc#w;NNwEW)C(C`xvWzY_%`_MmO -zD&g-sEaE)}6(&g)y-N&rNy;5@+{M`}!{60Y8wMgF5;HmO#B~hG`W$;7xLG*yF((rq -zxP6I#r#o`B3FppK{v(q1!C+YLFSfySDcHyoW!}EfzuCB1B|C5+oP}dtocnwkcNy1EZ6#5JX4=ePl&cu~0tMnt&79+I4%PaK>VqFx;r!QdNmnxlEqdU-QR%Nmu{aWP -zJxwXvt5fFTCOVgB)Zq -z%H0U=9q7Y0lu&1kc4zYT3*lHA@XJfoK>3WFM&WWf2u6^+wCm8##D$x@Gkw+t^HoO( -z4pxDRqg;$5S=t^k22H5^V3V0Qfy%Ogl8I%LD$52=7)J>Ki9Ej1HyEi_ujELlz8$-+?cdD1Zxi02kW0 -zaY=caFq4~s^R?zxcc3Z0X|az}Aww<{P$>6rk+5Di5J7$kWor0{Q&>+DWSBH^Gf`SP -zT{4}IOFh-hB7xwBdewq%de)q6QvxorV(()2>@j8i!kj)=^hN -zl_N{$9xTHHA;V&Zx#tX&1pOO;v^NiOP#_UK@J;;lp+OOhOOO2mlMdxM;Qv-mWG+^vzox|8t`w| -z=gPlM3)y6G*hfV1WwuMe>bO-vP9g`h5BqgO9x{ROBD;aPl>XDmvt(3PUxt|4RFRpK -z5OEtRz{(Oa_W_!Z4XHf#h;Z-~71XM7wlF*L!-#h_Uy2tGuy-rAZ)4{qE~feNkp}qf -zgvBtLkFPI~I7%C=OHZfPZz$j>L9)rb;l -z@J^dxncy52;wmHg=wC3|Xn6jPYCR7xc}~D0wNjoYxmoRh_zh=6@8coM1UQIa_z*1)cZPw4v40qoZQp-uy#DLv=oP -zX9b3vzFA2r8}|_AO8W1(OMG__0{1AUD&Z%&7-(>s+Z-X6Sv}G5QguIbZ3mYa--?09 -z;wNw?n=yAag4%m#w$$-YZ{(ZJUcwHfzu&!gykNjG)e}!=q8xy2_KS=ULsQwv45NK! -zVqqD8#S{vRjg4(Q6HM_F&tihNIQns<%DVjE$cv33ET>Dvc^#{z&#u&&9RgXO?ZLuebczKv#;! -zCS|2lIa37Bp#3RWj0$V3=I2>o40{(J^LD|EUH?!2;Z&HS*>7*V%{v1)wHaUP85mcX -z%q!K}Ntr*IzJD%++btJ;VQO*OjJL1t{GvR3cy@OC-~pe^bV?N`z0QKCr?Tom)4u%A -z3mi2k&eIgh0^rGI#Di+&3lrsy-r+}zwBkDQtswtPbkj!Y^l`{f!# -zLseC0M;DiifDa!({-G4{W$Wxsgv*(NX%HMyXhArVwY105dUHg?+=@6Sy8n@slS76x -zU7%PI8ToKm#qahfR;7kn#|t@9y(0EkooWBDqA1(mpO)>BBz))giBi8xVHlj#dR9U8 -zRo%`iBdlj8%_tRn^qa%T>{nsLLwTNld&WHLyfbPzv2W62m6q=Nsdxnk -z#{P==5!Lidx3bcr_qlUl%BX!xjywA?jv>FU^mJDa0zQT9Kw8RRHq>7B -zb~DXw0(oqBrOQunsm2ghWV2i1VmN{F?)U;0%*j{FEUxazAJ3)KSWomuhklkDi?5h*MTLDS5ma_Nk1sNZYzZ#$maGRyiXBzjG@(G__fuyBl(^A>s&{jF+J%5| -zv#7nD1XK806#_U_4#N2ANAxznk%;U$Y$z#{K*O07mADqx6LjACqwP<`HFV#C6Q*wx -z8JVP_qGF}V7B?^8)f*2F5AON7v$L~Kr?2}oPai_kG!_6MI(U`LS~+Mo*CSyrw>pPE -zllqxy -z^&rnDn4XA@AUY7~`1lwTCrm8KlVRqX&!kZFH&;i9@=R}UDxNSh*)Iq2U+#9}@ag1t -z%KUOEw0DXT)>hQoLTprY^z=BC=8NAyi3pZWT7A`?;rI<3%65Nqb93%pJ=!+dNtB>W -z7f3O-e-S7ZBgBntcyt~wOG_p$AU2zlGH8=%TEm+z8kLYReEMTkIo#2YiA=iKWrH); -zS%uT3xAyyY=!U)0Evpgx{{38MPR2nN<3913M<0O#YCO=TSt^4IzV3^D%2zC>t_OO} -z_h~AVOk+IIi$Ov;-g93a4j@WaekCC#HFm2_Vu9s)8-GbYtr{LgrxnSIN^PW9)!jYX -z?%-yssA~&R3F)C)wj5i|@!atCx?Qy%P1QEGSZm;iUNai`-F(8a%y+_a>CMzx$XEKx -z>sW|JbN36s+Y{4SZsrspH%UH=+Q6J`c&_-JLGL&5|$XUA1vFOC+rgoc&xT{dFT&pMaEBKwyD;plX0>2nla;jTlQ{!fn2M=Ak*=K*g% -zBm0-$ly1~}CT-5gv){jex9)7&b8u!a+vYHXU>=NF2>g3+_rN{(LUMGwRWKk49sS$v -zazyX8zZ1hwZ|U*5{fK@i@hRl*U%Q2cg+!iIfb)6W%S5F{91qinEZE%~4Gl>rBw9S< -zMP5$exl1jESyt}d~jo?hf`z^32b!}UGtJH+w9(0UrI#~Ei*ii&6z(AVE?(}k_A -zE9Z@mj7HF-ch46I0ipe3gapRj{=zk_J1E^b_JwdrhKi4ytBuwP)m>e$@9v`A{1N{h -zwUN6H=_W+h(a?rGaQ%%LP5C4)XiZ*`1uUwgqWvk`LyDD!Ps#Q5oI($KDJ%8n5kBi- -zghsLx`~mf<>WT)6-cJBbp|htk1NfkZ@e#B4@l?UH7!MDMpO?1NETGk_Eg{z!N3!D< -zWg8gtgS%b(0Bg7dw9u35xq)1vNdnM8iu7Eje*u?#sZ~%^q*HDaZC?5z4ZzhSA%ndS -z4&$M&7(|(9nWY%QShCnuN0 -z`n9&UeypypUgx;R+x;XM#8uDM{p`9~j<49)^dotHJVO*A@HL&g7F={FP#trj@{dzm -zeQUiqRWJ&pkKkA1O-|vOf8O1UQ$$0lIExffio|}F@ROV#MXcPH$ -z?$$kxAF@B#KT}u;R@SVyIO>1sw1!i?C(_013w9@?8$bKaLQi34zC$g*^}F&(%NEO6 -zQzD-^6}HQMnGJ{h$J*)HjSxjblWegsW&rLC8Ov_r_20jLjUS$Ptnm|p9fK%r0j+4; -z57^mjL&lISh8>DC;eB$B69$h4XxE3qU4T&zUpDeV@4g>or%D-x@qhie>6mqD959ck74(h?S0BA0}YQ18d?hr6}%}y{%ZNJ^-(?=Op~; -z#2-UNh)jH9>RXmvPJ(Y!8(uhyW|sFpyvv)AaNeljHj^Fx+RC -z!`@c->W1C^FUKHmG2w_atkdsMnzY+l!CV8havQ8-Gu)<8t{#V*2Pwp4h?ayXsi5Z> -zo!guta>TA~iv#iJpQkN>#)QF%As@2WgU&V_Y^qm#E*O}M_ijJfFWq}ts)-l4>D)kCqJJ@MG2$69ph0jzwI8ry1u8D@CyinC$oT?7S*Z}Eg -zYs}PWLqr4u@)w}#!{cMx;KxO6W2H6~3k$laJjAt+C{0mmCRnfs=OJYbh}HMh&e`#> -zj;jrpjqKCh41OK{FOS`@_sPP$iCm46G^EMNk8(l-1f>!gEV+4vMVRZ#8infUenP+k -zL^tBOHF^=)k&U-Tw{gfijqQ&^ -z-RHHII5yp}2|o8pTsf6x7$teW9Em!~iy2DN?D@|U)g%I6VG%JBO$|~;c~1Q^3|x`1 -z6HRbq1#~Ke)wWpALcc&@P;m+*sGavR0{aOx3=IwUE3YPWAwV45pzD$~02inxi7(6X -z$zk683M=_r#M*+6fQ)&FK0y|lm7JLwS)K=t&ZJk!U_-y%_o@fhr{s37MUEQOF*M)3 -zB$;4>Zx;Xk*(hwFjb>1iJ1f*D#nyWL{=>{2|9*^vCNN!%bF8Oe<`xz#s;jFz?;I}4M3lL;!fy_;J-E96Of+;sG%K=fZdR)99pJ}fM( -zq%(s8UrsEL{NrdF`!#RY+VjFyPpE_vtqPMM!MQ+QnE)+_g9Z^{4^;k&Sa^=w*yuxB_*Z!U%!3{_9Qr)Jfz4IeS#io4oj_Kqhq`HCUub|Ke!v$1-$v=kc+O#rlCej?%dhY -zxxKUTsFPG1nfoFp3%7@gh9S?vM0N27#*fpJyaX;Vy{!pt*}!9_mX9uC#J5RyjknW2Dm3dCvZYU -zSW?0kvI9!o2un}*%`AYhr^CQT1aZF=-Nt^atn@Kt%b2!hT(pK!|MclbBv3-<+6{>_ -z8toMfWc9rpOk(8|KW>Z-k>Fr(xc_+q9ocf`8!_n}XYUrW?Ax|*_|=5m*4F0V+46wJ -z1IGS^Z5t=0Zj86J2MfJc -zUq#WKCfhoB<;P2&&`*_G4^_0uqDR20m!>T8ay_rxSzA&9_v5##g6tzXTkx+KRfz32 -z9vvpp?+YxHTxDthCBu7)&Q052y4s9*$M4_2w-OdPyK?F-EBoUuSsIk@@(!gA*A_!0 -z2eu1y;-Q$Ut(M>8FCOtw?vZR-%*ly^x)<95vK@P0tJoZws@+M*NGhg_NU`!}DZnWBHQz%*@6))$BWN;EM0xAF+B4Mph#S??J?K+&viwPmes*n^HGDL9iBf -zCk|mDu46wwughN!isu&G((DO>Ws`(VLY?^#w=RONxUgFGby--Y=5NJ|(>qXOS`;lZhmXyMEyBdVM@jJh71E-})~`?t4w8^Kwy) -z<+KACjs!F^TS-;FT24_iWF+=l(nR}j7U#;Vd -z)IT3=b&}A}1PUKFa6DKfgHkJci!~7u?a%k9h7Rri^{y`|;;xNDoQbV}+oJ=LdApL}|77o@C= -z;~aed)XpbrMtt1x3gHPWxbliQH4nKBCew{9 -z*-_PTyn~`1VrwKcc4ZrhI^!MsZ{D0O0%O2!SHHi^Dfyr9*x*DGFKwc()b;q6nM*M7 -zvA$x_?$BMJJHN5HIn9Ps{_7-sn79~BZegaa5V;s(BA<5BnU?^AeJHXtd)cIj_UCjA -zW|N@MjV~vrJz{sE0Dzv}tXxUDQAXm)1(kX7C_ZVFX%!TlZ850i(P1A0BxaJu)#LcH -zoxMFRzxoxw$bM=B6gpuMD#vcsa^00?%=D+T9-dQqV*=zD|)W!3BLun2&^n)~$ -z2_^{i9~sGXOAsF_S=k&4mWJ@`mD+G%MiPTlhuomboeFNwHb(< -zVpVR!mwf;JmpO3JL|B%L-!;@7TG}+`HZA;-{VIlQGY|T=f|!9!S=!c?sq5|KeEQ*~ -zm!1xeZcJPbSsfjU9e>K|=Ni<+YgrIG!|5@|Z>4bjx+`1j^O-{QK8XARf -zUG$nLRiTEtt;)9F30rvw>nj)@vCF{$d7>o2n>}~Y2^^C79l@s`uXRZOcuy>^%2@t- -zRGv={pKlDXFUgvG_^DWGR==il1rIzn{$p4r(FVOQxZi!_*Ksfl2hR{Aj>01RbFAM= -zpr0wzMwlOwlkt4|JLK)$>VL+{4nv>^`yMa)T;(9f*B(9;{T+)_=M4dN>M&&hS-#(G -z)-sW(WxVkHR)`x#g)25Lu7qnN;~Q-bvKDZ=;^fyLy@okDpvt&ZU{!U)WVtmnp -zAN-CzM{jPFWep9NAKDDq@=kynkGi_GQ@Z2y_Wn)xc_q3-&+9`qdGy_{PF-2c^$)%x -zd0sonEJhtG*2|P*Q-f_3`Akk96HzBz2 -z!5tnJaCcA2hGQrSw*{F)epvfYX?7toP=O0dN -zizY2w`>O@4Vqff!dBhQ^><#TjMP}loM9ProiD-Og@$V=*zQ|Avg0D!+96lr^u(1fl -z3J52PHoJYDdvdiIW?q?JIC*r?88VruLx#bp0lys39v$(c6uC*j}2IFFh -zViOX|K+DH18cd9%Rgjs$*sXuoW<>p^Fv-7CV|zpgTUnj812pyyX-nhA4TZ^UyYY9; -z?}BOarTT1q;0xSTjV_DPWE11?Y2+wSA*ybzebDoy8JwhznKa6SvYxE$WswX7Z6pG$ -zsA2GgHFFL3^zA@XTYK{a+6$Q8di%@1-|q9U15y+~R-L7Kwx8*xr(FP{g*JDPa`e((jSl#~?Rx=3ne(nLfeP9k0grubJK -zU4euzZqt~$Cl%k^{-!e6YQZi|D3#+MUS}VsYZ)0S>y@)kyqRI?A_esvAu-{`1Uq@! -zC+b`wnMK&<_mitl+k@e*$*{&S>vayX*>D>Q5sw2FZ?l(8ff%(8lo<^mBMrwQXOXe+ -z*7sZdWzBTIwZO$y^F)qZL1XbOMY<@M_a56y{({Vg@YN<_y}toq41V%~w=+4ZQvg)X -zVw~l$z-sId^nKU%dlk7W(mG}eS&KV2BdYqNJnX-p=YrG&&`_m0fzA_|iKD${5?oL* -zdS$heR@%Q+(3!!T&k;tIN|v2j=UI))rgkvyC7MTTrKP3g>Fma@_R0`GE5(tL%sS$7 -zG41ag%(Y(xZ5cjlk=R~(3XC+$25r*Fo=G5OhGgR}i!nDoG?^sult?Eo*x$x6CH-3L@LtZ0dfq!Bbbw-S}RwlN%lpH8c=4l2qH -z1wRszHSPh~=esnWvXD8B{D4<}?}6cA+@Ob1760Is6`g!zl@WL(L&={LA}SxAt0>Tw -z%b7i^&yNKM;(vGcNwuxAK{g|S3Y1&pH_6U1G -z3M4zx5FU=O;=l_?VzQ-~bx~xN1axPgYI0am3d25BjYmfSTX7Q}==Vcryl6@Se0(Jv -zxKW_o%H`jdnC7QXlkFbCsACHN1Dx=0gf<~@PW-&<=`1Hd)@#ypH7%OpalDj-P=ts+3^~yWs~TV}BD20HjkW6zc1L -z0#HzMkn3JV%7N-18_@tgE82*YnmEzxirriDSx#_|<|q1vL{k}7>^mRzO(ueTSN2~H -zG}kxp)Qn!&)><3|e>62+GXSpQKcemfqU!&BHZ5Ca;DT<63bBM&uV1BDS?MM$M;x8w>gShAPMxJM^BbMZn}Unm{OC9^4x3%% -zlmX8!km-u$N4fQXQ>jRe`7)3+RFGjhz -z18zf(Fo2<>YV^7LJO^UTZ2Ivd#mpN}o?7pBV&q=f%ID>haV7M8R3jsF*@a%iwIy>| -zsZ!-y{!%&j7`B?W8TcF4NH-RHH1xZ{;7BsA<#APu!;cND)te)FhoXz$BIU}2&^7WP -zT}TX>ZO58$VNPuh6JV7~s(W$vAj`^%AtUamex3YdVl3~4+pqk?G)qUibNMrj0*M25 -zY>5Ac|Dnv6xBQmV#$3JA?&HTN(lYl~J}@$l{*TY^kORrCB)3dDO}^^v!dcLf^CHty -zanjllIQeSLmpuG+h&ae`r*v!C*0A&W^a&q>93?BAXzG7n -z2*3TGPIcN`-_hY9&oaiv#fiv~>}7`T`4=pInEqWX*3e8+yPm^9h-tr&ts55$l+388 -zW)~F}2JH!}VLbQ>?6~H@&k`MnSsTeVj0TRVP4jGbP*!!CwM6`Z11c)yI2w$+R0zxo -zT|obYS1&&`{>>Z9(jnVU&=yI*%PGe*f78ie*_9oap?sd7fx7{r^WT>=XHF -zl`f{=UJEn2?tRw`Fem?eRE6#*nOes(ebRcmaK3~a3{a3EyE1zXSF0p7I_iDJ&%;3V -zU;AS}e?*mH#Yh2P9E3QBigIqu2iXf=@t)2+I~f*_E^JtEP1@IR{CBfTj%T}E3e#n% -zUa{@vU?D$l4DEANwkkK@ruP4ta)E*e^KLGg%$PizyPmHvKNMWtuJQ6sPXY=(1m#>W -z7V?9E!Vj}>a|KfQx5ESpH+q6$@gAp-P#~lbz`aj1_?xinN>3o8b2-Z3w>UZ3QZ}W0 -zWg-!>p>AADDcU^4;0*L4UFgB0QLlXd^y1E&4>txV!T|!`RwjZGl`;-4ZgFf>luHIy -zZ8d8Rh{I3r!g-ht6mAZxMB6VxRqnA0UY`h|mJZy2 -z17BazT$jMKFL3J6Ue_HL1^)4s%$Jj~Qx~1HG#tS@kwL(KP_ZI3dWz0SH(sqj#-*TNGsIWqPj>cj?!GyWvfdEiNOu4$>MIqL=F&Cc0{g*~L5 -zA1wt)=_zMFUkCT5$l!G{1-Y9QtGQ#qm5E(3fYPms_EP*sSVI)bfXN|uNO`BqVuCvd -zv)z8IGRgtM1<_trndVhQ^xA)wn~*W~#d*X@E=W)jcQWI8+?kdzHe;DZ`%+JE%gE}m -z6H=FO8rJxM{N90S=Gi!Mel)TyanxPa;E}C?hJl@e9UWad->;S|v;axgFjrY$z3(rV{MiJ}3M)t;Q?P5wZy0e3G{dcDO7n}3slDXLMrB$;#*W@Qv)D$=?Xs$F(8eTcyGIQ~IWgD%Gn&E>F9y#o>cR-7spE;Rur<_E~Pu)e0I -z#&y1|@8D~8c55<|KMf;&x;hg!A%VOZ38_+uk`jH4#=b9M&xcpxV-7cMN{jXVRnKSe -zlKJJ%=VBV{$DNeI1QkiA;DfdVT?$;O#22z6v6bTK9)fjrfIh!Hq__l~KzuNqT{&kA -zKs@YV6^1ZLGjTgR%(=NHS-DvWnnP)NM#qbHINqmQdCE5??co$3nuikqgm=s7*#Kd*+j_weKrZjMeLeHEoiJm>zuDRU` -zh~ggr^knneWU!Nn}AQt=0Id6Hk; -z4bJqse|V$H`stT?NS0yreYvaZ9YF!fw+N}{3#yXRU!C7?exl35BDC%+!jDMGT^DN# -zN9FGd#5t#;$h}5UgQ?q-Gr15>C6=nLUszle9<+_!!oi_m@_L^-R>_Qty7_g|C%m|5 -z-7^5X5V_ARi?h9_LW%2vByD3X_IvUktqBv{%SYXO1&;e&O#Ll_cfC`Wv1u+l_#RI< -zQ5Kly0;P`%TXaQN(heOg~>V&L{d+ZDA%eq-UKo#1)$rkjSm=nzAE2r -z5--RyKhxfXoGVU3^ab{5XGlyL1+26foG)4HZvN -zG@&I3h0fnK5lIjcrg*XxPy1(gK3_TN`&VYnxP;C|j$~0rT$0f|*#=OzM^NbE-1T5D -z%Csnt)n!sx3N#b(8G&+G3W~Q_B#StA6jZZ=p#wuu`DrAMXm{T@#S;ku4Dme@{Njmk -zCtrh3z6O>o)~o{&Htx+6kn*)$NNBH-biu^aYtWUq -z(G>4rCEKr#tO>!x8A@%W@6g)Xs%2Hq!y#Mbb@9R2@GDWi&!{jhZvzQ1D9nMuPoOS+ -z+cj{9nx5X{jJOIavbFf)Kz5Jnbe5Bu#(XE-z$j&iaP%c9W59OoT0~|N#D*(N2kz={ -zs(|)nH!_+_g1)#ZH2xk>ZTG#6WN#qa3BxZM{NWxq`*#$H255k6Ky?hw*hSA6`c_fl -zT@Ua%E5Ez3;~`kQFmrC#$Nlvc_Uy3#yzhd-6UYuuIwgIBZZC-`dwOBJbfurL(FfhH -z{YkjE+9OrOveY`{t{sGw&51YO1@{iO4)Ki=!Z5#q=m_Hi)_j0`>?;t2j);vv%BUif -z;wpTZdLQLsGvZ()DCdxYudn^Pt;BZ}Rin$4F8h{R`HxT2z`uc&aMXIQOvwgA5%{&) -zFW52MiN!$!EXgx}Px~e1!EMp;#&kY65oDho95j~!qD%YJr`+aK4jCJ4UJ^;q>w@Lf -zvDfg|M`S^@DGxu+7aR3Cx#;%?advj&1~L-m -zJqCP9&TW3migV*`Z$#)Qa>3>Jf)g9D6Ki28P@iX(uso)hic8Dp1F< -zeF;(n8Po8A*~^T{De(J)Z2nqLl@Vv3yoSlGwq0aeOg4ymI(KIkTeur-=J-yp9z?qe)it6gq-wl@I -z0D-_I{|T<5kwD9uH3yf1GWXp5*8eOgJf*q0IRoK|+r{}Fug&0WpNDKMTC@(Xc)9K8 -zy`lByMn!1fnY)1KYP(0Je1)c~WilUuh<&Q8^OE?L9Q^xK*Y@M$`6D6TDCZ^@l8{|} -zxmmNw)mng$hYBii+&ZqedxWT0dnV#LG4zC%+kzcK+-??vEHT>Q-T8zu|s_1IbA#OV)^+1pg1OmmZn` - -literal 0 -HcmV?d00001 - diff --git a/Spigot-Server-Patches/Improve-death-events.patch b/Spigot-Server-Patches/Improve-death-events.patch deleted file mode 100644 index 55592b2056..0000000000 --- a/Spigot-Server-Patches/Improve-death-events.patch +++ /dev/null @@ -1,425 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 21 Aug 2018 01:39:35 +0100 -Subject: [PATCH] Improve death events - -This adds the ability to cancel the death events and to modify the sound -an entity makes when dying. (In cases were no sound should it will be -called with shouldPlaySound set to false allowing unsilencing of silent -entities) - -It makes handling of entity deaths a lot nicer as you no longer need -to listen on the damage event and calculate if the entity dies yourself -to cancel the death which has the benefit of also receiving the dropped -items and experience which is otherwise only properly possible by using -internal code. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public int ping; - public boolean viewingCredits; - private int containerUpdateDelay; // Paper -+ // Paper start - cancellable death event -+ public boolean queueHealthUpdatePacket = false; -+ public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); - - org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure -+ // Paper start - cancellable death event -+ if (event.isCancelled()) { -+ // make compatible with plugins that might have already set the health in an event listener -+ if (this.getHealth() <= 0) { -+ this.setHealth((float) event.getReviveHealth()); -+ } -+ return; -+ } -+ // Paper end - - // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - } - } -- -- return super.damageEntity(damagesource, f); -+ // Paper start - cancellable death events -+ //return super.damageEntity(damagesource, f); -+ this.queueHealthUpdatePacket = true; -+ boolean damaged = super.damageEntity(damagesource, f); -+ this.queueHealthUpdatePacket = false; -+ if (this.queuedHealthUpdatePacket != null) { -+ this.playerConnection.sendPacket(this.queuedHealthUpdatePacket); -+ this.queuedHealthUpdatePacket = null; -+ } -+ return damaged; -+ // Paper end - } - } - } -diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -@@ -0,0 +0,0 @@ public class CombatTracker { - this.h = null; - } - -+ public final void reset() { this.g(); } // Paper - OBFHELPER - public void g() { - int i = this.f ? 300 : 100; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ public final void runKillTrigger(Entity entity, int kills, DamageSource damageSource) { this.a(entity, kills, damageSource); } // Paper - OBFHELPER - public void a(Entity entity, int i, DamageSource damagesource) { - if (entity instanceof EntityPlayer) { - CriterionTriggers.c.a((EntityPlayer) entity, this, damagesource); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.fallDistance = 0.0F; - } - -+ public final void onKill(WorldServer worldserver, EntityLiving entityLiving) { this.a(worldserver, entityLiving); } // Paper - OBFHELPER - public void a(WorldServer worldserver, EntityLiving entityliving) {} - - protected void l(double d0, double d1, double d2) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - protected float aL; - protected float aM; - protected float aN; -- protected int aO; -+ protected int aO;protected int getKillCount() { return this.aO; } // Paper - OBFHELPER - public float lastDamage; - protected boolean jumping; - public float aR; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; - public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper -+ public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event - - @Override - public float getBukkitYaw() { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - if (knockbackCancelled) this.world.broadcastEntityEffect(this, (byte) 2); // Paper - Disable explosion knockback - if (this.dl()) { - if (!this.f(damagesource)) { -- SoundEffect soundeffect = this.getSoundDeath(); -+ // Paper start - moved into CraftEventFactory event caller for cancellable death event -+ //SoundEffect soundeffect = this.getSoundDeath(); - -- if (flag1 && soundeffect != null) { -- this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -- } -+// if (flag1 && soundeffect != null) { -+// this.playSound(soundeffect, this.getSoundVolume(), this.dH()); -+// } -+ this.silentDeath = !flag1; // mark entity as dying silently -+ // Paper end - - this.die(damagesource); -+ this.silentDeath = false; // Paper - cancellable death event - reset to default - } - } else if (flag1) { - this.c(damagesource); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - Entity entity = damagesource.getEntity(); - EntityLiving entityliving = this.getKillingEntity(); - -+ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below - if (this.aO >= 0 && entityliving != null) { - entityliving.a(this, this.aO, damagesource); - } -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - if (this.isSleeping()) { - this.entityWakeup(); - } -+ */ // Paper - - this.killed = true; -- this.getCombatTracker().g(); -+ // this.getCombatTracker().g(); // Paper - moved into if below as .reset() - if (this.world instanceof WorldServer) { - if (entity != null) { -- entity.a((WorldServer) this.world, this); -+ // entity.a((WorldServer) this.world, this); // Paper - move below into if for onKill - } - -- this.d(damagesource); -+ // Paper start -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.d(damagesource); -+ if (deathEvent == null || !deathEvent.isCancelled()) { -+ if (this.getKillCount() >= 0 && entityliving != null) { -+ entityliving.runKillTrigger(this, this.getKillCount(), damagesource); -+ } -+ if (this.isSleeping()) { -+ this.entityWakeup(); -+ } -+ this.getCombatTracker().reset(); -+ if (entity != null) { -+ entity.onKill((WorldServer) this.world, this); -+ } -+ } else { -+ this.killed = false; -+ this.setHealth((float) deathEvent.getReviveHealth()); -+ } -+ // Paper end - this.f(entityliving); - } - -+ if (this.killed) { // Paper - this.world.broadcastEntityEffect(this, (byte) 3); - this.setPose(EntityPose.DYING); -+ } // Paper - } - } - -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - if (!this.world.isClientSide) { - boolean flag = false; - -- if (entityliving instanceof EntityWither) { -+ if (this.killed && entityliving instanceof EntityWither) { // Paper - if (this.world.getGameRules().getBoolean(GameRules.MOB_GRIEFING)) { - BlockPosition blockposition = this.getChunkCoordinates(); - IBlockData iblockdata = Blocks.WITHER_ROSE.getBlockData(); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - } - -- protected void d(DamageSource damagesource) { -+ protected org.bukkit.event.entity.EntityDeathEvent processDeath(DamageSource damagesource) { return d(damagesource); } // Paper - OBFHELPER -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper - Entity entity = damagesource.getEntity(); - int i; - -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.dropDeathLoot(damagesource, i, flag); - } - // CraftBukkit start - Call death event -- CraftEventFactory.callEntityDeathEvent(this, this.drops); -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = CraftEventFactory.callEntityDeathEvent(this, this.drops); // Paper -+ this.postDeathDropItems(deathEvent); // Paper - this.drops = new ArrayList<>(); - // CraftBukkit end - - // this.dropInventory();// CraftBukkit - moved up - this.dropExperience(); -+ return deathEvent; // Paper - } - - protected void dropInventory() {} -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) {} // Paper - method for post death logic that cannot be ran before the event is potentially cancelled - - // CraftBukkit start - public int getExpReward() { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return SoundEffects.ENTITY_GENERIC_HURT; - } - -+ public final SoundEffect getDeathSoundEffect() { return this.getSoundDeath(); } // Paper - OBFHELPER - @Nullable - protected SoundEffect getSoundDeath() { - return SoundEffects.ENTITY_GENERIC_DEATH; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - } - -+ public final float getDeathSoundVolume() { return this.getSoundVolume(); } // Paper - OBFHELPER - protected float getSoundVolume() { - return 1.0F; - } - -+ public float getSoundPitch() { return dH();} // Paper - OBFHELPER - protected float dH() { - return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.5F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityFox.java -@@ -0,0 +0,0 @@ public class EntityFox extends EntityAnimal { - } - - @Override -- protected void d(DamageSource damagesource) { -- ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND); -+ protected org.bukkit.event.entity.EntityDeathEvent d(DamageSource damagesource) { // Paper -+ ItemStack itemstack = this.getEquipment(EnumItemSlot.MAINHAND).cloneItemStack(); // Paper -+ -+ // Paper start - Cancellable death event -+ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.d(damagesource); -+ -+ // Below is code to drop -+ -+ if (deathEvent == null || deathEvent.isCancelled()) { -+ return deathEvent; -+ } -+ // Paper end - - if (!itemstack.isEmpty()) { - this.a(itemstack); - this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); - } - -- super.d(damagesource); -+ return deathEvent; // Paper - } - - public static boolean a(EntityFox entityfox, EntityLiving entityliving) { -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseChestedAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityHorseChestedAbstract extends EntityHorseAbstract { - this.a((IMaterial) Blocks.CHEST); - } - -- this.setCarryingChest(false); -+ //this.setCarryingChest(false); // Paper - moved to post death logic - } - - } - -+ // Paper start -+ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { -+ if (this.isCarryingChest() && (event == null || !event.isCancelled())) { -+ this.setCarryingChest(false); -+ } -+ } -+ // Paper end -+ - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - - @Override - public void killEntity() { -- org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event -+ org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable -+ if (event.isCancelled()) return; // Paper - make cancellable - this.die(); - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void sendHealthUpdate() { -- getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ // Paper start - cancellable death event -+ //getHandle().playerConnection.sendPacket(new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel())); -+ PacketPlayOutUpdateHealth packet = new PacketPlayOutUpdateHealth(getScaledHealth(), getHandle().getFoodData().getFoodLevel(), getHandle().getFoodData().getSaturationLevel()); -+ if (this.getHandle().queueHealthUpdatePacket) { -+ this.getHandle().queuedHealthUpdatePacket = packet; -+ } else { -+ this.getHandle().playerConnection.sendPacket(packet); -+ } -+ // Paper end - } - - public void injectScaledMaxHealth(Collection collection, boolean force) { -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; -+import net.minecraft.sounds.SoundCategory; -+import net.minecraft.sounds.SoundEffect; - import net.minecraft.util.Unit; - import net.minecraft.world.EnumHand; - import net.minecraft.world.IInventory; -@@ -0,0 +0,0 @@ public class CraftEventFactory { - public static EntityDeathEvent callEntityDeathEvent(EntityLiving victim, List drops) { - CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); - EntityDeathEvent event = new EntityDeathEvent(entity, drops, victim.getExpReward()); -+ populateFields(victim, event); // Paper - make cancellable - CraftWorld world = (CraftWorld) entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); - -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - victim.expToDrop = event.getDroppedExp(); - - for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { -@@ -0,0 +0,0 @@ public class CraftEventFactory { - CraftPlayer entity = victim.getBukkitEntity(); - PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure - event.setKeepInventory(keepInventory); -+ populateFields(victim, event); // Paper - make cancellable - org.bukkit.World world = entity.getWorld(); - Bukkit.getServer().getPluginManager().callEvent(event); -+ // Paper start - make cancellable -+ if (event.isCancelled()) { -+ return event; -+ } -+ playDeathSound(victim, event); -+ // Paper end - - victim.keepLevel = event.getKeepLevel(); - victim.newLevel = event.getNewLevel(); -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start - helper methods for making death event cancellable -+ // Add information to death event -+ private static void populateFields(EntityLiving victim, EntityDeathEvent event) { -+ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); -+ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); -+ SoundEffect soundEffect = victim.getDeathSoundEffect(); -+ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); -+ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundCategory().name())); -+ event.setDeathSoundVolume(victim.getDeathSoundVolume()); -+ event.setDeathSoundPitch(victim.getSoundPitch()); -+ } -+ -+ // Play death sound manually -+ private static void playDeathSound(EntityLiving victim, EntityDeathEvent event) { -+ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { -+ EntityHuman source = victim instanceof EntityHuman ? (EntityHuman) victim : null; -+ double x = event.getEntity().getLocation().getX(); -+ double y = event.getEntity().getLocation().getY(); -+ double z = event.getEntity().getLocation().getZ(); -+ SoundEffect soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); -+ SoundCategory soundCategory = SoundCategory.valueOf(event.getDeathSoundCategory().name()); -+ victim.world.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); -+ } -+ } -+ // Paper end - /** - * Server methods - */ diff --git a/Spigot-Server-Patches/Improve-inlinig-for-some-hot-IBlockData-methods.patch b/Spigot-Server-Patches/Improve-inlinig-for-some-hot-IBlockData-methods.patch deleted file mode 100644 index 0644013f7d..0000000000 --- a/Spigot-Server-Patches/Improve-inlinig-for-some-hot-IBlockData-methods.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Jul 2020 20:46:50 -0700 -Subject: [PATCH] Improve inlinig for some hot IBlockData methods - - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -0,0 +0,0 @@ public abstract class BlockBase { - } - // Paper end - -+ // Paper start -+ protected boolean isTicking; -+ protected Fluid fluid; -+ // Paper end -+ - public void a() { -+ this.fluid = this.getBlock().d(this.p()); // Paper - moved from getFluid() -+ this.isTicking = this.getBlock().isTicking(this.p()); // Paper - moved from isTicking() - if (!this.getBlock().o()) { - this.a = new BlockBase.BlockData.Cache(this.p()); - } -@@ -0,0 +0,0 @@ public abstract class BlockBase { - return this.getBlock().d(this.p(), iblockaccess, blockposition); - } - -- public boolean d() { -+ public final boolean d() { // Paper - return this.a == null || this.a.c; - } - -- public boolean e() { -+ public final boolean e() { // Paper - return this.e; - } - -- public int f() { -+ public final int f() { // Paper - return this.b; - } - -- public boolean isAir() { -+ public final boolean isAir() { // Paper - return this.f; - } - -@@ -0,0 +0,0 @@ public abstract class BlockBase { - } - } - -- public boolean l() { -+ public final boolean l() { // Paper - return this.k; - } - -@@ -0,0 +0,0 @@ public abstract class BlockBase { - return this.getBlock().a(block); - } - -- public Fluid getFluid() { -- return this.getBlock().d(this.p()); -+ public final Fluid getFluid() { // Paper -+ return this.fluid; // Paper - moved into init - } - -- public boolean isTicking() { -- return this.getBlock().isTicking(this.p()); -+ public final boolean isTicking() { // Paper -+ return this.isTicking; // Paper - moved into init - } - - public SoundEffectType getStepSound() { -diff --git a/src/main/java/net/minecraft/world/level/material/Fluid.java b/src/main/java/net/minecraft/world/level/material/Fluid.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/material/Fluid.java -+++ b/src/main/java/net/minecraft/world/level/material/Fluid.java -@@ -0,0 +0,0 @@ public final class Fluid extends IBlockDataHolder { - - public static final Codec a = a((Codec) IRegistry.FLUID, FluidType::h).stable(); - -+ // Paper start -+ protected final boolean isEmpty; -+ // Paper end - public Fluid(FluidType fluidtype, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(fluidtype, immutablemap, mapcodec); -+ this.isEmpty = fluidtype.b(); // Paper - moved from isEmpty() - } - - public FluidType getType() { -@@ -0,0 +0,0 @@ public final class Fluid extends IBlockDataHolder { - } - - public boolean isEmpty() { -- return this.getType().b(); -+ return this.isEmpty; // Paper - moved into constructor - } - - public float getHeight(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/Spigot-Server-Patches/Improve-the-Saddle-API-for-Horses.patch b/Spigot-Server-Patches/Improve-the-Saddle-API-for-Horses.patch deleted file mode 100644 index 353e1bef8e..0000000000 --- a/Spigot-Server-Patches/Improve-the-Saddle-API-for-Horses.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Dec 2016 16:24:06 -0500 -Subject: [PATCH] Improve the Saddle API for Horses - -Not all horses with Saddles have armor. This lets us break up the horses with saddles -and access their saddle state separately from an interface shared with Armor. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; - import org.apache.commons.lang.Validate; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; -+import org.bukkit.craftbukkit.inventory.CraftSaddledInventory; - import org.bukkit.entity.AbstractHorse; - import org.bukkit.entity.AnimalTamer; - import org.bukkit.entity.Horse; -@@ -0,0 +0,0 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - - @Override - public AbstractHorseInventory getInventory() { -- return new CraftInventoryAbstractHorse(getHandle().inventoryChest); -+ return new CraftSaddledInventory(getHandle().inventoryChest); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryHorse.java -@@ -0,0 +0,0 @@ import net.minecraft.world.IInventory; - import org.bukkit.inventory.HorseInventory; - import org.bukkit.inventory.ItemStack; - --public class CraftInventoryHorse extends CraftInventoryAbstractHorse implements HorseInventory { -+public class CraftInventoryHorse extends CraftSaddledInventory implements HorseInventory { - - public CraftInventoryHorse(IInventory inventory) { - super(inventory); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftSaddledInventory.java -@@ -0,0 +0,0 @@ -+package org.bukkit.craftbukkit.inventory; -+ -+import net.minecraft.world.IInventory; -+import org.bukkit.inventory.SaddledHorseInventory; -+ -+public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { -+ -+ public CraftSaddledInventory(IInventory inventory) { -+ super(inventory); -+ } -+ -+} diff --git a/Spigot-Server-Patches/Improved-Async-Task-Scheduler.patch b/Spigot-Server-Patches/Improved-Async-Task-Scheduler.patch deleted file mode 100644 index b05b55f2ee..0000000000 --- a/Spigot-Server-Patches/Improved-Async-Task-Scheduler.patch +++ /dev/null @@ -1,370 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 16 Mar 2018 22:59:43 -0400 -Subject: [PATCH] Improved Async Task Scheduler - -The Craft Scheduler still uses the primary thread for task scheduling. -This results in the main thread still having to do work as part of the -dispatching of async tasks. - -If plugins make use of lots of async tasks, such as particle emitters -that want to keep the logic off the main thread, the main thread still -receives quite a bit of load from processing all of these queued tasks. - -Additionally, resizing and managing the pending entries for all of -these asynchronous tasks takes up time on the main thread too. - -This commit replaces the implementation of the scheduler when working -with asynchronous tasks, by forwarding calls to the new scheduler. - -The Async Scheduler uses a single thread executor for "management" tasks. -The Management Thread is responsible for all adding and dispatching of -scheduled tasks. - -The mainThreadHeartbeat will send a heartbeat task to the management thread -with the currentTick value, so that it can find which tasks to execute. - -Scheduling of an async tasks also dispatches a management task, ensuring -that any Queue resizing operation occurs off of the main thread. - -The async queue uses a complete separate PriorityQueue, ensuring that resize -operations are decoupled from the sync tasks queue. - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java -@@ -0,0 +0,0 @@ -+/* -+ * Copyright (c) 2018 Daniel Ennis (Aikar) MIT License -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining -+ * a copy of this software and associated documentation files (the -+ * "Software"), to deal in the Software without restriction, including -+ * without limitation the rights to use, copy, modify, merge, publish, -+ * distribute, sublicense, and/or sell copies of the Software, and to -+ * permit persons to whom the Software is furnished to do so, subject to -+ * the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+package org.bukkit.craftbukkit.scheduler; -+ -+import com.destroystokyo.paper.ServerSchedulerReportingWrapper; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import org.bukkit.plugin.Plugin; -+ -+import java.util.ArrayList; -+import java.util.Iterator; -+import java.util.List; -+import java.util.concurrent.Executor; -+import java.util.concurrent.Executors; -+import java.util.concurrent.SynchronousQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+ -+public class CraftAsyncScheduler extends CraftScheduler { -+ -+ private final ThreadPoolExecutor executor = new ThreadPoolExecutor( -+ 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), -+ new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); -+ private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() -+ .setNameFormat("Craft Async Scheduler Management Thread").build()); -+ private final List temp = new ArrayList<>(); -+ -+ CraftAsyncScheduler() { -+ super(true); -+ executor.allowCoreThreadTimeOut(true); -+ executor.prestartAllCoreThreads(); -+ } -+ -+ @Override -+ public void cancelTask(int taskId) { -+ this.management.execute(() -> this.removeTask(taskId)); -+ } -+ -+ private synchronized void removeTask(int taskId) { -+ parsePending(); -+ this.pending.removeIf((task) -> { -+ if (task.getTaskId() == taskId) { -+ task.cancel0(); -+ return true; -+ } -+ return false; -+ }); -+ } -+ -+ @Override -+ public void mainThreadHeartbeat(int currentTick) { -+ this.currentTick = currentTick; -+ this.management.execute(() -> this.runTasks(currentTick)); -+ } -+ -+ private synchronized void runTasks(int currentTick) { -+ parsePending(); -+ while (!this.pending.isEmpty() && this.pending.peek().getNextRun() <= currentTick) { -+ CraftTask task = this.pending.remove(); -+ if (executeTask(task)) { -+ final long period = task.getPeriod(); -+ if (period > 0) { -+ task.setNextRun(currentTick + period); -+ temp.add(task); -+ } -+ } -+ parsePending(); -+ } -+ this.pending.addAll(temp); -+ temp.clear(); -+ } -+ -+ private boolean executeTask(CraftTask task) { -+ if (isValid(task)) { -+ this.runners.put(task.getTaskId(), task); -+ this.executor.execute(new ServerSchedulerReportingWrapper(task)); -+ return true; -+ } -+ return false; -+ } -+ -+ @Override -+ public synchronized void cancelTasks(Plugin plugin) { -+ parsePending(); -+ for (Iterator iterator = this.pending.iterator(); iterator.hasNext(); ) { -+ CraftTask task = iterator.next(); -+ if (task.getTaskId() != -1 && (plugin == null || task.getOwner().equals(plugin))) { -+ task.cancel0(); -+ iterator.remove(); -+ } -+ } -+ } -+ -+ /** -+ * Task is not cancelled -+ * @param runningTask -+ * @return -+ */ -+ static boolean isValid(CraftTask runningTask) { -+ return runningTask.getPeriod() >= CraftTask.NO_REPEATING; -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - /** - * Main thread logic only - */ -- private final PriorityQueue pending = new PriorityQueue(10, -+ final PriorityQueue pending = new PriorityQueue(10, // Paper - new Comparator() { - @Override - public int compare(final CraftTask o1, final CraftTask o2) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - /** - * These are tasks that are currently active. It's provided for 'viewing' the current state. - */ -- private final ConcurrentHashMap runners = new ConcurrentHashMap(); -+ final ConcurrentHashMap runners = new ConcurrentHashMap(); // Paper - /** - * The sync task that is currently running on the main thread. - */ - private volatile CraftTask currentTask = null; -- private volatile int currentTick = -1; -+ // Paper start - Improved Async Task Scheduler -+ volatile int currentTick = -1;/* - private final Executor executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %d").build()); - private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) { - @Override -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - }; - private CraftAsyncDebugger debugTail = debugHead; -+ -+ */ // Paper end - private static final int RECENT_TICKS; - - static { - RECENT_TICKS = 30; - } - -+ -+ // Paper start -+ private final CraftScheduler asyncScheduler; -+ private final boolean isAsyncScheduler; -+ public CraftScheduler() { -+ this(false); -+ } -+ -+ public CraftScheduler(boolean isAsync) { -+ this.isAsyncScheduler = isAsync; -+ if (isAsync) { -+ this.asyncScheduler = this; -+ } else { -+ this.asyncScheduler = new CraftAsyncScheduler(); -+ } -+ } -+ // Paper end - @Override - public int scheduleSyncDelayedTask(final Plugin plugin, final Runnable task) { - return this.scheduleSyncDelayedTask(plugin, task, 0L); -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } else if (period < CraftTask.NO_REPEATING) { - period = CraftTask.NO_REPEATING; - } -- return handle(new CraftAsyncTask(runners, plugin, runnable, nextId(), period), delay); -+ return handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, nextId(), period), delay); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return; - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTask(taskId); -+ } -+ // Paper end - CraftTask task = runners.get(taskId); - if (task != null) { - task.cancel0(); -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - @Override - public void cancelTasks(final Plugin plugin) { - Validate.notNull(plugin, "Cannot cancel tasks of null plugin"); -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.cancelTasks(plugin); -+ } -+ // Paper end - final CraftTask task = new CraftTask( - new Runnable() { - @Override -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public boolean isCurrentlyRunning(final int taskId) { -+ // Paper start -+ if (!isAsyncScheduler) { -+ if (this.asyncScheduler.isCurrentlyRunning(taskId)) { -+ return true; -+ } -+ } -+ // Paper end - final CraftTask task = runners.get(taskId); - if (task == null) { - return false; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - if (taskId <= 0) { - return false; - } -+ // Paper start -+ if (!this.isAsyncScheduler && this.asyncScheduler.isQueued(taskId)) { -+ return true; -+ } -+ // Paper end - for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { - if (task.getTaskId() == taskId) { - return task.getPeriod() >= CraftTask.NO_REPEATING; // The task will run -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public List getActiveWorkers() { -+ // Paper start -+ if (!isAsyncScheduler) { -+ //noinspection TailRecursion -+ return this.asyncScheduler.getActiveWorkers(); -+ } -+ // Paper end - final ArrayList workers = new ArrayList(); - for (final CraftTask taskObj : runners.values()) { - // Iterator will be a best-effort (may fail to grab very new values) if called from an async thread -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - pending.add(task); - } - } -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ pending.addAll(this.asyncScheduler.getPendingTasks()); -+ } -+ // Paper end - return pending; - } - -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - * This method is designed to never block or wait for locks; an immediate execution of all current tasks. - */ - public void mainThreadHeartbeat(final int currentTick) { -+ // Paper start -+ if (!this.isAsyncScheduler) { -+ this.asyncScheduler.mainThreadHeartbeat(currentTick); -+ } -+ // Paper end - this.currentTick = currentTick; - final List temp = this.temp; - parsePending(); -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); - } else { - //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper -- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper -+ task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Paper"); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) - } -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - //debugHead = debugHead.getNextHead(currentTick); // Paper - } - -- private void addTask(final CraftTask task) { -+ protected void addTask(final CraftTask task) { - final AtomicReference tail = this.tail; - CraftTask tailTask = tail.get(); - while (!tail.compareAndSet(tailTask, task)) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - tailTask.setNext(task); - } - -- private CraftTask handle(final CraftTask task, final long delay) { -+ protected CraftTask handle(final CraftTask task, final long delay) { // Paper -+ // Paper start -+ if (!this.isAsyncScheduler && !task.isSync()) { -+ this.asyncScheduler.handle(task, delay); -+ return task; -+ } -+ // Paper end - task.setNextRun(currentTick + delay); - addTask(task); - return task; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - return ids.incrementAndGet(); - } - -- private void parsePending() { -- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); -+ void parsePending() { // Paper -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper - } - - private boolean isReady(final int currentTick) { diff --git a/Spigot-Server-Patches/Improved-Watchdog-Support.patch b/Spigot-Server-Patches/Improved-Watchdog-Support.patch deleted file mode 100644 index 10804f9c96..0000000000 --- a/Spigot-Server-Patches/Improved-Watchdog-Support.patch +++ /dev/null @@ -1,608 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Apr 2020 15:50:48 -0400 -Subject: [PATCH] Improved Watchdog Support - -Forced Watchdog Crash support and Improve Async Shutdown - -If the request to shut down the server is received while we are in -a watchdog hang, immediately treat it as a crash and begin the shutdown -process. Shutdown process is now improved to also shutdown cleanly when -not using restart scripts either. - -If a server is deadlocked, a server owner can send SIGUP (or any other signal -the JVM understands to shut down as it currently does) and the watchdog -will no longer need to wait until the full timeout, allowing you to trigger -a close process and try to shut the server down gracefully, saving player and -world data. - -Previously there was no way to trigger this outside of waiting for a full watchdog -timeout, which may be set to a really long time... - -Additionally, fix everything to do with shutting the server down asynchronously. - -Previously, nearly everything about the process was fragile and unsafe. Main might -not have actually been frozen, and might still be manipulating state. - -Or, some reuest might ask main to do something in the shutdown but main is dead. - -Or worse, other things might start closing down items such as the Console or Thread Pool -before we are fully shutdown. - -This change tries to resolve all of these issues by moving everything into the stop -method and guaranteeing only one thread is stopping the server. - -We then issue Thread Death to the main thread of another thread initiates the stop process. -We have to ensure Thread Death propagates correctly though to stop main completely. - -This is to ensure that if main isn't truely stuck, it's not manipulating state we are trying to save. - -This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they -are properly accounted for and wont trip watchdog on init. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/Metrics.java -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -0,0 +0,0 @@ public class Metrics { - * Starts the Scheduler which submits our data every 30 minutes. - */ - private void startSubmitting() { -- final Runnable submitTask = this::submitData; -+ final Runnable submitTask = () -> { -+ if (MinecraftServer.getServer().hasStopped()) { -+ return; -+ } -+ submitData(); -+ }; - - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/CrashReport.java -+++ b/src/main/java/net/minecraft/CrashReport.java -@@ -0,0 +0,0 @@ public class CrashReport { - } - - public static CrashReport a(Throwable throwable, String s) { -+ if (throwable instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(throwable); // Paper - while (throwable instanceof CompletionException && throwable.getCause() != null) { - throwable = throwable.getCause(); - } -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -0,0 +0,0 @@ public class SystemUtils { - return SystemUtils.f; - } - -+ public static void shutdownServerThreadPool() { h(); } // Paper - OBFHELPER - public static void h() { - a(SystemUtils.e); - a(SystemUtils.f); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant S a(Function function) { - AtomicReference atomicreference = new AtomicReference(); - Thread thread = new Thread(() -> { -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ world.tickingEntities = false; -+ }); -+ } -+ // Paper end - // CraftBukkit end - MinecraftServer.LOGGER.info("Stopping server"); - MinecraftTimings.stopServer(); // Paper -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant {}; -+ } -+ // Paper end - return new TickTask(this.ticks, runnable); - } - -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - CompletableFuture completablefuture; -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private final Queue entitiesToAdd = Queues.newArrayDeque(); - public final List players = Lists.newArrayList(); // Paper - private -> public - public final ChunkProviderServer chunkProvider; // Paper - public -- boolean tickingEntities; -+ public boolean tickingEntities; // Paper - expose for watchdog - // Paper start - List afterEntityTickingTasks = Lists.newArrayList(); - public void doIfNotEntityTicking(java.lang.Runnable run) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - -- entityplayer.playerTick(); // SPIGOT-924 -+ if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) - // CraftBukkit end - - // Paper start - Remove from collideRule team if needed -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -0,0 +0,0 @@ public abstract class IAsyncTaskHandler implements Mailbox asList(String... params) { - return Arrays.asList(params); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -0,0 +0,0 @@ public class ServerShutdownThread extends Thread { - @Override - public void run() { - try { -+ // Paper start - try to shutdown on main -+ server.safeShutdown(false, false); -+ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { -+ Thread.sleep(100); -+ } -+ if (server.hasStopped()) { -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ return; -+ } -+ // Looks stalled, close async - org.spigotmc.AsyncCatcher.enabled = false; // Spigot - org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper -+ server.forceTicks = true; - server.close(); -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ // Paper end - } finally { - try { -- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender -+ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -0,0 +0,0 @@ public class RestartCommand extends Command - // Paper end - - // Paper start - copied from above and modified to return if the hook registered -- private static boolean addShutdownHook(String restartScript) -+ public static boolean addShutdownHook(String restartScript) - { - String[] split = restartScript.split( " " ); - if ( split.length > 0 && new File( split[0] ).isFile() ) -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -0,0 +0,0 @@ import org.bukkit.Bukkit; - public class WatchdogThread extends Thread - { - -+ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper - private static WatchdogThread instance; - private long timeoutTime; - private boolean restart; -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - { - if ( instance == null ) - { -+ if (timeoutTime <= 0) timeoutTime = 300; // Paper - instance = new WatchdogThread( timeoutTime * 1000L, restart ); - instance.start(); - } else -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - // Paper start - Logger log = Bukkit.getServer().getLogger(); - long currentTime = monotonicMillis(); -- if ( lastTick != 0 && timeoutTime > 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) -+ MinecraftServer server = MinecraftServer.getServer(); -+ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) - { -- boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); - // Don't spam early warning dumps - if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; -- if ( !isLongTimeout && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... - lastEarlyWarning = currentTime; - if (isLongTimeout) { - // Paper end -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper -- dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); -+ dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // - // Paper start - Only print full dump on long timeouts -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - - if ( isLongTimeout ) - { -- if ( restart && !MinecraftServer.getServer().hasStopped() ) -+ if ( !server.hasStopped() ) - { -- RestartCommand.restart(); -+ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ AsyncCatcher.shuttingDown = true; -+ server.forceTicks = true; -+ if (restart) { -+ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); -+ } -+ // try one last chance to safe shutdown on main incase it 'comes back' -+ server.abnormalExit = true; -+ server.safeShutdown(false, restart); -+ try { -+ Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ } -+ if (!server.hasStopped()) { -+ server.close(); -+ } - } - break; - } // Paper end -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -0,0 +0,0 @@ - -- -+ - - - diff --git a/Spigot-Server-Patches/Increase-Light-Queue-Size.patch b/Spigot-Server-Patches/Increase-Light-Queue-Size.patch deleted file mode 100644 index 837ab8176c..0000000000 --- a/Spigot-Server-Patches/Increase-Light-Queue-Size.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 21:24:05 -0400 -Subject: [PATCH] Increase Light Queue Size - -Wiz mentioned that large WorldEdit operations cause light to run on -main thread. The queue was small, set to 5.. this bumps it to 20 -but makes it configurable per-world. - -The main risk of increasing this higher is during shutdown, some -queued light updates may be lost because mojang did not flush the -light engine on shutdown... - -The queue size only puts a cap on max loss, doesn't solve that problem. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void zombieVillagerInfectionChance() { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); - } -+ -+ public int lightQueueSize = 20; -+ private void lightQueueSize() { -+ lightQueueSize = getInt("light-queue-size", lightQueueSize); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sun, 9 Aug 2020 08:59:25 +0300 -Subject: [PATCH] Incremental player saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - allowPistonDuplication = getBoolean("settings.unsupported-settings.allow-piston-duplication", config.getBoolean("settings.unsupported-settings.allow-tnt-duplication", false)); - set("settings.unsupported-settings.allow-tnt-duplication", null); - } -+ -+ public static int playerAutoSaveRate = -1; -+ public static int maxPlayerAutoSavePerTick = 10; -+ private static void playerAutoSaveRate() { -+ playerAutoSaveRate = getInt("settings.player-auto-save-rate", -1); -+ maxPlayerAutoSavePerTick = getInt("settings.max-player-auto-save-per-tick", -1); -+ if (maxPlayerAutoSavePerTick == -1) { // -1 Automatic / "Recommended" -+ // 10 should be safe for everyone unless you mass spamming player auto save -+ maxPlayerAutoSavePerTick = (playerAutoSaveRate == -1 || playerAutoSaveRate > 100) ? 10 : 20; -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down - //MinecraftServer.LOGGER.debug("Autosave started"); // Paper - serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper -+ // Paper start -+ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; -+ if (playerSaveInterval < 0) { -+ playerSaveInterval = autosavePeriod; -+ } -+ // Paper end - this.methodProfiler.enter("save"); -- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper -- this.playerList.savePlayers(); -+ if (playerSaveInterval > 0) { // Paper -+ this.playerList.savePlayers(playerSaveInterval); // Paper - }// Paper - // Paper start - for (WorldServer world : getWorlds()) { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ import org.bukkit.inventory.MainHand; - public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger LOGGER = LogManager.getLogger(); -+ public long lastSave = MinecraftServer.currentTick; // Paper - public PlayerConnection playerConnection; - public NetworkManager networkManager; // Paper - public final MinecraftServer server; -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - protected void savePlayerFile(EntityPlayer entityplayer) { - if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit - if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) -+ entityplayer.lastSave = MinecraftServer.currentTick; // Paper - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ // Paper start - incremental player saving -+ savePlayers(null); -+ } -+ public void savePlayers(Integer interval) { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper -+ int numSaved = 0; -+ long now = MinecraftServer.currentTick; - for (int i = 0; i < this.players.size(); ++i) { -- this.savePlayerFile((EntityPlayer) this.players.get(i)); -+ EntityPlayer entityplayer = this.players.get(i); -+ if (interval == null || now - entityplayer.lastSave >= interval) { -+ this.savePlayerFile(entityplayer); -+ if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } -+ } -+ // Paper end - } - MinecraftTimings.savePlayers.stopTiming(); // Paper - return null; }); // Paper - ensure main diff --git a/Spigot-Server-Patches/Inline-shift-direction-fields.patch b/Spigot-Server-Patches/Inline-shift-direction-fields.patch deleted file mode 100644 index a8839ad63d..0000000000 --- a/Spigot-Server-Patches/Inline-shift-direction-fields.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 18 Jan 2021 20:45:25 -0500 -Subject: [PATCH] Inline shift direction fields - -Removes a layer of indirection for EnumDirection.getAdjacent(X|Y|Z)(), which is in the -critical section for much of the server, including the lighting engine. - -diff --git a/src/main/java/net/minecraft/core/EnumDirection.java b/src/main/java/net/minecraft/core/EnumDirection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/EnumDirection.java -+++ b/src/main/java/net/minecraft/core/EnumDirection.java -@@ -0,0 +0,0 @@ public enum EnumDirection implements INamable { - }, (enumdirection, enumdirection1) -> { - throw new IllegalArgumentException("Duplicate keys"); - }, Long2ObjectOpenHashMap::new)); -+ // Paper start -+ private final int adjX; -+ private final int adjY; -+ private final int adjZ; -+ // Paper end - - private EnumDirection(int i, int j, int k, String s, EnumDirection.EnumAxisDirection enumdirection_enumaxisdirection, EnumDirection.EnumAxis enumdirection_enumaxis, BaseBlockPosition baseblockposition) { - this.g = i; -@@ -0,0 +0,0 @@ public enum EnumDirection implements INamable { - this.k = enumdirection_enumaxis; - this.l = enumdirection_enumaxisdirection; - this.m = baseblockposition; -+ // Paper start -+ this.adjX = baseblockposition.getX(); -+ this.adjY = baseblockposition.getY(); -+ this.adjZ = baseblockposition.getZ(); -+ // Paper end - } - - public static EnumDirection[] a(Entity entity) { -@@ -0,0 +0,0 @@ public enum EnumDirection implements INamable { - } - - public int getAdjacentX() { -- return this.m.getX(); -+ return this.adjX; // Paper - } - - public int getAdjacentY() { -- return this.m.getY(); -+ return this.adjY; // Paper - } - - public int getAdjacentZ() { -- return this.m.getZ(); -+ return this.adjZ; // Paper - } - - public String m() { diff --git a/Spigot-Server-Patches/Introduce-beacon-activation-deactivation-events.patch b/Spigot-Server-Patches/Introduce-beacon-activation-deactivation-events.patch deleted file mode 100644 index 802e282afd..0000000000 --- a/Spigot-Server-Patches/Introduce-beacon-activation-deactivation-events.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spyridon Pagkalos -Date: Thu, 25 Mar 2021 20:28:04 +0200 -Subject: [PATCH] Introduce beacon activation/deactivation events - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityBeacon.java -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - this.a(SoundEffects.BLOCK_BEACON_AMBIENT); - } - } -+ // Paper start - beacon activation/deactivation events -+ if (!(i1 > 0) && this.levels > 0) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent(); -+ } else if (i1 > 0 && !(this.levels > 0)) { -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); -+ } -+ // Paper end - - if (this.i >= l) { - this.i = -1; -@@ -0,0 +0,0 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic - - @Override - public void al_() { -+ // Paper start - BeaconDeactivatedEvent -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); -+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); -+ // Paper end - this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE); - super.al_(); - } diff --git a/Spigot-Server-Patches/Inventory-close.patch b/Spigot-Server-Patches/Inventory-close.patch deleted file mode 100644 index 8218375461..0000000000 --- a/Spigot-Server-Patches/Inventory-close.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 11 May 2021 14:54:56 -0700 -Subject: [PATCH] Inventory#close - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -0,0 +0,0 @@ public class CraftInventory implements Inventory { - clear(i); - } - } -+ // Paper start -+ @Override -+ public int close() { -+ int count = this.inventory.getViewers().size(); -+ com.google.common.collect.Lists.newArrayList(this.inventory.getViewers()).forEach(HumanEntity::closeInventory); -+ return count; -+ } -+ // Paper end - - @Override - public ListIterator iterator() { diff --git a/Spigot-Server-Patches/Inventory-getHolder-method-without-block-snapshot.patch b/Spigot-Server-Patches/Inventory-getHolder-method-without-block-snapshot.patch deleted file mode 100644 index 61853fe17c..0000000000 --- a/Spigot-Server-Patches/Inventory-getHolder-method-without-block-snapshot.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Wed, 10 Jun 2020 23:55:15 +0100 -Subject: [PATCH] Inventory getHolder method without block snapshot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -0,0 +0,0 @@ import net.minecraft.world.inventory.InventoryCrafting; - import net.minecraft.world.inventory.InventoryEnderChest; - import net.minecraft.world.inventory.InventoryMerchant; - import net.minecraft.world.level.block.entity.IHopper; -+import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.entity.TileEntityBarrel; - import net.minecraft.world.level.block.entity.TileEntityBlastFurnace; - import net.minecraft.world.level.block.entity.TileEntityBrewingStand; -@@ -0,0 +0,0 @@ public class CraftInventory implements Inventory { - return inventory.getOwner(); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public InventoryHolder getHolder(boolean useSnapshot) { -+ return inventory instanceof TileEntity ? ((TileEntity) inventory).getOwner(useSnapshot) : getHolder(); -+ } -+ // Paper end -+ - @Override - public int getMaxStackSize() { - return inventory.getMaxStackSize(); -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryDoubleChest.java -@@ -0,0 +0,0 @@ public class CraftInventoryDoubleChest extends CraftInventory implements DoubleC - return new DoubleChest(this); - } - -+ // Paper start - getHolder without snapshot -+ @Override -+ public DoubleChest getHolder(boolean useSnapshot) { -+ return getHolder(); -+ } -+ // Paper end -+ - @Override - public Location getLocation() { - return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); diff --git a/Spigot-Server-Patches/Inventory-removeItemAnySlot.patch b/Spigot-Server-Patches/Inventory-removeItemAnySlot.patch deleted file mode 100644 index c9b419fec2..0000000000 --- a/Spigot-Server-Patches/Inventory-removeItemAnySlot.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 28 Aug 2018 23:04:15 -0400 -Subject: [PATCH] Inventory#removeItemAnySlot - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java -@@ -0,0 +0,0 @@ public class CraftInventory implements Inventory { - } - - private int first(ItemStack item, boolean withAmount) { -+ // Paper start -+ return first(item, withAmount, getStorageContents()); -+ } -+ -+ private int first(ItemStack item, boolean withAmount, ItemStack[] inventory) { -+ // Paper end - if (item == null) { - return -1; - } -- ItemStack[] inventory = getStorageContents(); -+ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal - for (int i = 0; i < inventory.length; i++) { - if (inventory[i] == null) continue; - -@@ -0,0 +0,0 @@ public class CraftInventory implements Inventory { - - @Override - public HashMap removeItem(ItemStack... items) { -+ // Paper start -+ return removeItem(false, items); -+ } -+ -+ @Override -+ public HashMap removeItemAnySlot(ItemStack... items) { -+ return removeItem(true, items); -+ } -+ -+ private HashMap removeItem(boolean searchEntire, ItemStack... items) { -+ // Paper end - Validate.notNull(items, "Items cannot be null"); - HashMap leftover = new HashMap(); - -@@ -0,0 +0,0 @@ public class CraftInventory implements Inventory { - int toDelete = item.getAmount(); - - while (true) { -- int first = first(item, false); -+ // Paper start - Allow searching entire contents -+ ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); -+ int first = first(item, false, toSearch); -+ // Paper end - - // Drat! we don't have this type in the inventory - if (first == -1) { diff --git a/Spigot-Server-Patches/InventoryCloseEvent-Reason-API.patch b/Spigot-Server-Patches/InventoryCloseEvent-Reason-API.patch deleted file mode 100644 index 12ea07bb83..0000000000 --- a/Spigot-Server-Patches/InventoryCloseEvent-Reason-API.patch +++ /dev/null @@ -1,227 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 3 Jul 2018 21:56:23 -0400 -Subject: [PATCH] InventoryCloseEvent Reason API - -Allows you to determine why an inventory was closed, enabling plugin developers -to "confirm" things based on if it was player triggered close or not. - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // Paper end - if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } - -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper - } - - net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - return OptionalInt.empty(); - } else { - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - this.nextContainerCounter(); -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - // CraftBukkit end - if (this.activeContainer != this.defaultContainer) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - // this.nextContainerCounter(); // CraftBukkit - moved up -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - @Override - public void closeInventory() { -- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit -+ // Paper start -+ closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit -+ // Paper end - this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId)); - this.o(); - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - for (TileEntity tileentity : chunk.getTileEntities().values()) { - if (tileentity instanceof net.minecraft.world.IInventory) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.IInventory) tileentity).getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - } -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // Spigot Start - if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder) { - for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) { -- h.closeInventory(); -+ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - } - } - // Spigot End -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ import org.bukkit.event.inventory.ClickType; - import org.bukkit.event.inventory.CraftItemEvent; - import org.bukkit.event.inventory.InventoryAction; - import org.bukkit.event.inventory.InventoryClickEvent; -+import org.bukkit.event.inventory.InventoryCloseEvent; // Paper - import org.bukkit.event.inventory.InventoryCreativeEvent; - import org.bukkit.event.inventory.InventoryType.SlotType; - import org.bukkit.event.inventory.SmithItemEvent; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInCloseWindow packetplayinclosewindow) { -+ // Paper start -+ handleContainerClose(packetplayinclosewindow, InventoryCloseEvent.Reason.PLAYER); -+ } -+ public void handleContainerClose(PacketPlayInCloseWindow packetplayinclosewindow, InventoryCloseEvent.Reason reason) { -+ // Paper end - PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.getWorldServer()); - - if (this.player.isFrozen()) return; // CraftBukkit -- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit -+ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper - - this.player.o(); - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it - // See SPIGOT-5799, SPIGOT-6145 - if (entityplayer.activeContainer != entityplayer.defaultContainer) { -- entityplayer.closeInventory(); -+ entityplayer.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - this.et(); - super.tick(); - if (!this.world.isClientSide && this.activeContainer != null && !this.activeContainer.canUse(this)) { -- this.closeInventory(); -+ this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } - -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - return 20; - } - -+ // Paper start - unused code, but to keep signatures aligned -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ closeInventory(); -+ this.activeContainer = this.defaultContainer; -+ } -+ // Paper end -+ - public void closeInventory() { - this.activeContainer = this.defaultContainer; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (((EntityPlayer) getHandle()).playerConnection == null) return; - if (getHandle().activeContainer != getHandle().defaultContainer) { - // fire INVENTORY_CLOSE if one already open -- ((EntityPlayer) getHandle()).playerConnection.a(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId)); -+ ((EntityPlayer) getHandle()).playerConnection.handleContainerClose(new PacketPlayInCloseWindow(getHandle().activeContainer.windowId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - EntityPlayer player = (EntityPlayer) getHandle(); - Container container; -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - - @Override - public void closeInventory() { -- getHandle().closeInventory(); -+ // Paper start -+ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); - } -+ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ getHandle().closeInventory(reason); -+ } -+ // Paper end - - @Override - public boolean isBlocking() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - // Close any foreign inventory - if (getHandle().activeContainer != getHandle().defaultContainer) { -- getHandle().closeInventory(); -+ getHandle().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.TELEPORT); // Paper - } - - // Check if the fromWorld and toWorld are the same. -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - - public static Container callInventoryOpenEvent(EntityPlayer player, Container container, boolean cancelled) { - if (player.activeContainer != player.defaultContainer) { // fire INVENTORY_CLOSE if one already open -- player.playerConnection.a(new PacketPlayInCloseWindow(player.activeContainer.windowId)); -+ player.playerConnection.handleContainerClose(new PacketPlayInCloseWindow(player.activeContainer.windowId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - } - - CraftServer server = player.world.getServer(); -@@ -0,0 +0,0 @@ public class CraftEventFactory { - return event; - } - -+ // Paper start -+ /** -+ * Incase plugins hooked into this or Spigot adds a new inventory close event. Prefer to pass a reason -+ * @param human -+ */ -+ @Deprecated - public static void handleInventoryCloseEvent(EntityHuman human) { -- InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView()); -+ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); -+ } -+ public static void handleInventoryCloseEvent(EntityHuman human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { -+ // Paper end -+ InventoryCloseEvent event = new InventoryCloseEvent(human.activeContainer.getBukkitView(), reason); // Paper - human.world.getServer().getPluginManager().callEvent(event); - human.activeContainer.transferTo(human.defaultContainer, human.getBukkitEntity()); - } diff --git a/Spigot-Server-Patches/Item-Rarity-API.patch b/Spigot-Server-Patches/Item-Rarity-API.patch deleted file mode 100644 index 4c3e4b9412..0000000000 --- a/Spigot-Server-Patches/Item-Rarity-API.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 12 Mar 2021 17:09:42 -0800 -Subject: [PATCH] Item Rarity API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -0,0 +0,0 @@ public class Item implements IMaterial { - protected static final UUID g = UUID.fromString("FA233E1C-4180-4865-B01B-BCCE9785ACA3"); - protected static final Random RANDOM = new Random(); - protected final CreativeModeTab i; -- private final EnumItemRarity a; -+ private final EnumItemRarity a; public final EnumItemRarity getItemRarity() { return a; } // Paper - OBFHELPER - private final int maxStackSize; - private final int durability; - private final boolean d; -@@ -0,0 +0,0 @@ public class Item implements IMaterial { - return itemstack.hasEnchantments(); - } - -+ public EnumItemRarity getItemStackRarity(ItemStack itemStack) { return i(itemStack); } // Paper - OBFHELPER - public EnumItemRarity i(ItemStack itemstack) { - if (!itemstack.hasEnchantments()) { - return this.a; -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public int nextEntityId() { - return net.minecraft.world.entity.Entity.nextEntityId(); - } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemRarity(org.bukkit.Material material) { -+ Item item = getItem(material); -+ if (item == null) { -+ throw new IllegalArgumentException(material + " is not an item, and rarity does not apply to blocks"); -+ } -+ return io.papermc.paper.inventory.ItemRarity.values()[item.getItemRarity().ordinal()]; -+ } -+ -+ @Override -+ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { -+ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; -+ } - // Paper end - - /** diff --git a/Spigot-Server-Patches/Item-canEntityPickup.patch b/Spigot-Server-Patches/Item-canEntityPickup.patch deleted file mode 100644 index 7d40d6629a..0000000000 --- a/Spigot-Server-Patches/Item-canEntityPickup.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 5 May 2017 03:57:17 -0500 -Subject: [PATCH] Item#canEntityPickup - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - EntityItem entityitem = (EntityItem) iterator.next(); - - if (!entityitem.dead && !entityitem.getItemStack().isEmpty() && !entityitem.p() && this.i(entityitem.getItemStack())) { -+ // Paper Start -+ if (!entityitem.canMobPickup) { -+ continue; -+ } -+ // Paper End - this.b(entityitem); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - private UUID owner; - public final float b; - private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit -+ public boolean canMobPickup = true; // Paper - - public EntityItem(EntityTypes entitytypes, World world) { - super(entitytypes, world); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -0,0 +0,0 @@ public class CraftItem extends CraftEntity implements Item { - item.age = value; - } - -+ // Paper Start -+ public boolean canMobPickup() { -+ return item.canMobPickup; -+ } -+ -+ public void setCanMobPickup(boolean canMobPickup) { -+ item.canMobPickup = canMobPickup; -+ } -+ // Paper End -+ - @Override - public void setOwner(UUID uuid) { - item.setOwner(uuid); diff --git a/Spigot-Server-Patches/Item-no-age-no-player-pickup.patch b/Spigot-Server-Patches/Item-no-age-no-player-pickup.patch deleted file mode 100644 index 287bfb99b2..0000000000 --- a/Spigot-Server-Patches/Item-no-age-no-player-pickup.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Smith -Date: Sat, 7 Nov 2020 01:20:33 +0000 -Subject: [PATCH] Item no age & no player pickup - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.Item; - import org.bukkit.inventory.ItemStack; - - public class CraftItem extends CraftEntity implements Item { -+ -+ // Paper start -+ private final static int NO_AGE_TIME = (int) Short.MIN_VALUE; -+ private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; -+ // Paper end -+ - private final EntityItem item; - - public CraftItem(CraftServer server, Entity entity, EntityItem item) { -@@ -0,0 +0,0 @@ public class CraftItem extends CraftEntity implements Item { - public void setCanMobPickup(boolean canMobPickup) { - item.canMobPickup = canMobPickup; - } -+ -+ @Override -+ public boolean canPlayerPickup() { -+ return item.pickupDelay != NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public void setCanPlayerPickup(boolean canPlayerPickup) { -+ item.pickupDelay = canPlayerPickup ? 0 : NO_PICKUP_TIME; -+ } -+ -+ @Override -+ public boolean willAge() { -+ return item.age != NO_AGE_TIME; -+ } -+ -+ @Override -+ public void setWillAge(boolean willAge) { -+ item.age = willAge ? 0 : NO_AGE_TIME; -+ } - // Paper End - - @Override diff --git a/Spigot-Server-Patches/ItemStack-getMaxItemUseDuration.patch b/Spigot-Server-Patches/ItemStack-getMaxItemUseDuration.patch deleted file mode 100644 index ad228f3fa5..0000000000 --- a/Spigot-Server-Patches/ItemStack-getMaxItemUseDuration.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 23:00:29 -0400 -Subject: [PATCH] ItemStack#getMaxItemUseDuration - -Allows you to determine how long it takes to use a usable/consumable item - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - this.getItem().b(this, world, entityhuman); - } - -+ public int getItemUseMaxDuration() { return k(); } // Paper - OBFHELPER - public int k() { - return this.getItem().e_(this); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack { - return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize(); - } - -+ // Paper start -+ @Override -+ public int getMaxItemUseDuration() { -+ return handle == null ? 0 : handle.getItemUseMaxDuration(); -+ } -+ // Paper end -+ - @Override - public void addUnsafeEnchantment(Enchantment ench, int level) { - Validate.notNull(ench, "Cannot add null enchantment"); diff --git a/Spigot-Server-Patches/ItemStack-repair-check-API.patch b/Spigot-Server-Patches/ItemStack-repair-check-API.patch deleted file mode 100644 index b397b6702f..0000000000 --- a/Spigot-Server-Patches/ItemStack-repair-check-API.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 22:11:11 -0700 -Subject: [PATCH] ItemStack repair check API - - -diff --git a/src/main/java/net/minecraft/world/item/Item.java b/src/main/java/net/minecraft/world/item/Item.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/Item.java -+++ b/src/main/java/net/minecraft/world/item/Item.java -@@ -0,0 +0,0 @@ public class Item implements IMaterial { - return this.i; - } - -+ public boolean canRepair(ItemStack toBeRepaired, ItemStack repairMaterial) { return a(toBeRepaired, repairMaterial); } // Paper - OBFHELPER - public boolean a(ItemStack itemstack, ItemStack itemstack1) { - return false; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getItemStackRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; - } - -+ @Override -+ public boolean isValidRepairItemStack(org.bukkit.inventory.ItemStack itemToBeRepaired, org.bukkit.inventory.ItemStack repairMaterial) { -+ if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { -+ return false; -+ } -+ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); -+ } -+ - @Override - public int getProtocolVersion() { - return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); -diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.util; -+ -+import org.bukkit.Material; -+import org.bukkit.inventory.ItemStack; -+import org.bukkit.support.AbstractTestingBase; -+import org.junit.Test; -+ -+import static org.junit.Assert.assertFalse; -+import static org.junit.Assert.assertThrows; -+import static org.junit.Assert.assertTrue; -+ -+public class ItemStackRepairCheckTest extends AbstractTestingBase { -+ -+ @Test -+ public void testIsRepariableBy() { -+ ItemStack diamondPick = new ItemStack(Material.DIAMOND_PICKAXE); -+ -+ assertTrue("diamond pick isn't repairable by a diamond", diamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+ -+ @Test -+ public void testCanRepair() { -+ ItemStack diamond = new ItemStack(Material.DIAMOND); -+ -+ assertTrue("diamond can't repair a diamond axe", diamond.canRepair(new ItemStack(Material.DIAMOND_AXE))); -+ } -+ -+ @Test -+ public void testIsNotRepairableBy() { -+ ItemStack notDiamondPick = new ItemStack(Material.ACACIA_SAPLING); -+ -+ assertFalse("acacia sapling is repairable by a diamond", notDiamondPick.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+ -+ @Test -+ public void testCanNotRepair() { -+ ItemStack diamond = new ItemStack(Material.DIAMOND); -+ -+ assertFalse("diamond can repair oak button", diamond.canRepair(new ItemStack(Material.OAK_BUTTON))); -+ } -+ -+ @Test -+ public void testInvalidItem() { -+ ItemStack badItemStack = new ItemStack(Material.ACACIA_WALL_SIGN); -+ -+ assertFalse("acacia wall sign is repairable by diamond", badItemStack.isRepairableBy(new ItemStack(Material.DIAMOND))); -+ } -+} diff --git a/Spigot-Server-Patches/Lag-compensate-eating.patch b/Spigot-Server-Patches/Lag-compensate-eating.patch deleted file mode 100644 index 9c37cd06e9..0000000000 --- a/Spigot-Server-Patches/Lag-compensate-eating.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 15:28:28 -0800 -Subject: [PATCH] Lag compensate eating - -When the server is lagging, players will wait longer when eating. -Change to also use a time check instead if it passes. - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - private int jumpTicks; - private float bw; - public ItemStack activeItem; // Paper - public -- protected int bd; -+ protected int bd; protected final int getEatTimeTicks() { return this.bd; } protected final void setEatTimeTicks(int value) { this.bd = value; } // Paper - OBFHELPER - protected int be; - private BlockPosition bx; - private Optional by; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return ((Byte) this.datawatcher.get(EntityLiving.ag) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND; - } - -+ // Paper start - lag compensate eating -+ protected long eatStartTime; -+ protected int totalEatTimeTicks; -+ // Paper end -+ - private void t() { - if (this.isHandRaised()) { - if (ItemStack.d(this.b(this.getRaisedHand()), this.activeItem)) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.b(this.activeItem, 5); - } - -- if (--this.bd == 0 && !this.world.isClientSide && !this.activeItem.m()) { -+ // Paper start - lag compensate eating -+ // we add 1 to the expected time to avoid lag compensating when we should not -+ boolean shouldLagCompensate = this.activeItem.getItem().isFood() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); -+ if ((--this.bd == 0 || shouldLagCompensate) && !this.world.isClientSide && !this.activeItem.m()) { -+ this.setEatTimeTicks(0); -+ // Paper end - this.s(); - } - } else { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag - this.activeItem = itemstack; -- this.bd = itemstack.k(); -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = itemstack.k(); -+ this.eatStartTime = System.nanoTime(); -+ // Paper end - if (!this.world.isClientSide) { - this.c(1, true); - this.c(2, enumhand == EnumHand.OFF_HAND); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - } else if (!this.isHandRaised() && !this.activeItem.isEmpty()) { - this.activeItem = ItemStack.b; -- this.bd = 0; -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - } - -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - this.activeItem = ItemStack.b; -- this.bd = 0; -+ // Paper start - lag compensate eating -+ this.bd = this.totalEatTimeTicks = 0; -+ this.eatStartTime = -1L; -+ // Paper end - } - - public boolean isBlocking() { diff --git a/Spigot-Server-Patches/Lazily-track-plugin-scoreboards-by-default.patch b/Spigot-Server-Patches/Lazily-track-plugin-scoreboards-by-default.patch deleted file mode 100644 index d50d241b01..0000000000 --- a/Spigot-Server-Patches/Lazily-track-plugin-scoreboards-by-default.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sat, 3 Oct 2020 04:15:09 -0400 -Subject: [PATCH] Lazily track plugin scoreboards by default - -On servers with plugins that constantly churn through scoreboards, there is a risk of -degraded GC performance due to the number of scoreboards held on by weak references. -Most plugins don't even need the (vanilla) functionality that requires all plugin -scoreboards to be tracked by the server. Instead, only track scoreboards when an -objective is added with a non-dummy criteria. - -This is a breaking change, however the change is a much more sensible default. In case -this breaks your workflow you can always force all scoreboards to be tracked with -settings.track-plugin-scoreboards in paper.yml. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void maxJoinsPerTick() { - maxJoinsPerTick = getInt("settings.max-joins-per-tick", 3); - } -+ -+ public static boolean trackPluginScoreboards; -+ private static void trackPluginScoreboards() { -+ trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java -@@ -0,0 +0,0 @@ import org.bukkit.scoreboard.Team; - - public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - final Scoreboard board; -+ boolean registeredGlobally = false; // Paper - - CraftScoreboard(Scoreboard board) { - this.board = board; -@@ -0,0 +0,0 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters"); - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start - the block comment from the old registerNewObjective didnt cause a conflict when rebasing, so this block wasn't added to the adventure registerNewObjective -+ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.IScoreboardCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective); - } -@@ -0,0 +0,0 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard { - Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists"); - - CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); -+ // Paper start -+ if (craftCriteria.criteria != net.minecraft.server.IScoreboardCriteria.DUMMY && !registeredGlobally) { -+ net.minecraft.server.MinecraftServer.getServer().server.getScoreboardManager().registerScoreboardForVanilla(this); -+ registeredGlobally = true; -+ } -+ // Paper end - ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective);*/ // Paper - return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -@@ -0,0 +0,0 @@ public final class CraftScoreboardManager implements ScoreboardManager { - - public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { - mainScoreboard = new CraftScoreboard(scoreboardServer); -+ mainScoreboard.registeredGlobally = true; // Paper - server = minecraftserver; - scoreboards.add(mainScoreboard); - } -@@ -0,0 +0,0 @@ public final class CraftScoreboardManager implements ScoreboardManager { - public CraftScoreboard getNewScoreboard() { - org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot - CraftScoreboard scoreboard = new CraftScoreboard(new ScoreboardServer(server)); -+ // Paper start -+ if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { -+ scoreboard.registeredGlobally = true; - scoreboards.add(scoreboard); -+ } -+ // Paper end - return scoreboard; - } - -+ // Paper start -+ public void registerScoreboardForVanilla(CraftScoreboard scoreboard) { -+ org.spigotmc.AsyncCatcher.catchOp("scoreboard registration"); -+ scoreboards.add(scoreboard); -+ } -+ // Paper end -+ - // CraftBukkit method - public CraftScoreboard getPlayerBoard(CraftPlayer player) { - CraftScoreboard board = playerBoards.get(player); diff --git a/Spigot-Server-Patches/Limit-Client-Sign-length-more.patch b/Spigot-Server-Patches/Limit-Client-Sign-length-more.patch deleted file mode 100644 index 80b4eab604..0000000000 --- a/Spigot-Server-Patches/Limit-Client-Sign-length-more.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Feb 2019 22:18:40 -0500 -Subject: [PATCH] Limit Client Sign length more - -modified clients can send more data from the client -to the server and it would get stored on the sign as sent. - -Mojang has a limit of 384 which is much higher than reasonable. - -the client can barely render around 16 characters as-is, but formatting -codes can get it to be more than 16 actual length. - -Set a limit of 80 which should give an average of 16 characters 2 -sets of legacy formatting codes which should be plenty for all uses. - -This does not strip any existing data from the NBT as plugins -may use this for storing data out of the rendered area. - -it only impacts data sent from the client. - -Set -DPaper.maxSignLength=XX to change limit or -1 to disable - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private int E; - private int receivedMovePackets; - private int processedMovePackets; -+ private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - List lines = new java.util.ArrayList<>(); - - for (int i = 0; i < list.size(); ++i) { -- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(list.get(i)))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. -+ // Paper start - cap line length - modified clients can send longer data than normal -+ String currentLine = list.get(i); -+ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.length() > MAX_SIGN_LINE_LENGTH) { -+ // This handles multibyte characters as 1 -+ int offset = currentLine.codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); -+ if (offset < currentLine.length()) { -+ list.set(i, currentLine = currentLine.substring(0, offset)); -+ } -+ } -+ // Paper end -+ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterAllowedChatCharacters(currentLine))); // Paper - Replaced with anvil color stripping method to stop exploits that allow colored signs to be created. - } - SignChangeEvent event = new SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(worldserver, blockposition), this.getPlayer(), lines); - this.server.getPluginManager().callEvent(event); diff --git a/Spigot-Server-Patches/Limit-item-frame-cursors-on-maps.patch b/Spigot-Server-Patches/Limit-item-frame-cursors-on-maps.patch deleted file mode 100644 index e8ca03f8f2..0000000000 --- a/Spigot-Server-Patches/Limit-item-frame-cursors-on-maps.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yive -Date: Wed, 26 May 2021 15:09:33 -0700 -Subject: [PATCH] Limit item frame cursors on maps - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void allowUsingSignsInsideSpawnProtection() { - allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); - } -+ -+ public int mapItemFrameCursorLimit = 128; -+ private void mapItemFrameCursorLimit() { -+ mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/WorldMap.java -@@ -0,0 +0,0 @@ public class WorldMap extends PersistentBase { - - WorldMapFrame worldmapframe1 = new WorldMapFrame(blockposition, entityitemframe.getDirection().get2DRotationValue() * 90, entityitemframe.getId()); - -+ // Paper start -+ if (this.decorations.size() < entityhuman.world.paperConfig.mapItemFrameCursorLimit) { - this.a(MapIcon.Type.FRAME, entityhuman.world, "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DRotationValue() * 90), (IChatBaseComponent) null); - this.n.put(worldmapframe1.e(), worldmapframe1); -+ } -+ // Paper end - } - - NBTTagCompound nbttagcompound = itemstack.getTag(); diff --git a/Spigot-Server-Patches/Limit-lightning-strike-effect-distance.patch b/Spigot-Server-Patches/Limit-lightning-strike-effect-distance.patch deleted file mode 100644 index 9744c5ddd7..0000000000 --- a/Spigot-Server-Patches/Limit-lightning-strike-effect-distance.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 14 Sep 2018 17:42:08 +0200 -Subject: [PATCH] Limit lightning strike effect distance - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - delayChunkUnloadsBy *= 20; - } - } -+ -+ public double sqrMaxThunderDistance; -+ public double sqrMaxLightningImpactSoundDistance; -+ public double maxLightningFlashDistance; -+ private void lightningStrikeDistanceLimit() { -+ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1); -+ if (sqrMaxThunderDistance > 0) { -+ sqrMaxThunderDistance *= sqrMaxThunderDistance; -+ } -+ -+ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1); -+ if (sqrMaxLightningImpactSoundDistance < 0) { -+ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value -+ } else { -+ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance; -+ } -+ -+ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1); -+ if (maxLightningFlashDistance < 0) { -+ maxLightningFlashDistance = 512; // Vanilla value -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLightning.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java -@@ -0,0 +0,0 @@ public class EntityLightning extends Entity { - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -+ // Paper start - Limit lightning strike effect distance -+ if (distanceSquared <= this.world.paperConfig.sqrMaxLightningImpactSoundDistance) { -+ player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, -+ SoundCategory.WEATHER, this.locX(), this.locY(), this.locZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F)); -+ } -+ -+ if (world.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= world.paperConfig.sqrMaxThunderDistance) { -+ continue; -+ } -+ -+ // Paper end - if (distanceSquared > viewDistance * viewDistance) { - double deltaLength = Math.sqrt(distanceSquared); - double relativeX = player.locX() + (deltaX / deltaLength) * viewDistance; -@@ -0,0 +0,0 @@ public class EntityLightning extends Entity { - } - } - // CraftBukkit end -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); -+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop) - } - - --this.lifeTicks; diff --git a/Spigot-Server-Patches/Limit-recipe-packets.patch b/Spigot-Server-Patches/Limit-recipe-packets.patch deleted file mode 100644 index d93fd17af2..0000000000 --- a/Spigot-Server-Patches/Limit-recipe-packets.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 12 Dec 2020 23:45:28 +0000 -Subject: [PATCH] Limit recipe packets - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); - } - -+ public static int autoRecipeIncrement = 1; -+ public static int autoRecipeLimit = 20; -+ private static void autoRecipieLimiters() { -+ autoRecipeIncrement = getInt("settings.spam-limiter.recipe-spam-increment", autoRecipeIncrement); -+ autoRecipeLimit = getInt("settings.spam-limiter.recipe-spam-limit", autoRecipeLimit); -+ } -+ - public static boolean velocitySupport; - public static boolean velocityOnlineMode; - public static byte[] velocitySecretKey; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.network; - -+import com.destroystokyo.paper.PaperConfig; - import com.google.common.collect.Lists; - import com.google.common.primitives.Doubles; - import com.google.common.primitives.Floats; -@@ -0,0 +0,0 @@ import net.minecraft.world.inventory.InventoryClickType; - import net.minecraft.world.item.crafting.IRecipe; - import net.minecraft.world.level.RayTrace; - import net.minecraft.world.phys.MovingObjectPosition; -+import org.bukkit.Bukkit; // Paper - import org.bukkit.Location; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.event.CraftEventFactory; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); - private final java.util.concurrent.atomic.AtomicInteger tabSpamLimiter = new java.util.concurrent.atomic.AtomicInteger(); // Paper - configurable tab spam limits -+ private final java.util.concurrent.atomic.AtomicInteger recipeSpamPackets = new java.util.concurrent.atomic.AtomicInteger(); // Paper - auto recipe limit - // CraftBukkit end - private int j; - private final Int2ShortMap k = new Int2ShortOpenHashMap(); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; - if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - split to seperate variable -+ if (recipeSpamPackets.get() > 0) recipeSpamPackets.getAndDecrement(); // Paper - /* Use thread-safe field access instead - if (this.chatThrottle > 0) { - --this.chatThrottle; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInAutoRecipe packetplayinautorecipe) { -+ // Paper start -+ if (!Bukkit.isPrimaryThread()) { -+ if (recipeSpamPackets.addAndGet(PaperConfig.autoRecipeIncrement) > PaperConfig.autoRecipeLimit) { -+ minecraftServer.scheduleOnMain(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper -+ return; -+ } -+ } -+ // Paper end - PlayerConnectionUtils.ensureMainThread(packetplayinautorecipe, this, this.player.getWorldServer()); - this.player.resetIdleTimer(); - if (!this.player.isSpectator() && this.player.activeContainer.windowId == packetplayinautorecipe.b() && this.player.activeContainer.c(this.player) && this.player.activeContainer instanceof ContainerRecipeBook) { diff --git a/Spigot-Server-Patches/LivingEntity-Hand-Raised-Item-Use-API.patch b/Spigot-Server-Patches/LivingEntity-Hand-Raised-Item-Use-API.patch deleted file mode 100644 index 5720ca4918..0000000000 --- a/Spigot-Server-Patches/LivingEntity-Hand-Raised-Item-Use-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 Jun 2018 00:21:28 -0400 -Subject: [PATCH] LivingEntity Hand Raised/Item Use API - -How long an entity has raised hands to charge an attack or use an item - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - private float bu; - private int jumpTicks; - private float bw; -- protected ItemStack activeItem; -+ public ItemStack activeItem; // Paper - public - protected int bd; - protected int be; - private BlockPosition bx; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return this.activeItem; - } - -+ public int getItemUseRemainingTime() { return this.dZ(); } // Paper - OBFHELPER - public int dZ() { - return this.bd; - } - -+ public int getHandRaisedTime() { return this.ea(); } // Paper - OBFHELPER - public int ea() { - return this.isHandRaised() ? this.activeItem.k() - this.dZ() : 0; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setShieldBlockingDelay(int delay) { - getHandle().setShieldBlockingDelay(delay); - } -+ -+ @Override -+ public ItemStack getActiveItem() { -+ return getHandle().activeItem.asBukkitMirror(); -+ } -+ -+ @Override -+ public int getItemUseRemainingTime() { -+ return getHandle().getItemUseRemainingTime(); -+ } -+ -+ @Override -+ public int getHandRaisedTime() { -+ return getHandle().getHandRaisedTime(); -+ } -+ -+ @Override -+ public boolean isHandRaised() { -+ return getHandle().isHandRaised(); -+ } -+ -+ @Override -+ public org.bukkit.inventory.EquipmentSlot getHandRaised() { -+ return getHandle().getRaisedHand() == net.minecraft.world.EnumHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/LivingEntity-setKiller.patch b/Spigot-Server-Patches/LivingEntity-setKiller.patch deleted file mode 100644 index b576a86abe..0000000000 --- a/Spigot-Server-Patches/LivingEntity-setKiller.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:49:48 -0500 -Subject: [PATCH] LivingEntity#setKiller - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - public float aE; - @Nullable - public EntityHuman killer; -- protected int lastDamageByPlayerTime; -+ public int lastDamageByPlayerTime; // Paper - protected -> public - protected boolean killed; - protected int ticksFarFromPlayer; - protected float aJ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ import java.util.Iterator; - import java.util.List; - import java.util.Set; - import java.util.UUID; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.effect.MobEffect; -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().killer == null ? null : (Player) getHandle().killer.getBukkitEntity(); - } - -+ // Paper start -+ @Override -+ public void setKiller(Player killer) { -+ EntityPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); -+ getHandle().killer = entityPlayer; -+ getHandle().lastDamager = entityPlayer; -+ getHandle().lastDamageByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity -+ } -+ // Paper end -+ - @Override - public boolean addPotionEffect(PotionEffect effect) { - return addPotionEffect(effect, false); diff --git a/Spigot-Server-Patches/Load-Chunks-for-Login-Asynchronously.patch b/Spigot-Server-Patches/Load-Chunks-for-Login-Asynchronously.patch deleted file mode 100644 index 138ef46918..0000000000 --- a/Spigot-Server-Patches/Load-Chunks-for-Login-Asynchronously.patch +++ /dev/null @@ -1,306 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 19 Apr 2020 04:28:29 -0400 -Subject: [PATCH] Load Chunks for Login Asynchronously - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - return this.serverThreadQueue.executeNext(); - } - -- private boolean tickDistanceManager() { -+ public boolean tickDistanceManager() { // Paper - private -> public - boolean flag = this.chunkMapDistance.a(this.playerChunkMap); - boolean flag1 = this.playerChunkMap.b(); - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.core.NonNullList; - import net.minecraft.core.SectionPosition; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatHoverable; - import net.minecraft.network.chat.ChatMessage; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - private static final Logger LOGGER = LogManager.getLogger(); - public PlayerConnection playerConnection; -+ public NetworkManager networkManager; // Paper - public final MinecraftServer server; - public final PlayerInteractManager playerInteractManager; - public final Deque removeQueue = new ArrayDeque<>(); // Paper -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean joining = true; - public boolean sentListPacket = false; - public boolean supressTrackerForLogin = false; // Paper -+ public boolean didPlayerJoinEvent = false; // Paper - public Integer clientViewDistance; - // CraftBukkit end - public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final Mailbox> mailboxWorldGen; - private final Mailbox> mailboxMain; - public final WorldLoadListener worldLoadListener; -- public final PlayerChunkMap.a chunkDistanceManager; -+ public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER - private final AtomicInteger u; - public final DefinedStructureManager definedStructureManager; // Paper - private -> public - private final File w; -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -0,0 +0,0 @@ public class TicketType { - public static final TicketType FORCED = a("forced", Comparator.comparingLong(ChunkCoordIntPair::pair)); - public static final TicketType LIGHT = a("light", Comparator.comparingLong(ChunkCoordIntPair::pair)); - public static final TicketType PORTAL = a("portal", BaseBlockPosition::compareTo, 300); -+ public static final TicketType LOGIN = a("login", Long::compareTo, 100); // Paper - public static final TicketType POST_TELEPORT = a("post_teleport", Integer::compareTo, 5); - public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - } - // Paper end - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { -- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); -+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper - - if (entityplayer == null) { - this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - } - - this.networkManager.sendPacket(new PacketLoginOutSuccess(this.i)); -- EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); -+ EntityPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.i.getId()); // Paper - - if (entityplayer != null) { - this.g = LoginListener.EnumProtocolState.DELAY_ACCEPT; -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private static final Logger LOGGER = LogManager.getLogger(); - public final NetworkManager networkManager; - private final MinecraftServer minecraftServer; -+ public Runnable playerJoinReady; // Paper - public EntityPlayer player; - private int e; - private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - public void tick() { -+ // Paper start - login async -+ Runnable playerJoinReady = this.playerJoinReady; -+ if (playerJoinReady != null) { -+ this.playerJoinReady = null; -+ playerJoinReady.run(); -+ } -+ // Don't tick if not valid (dead), otherwise we load chunks below -+ if (this.player.valid) { -+ // Paper end - this.syncPosition(); - this.player.lastX = this.player.locX(); - this.player.lastY = this.player.locY(); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.r = null; - this.D = false; - this.E = 0; -- } -+ }} // Paper - end if (valid) - - this.minecraftServer.getMethodProfiler().enter("keepAlive"); - // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutEntityStatus; - import net.minecraft.network.protocol.game.PacketPlayOutExperience; - import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; - import net.minecraft.network.protocol.game.PacketPlayOutHeldItemSlot; -+import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; - import net.minecraft.network.protocol.game.PacketPlayOutLogin; - import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.protocol.game.PacketPlayOutPlayerInfo; -@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer; - import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.PlayerInteractManager; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - private static final SimpleDateFormat g = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); - private final MinecraftServer server; - public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety -- private final Map j = Maps.newHashMap(); -+ private final Map j = Maps.newHashMap();Map getUUIDMap() { return j; } // Paper - OBFHELPER - private final GameProfileBanList k; - private final IpBanList l; - private final OpList operators; - private final WhiteList whitelist; -+ private final Map pendingPlayers = Maps.newHashMap(); // Paper - // CraftBukkit start - // private final Map o; - // private final Map p; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { -+ EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper -+ if (prev != null) { -+ disconnectPendingPlayer(prev); -+ } -+ entityplayer.networkManager = networkmanager; // Paper - entityplayer.loginTime = System.currentTimeMillis(); // Paper - GameProfile gameprofile = entityplayer.getProfile(); - UserCache usercache = this.server.getUserCache(); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - if (nbttagcompound != null && nbttagcompound.hasKey("bukkit")) { - NBTTagCompound bukkit = nbttagcompound.getCompound("bukkit"); - s = bukkit.hasKeyOfType("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; -- } -+ }String lastKnownName = s; // Paper - // CraftBukkit end - - if (nbttagcompound != null) { -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.getRecipeBook().a(entityplayer); - this.sendScoreboard(worldserver1.getScoreboard(), entityplayer); - this.server.invalidatePingSample(); -+ // Paper start - async load spawn in chunk -+ WorldServer finalWorldserver = worldserver1; -+ int chunkX = loc.getBlockX() >> 4; -+ int chunkZ = loc.getBlockZ() >> 4; -+ final ChunkCoordIntPair pos = new ChunkCoordIntPair(chunkX, chunkZ); -+ PlayerChunkMap playerChunkMap = worldserver1.getChunkProvider().playerChunkMap; -+ playerChunkMap.getChunkDistanceManager().addTicketAtLevel(TicketType.LOGIN, pos, 31, pos.pair()); -+ worldserver1.getChunkProvider().tickDistanceManager(); -+ worldserver1.getChunkProvider().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { -+ PlayerChunk updatingChunk = playerChunkMap.getUpdatingChunk(pos.pair()); -+ if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); -+ } else { -+ return java.util.concurrent.CompletableFuture.completedFuture(chunk); -+ } -+ }).thenAccept(chunk -> { -+ playerconnection.playerJoinReady = () -> { -+ postChunkLoadJoin( -+ entityplayer, finalWorldserver, networkmanager, playerconnection, -+ nbttagcompound, networkmanager.getSocketAddress().toString(), lastKnownName -+ ); -+ }; -+ }); -+ } -+ -+ public EntityPlayer getActivePlayer(UUID uuid) { -+ EntityPlayer player = this.getUUIDMap().get(uuid); -+ return player != null ? player : pendingPlayers.get(uuid); -+ } -+ -+ void disconnectPendingPlayer(EntityPlayer entityplayer) { -+ ChatMessage msg = new ChatMessage("multiplayer.disconnect.duplicate_login", new Object[0]); -+ entityplayer.networkManager.sendPacket(new PacketPlayOutKickDisconnect(msg), (future) -> { -+ entityplayer.networkManager.close(msg); -+ entityplayer.networkManager = null; -+ }); -+ } -+ -+ private void postChunkLoadJoin(EntityPlayer entityplayer, WorldServer worldserver1, NetworkManager networkmanager, PlayerConnection playerconnection, NBTTagCompound nbttagcompound, String s1, String s) { -+ pendingPlayers.remove(entityplayer.getUniqueID(), entityplayer); -+ if (!networkmanager.isConnected()) { -+ return; -+ } -+ entityplayer.didPlayerJoinEvent = true; -+ // Paper end - ChatMessage chatmessage; - - if (entityplayer.getProfile().getName().equalsIgnoreCase(s)) { -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - protected void savePlayerFile(EntityPlayer entityplayer) { - if (!entityplayer.getBukkitEntity().isPersistent()) return; // CraftBukkit -+ if (!entityplayer.didPlayerJoinEvent) return; // Paper - If we never fired PJE, we disconnected during login. Data has not changed, and additionally, our saved vehicle is not loaded! If we save now, we will lose our vehicle (CraftBukkit bug) - this.playerFileData.save(entityplayer); - ServerStatisticManager serverstatisticmanager = (ServerStatisticManager) entityplayer.getStatisticManager(); // CraftBukkit - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getName()))); -- cserver.getPluginManager().callEvent(playerQuitEvent); -+ if (entityplayer.didPlayerJoinEvent) cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); - - if (server.isMainThread()) entityplayer.playerTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // this.p.remove(uuid); - // CraftBukkit end - } -+ // Paper start -+ entityplayer1 = pendingPlayers.get(uuid); -+ if (entityplayer1 == entityplayer) { -+ pendingPlayers.remove(uuid); -+ } -+ entityplayer.networkManager = null; -+ // Paper end - - // CraftBukkit start - // this.sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, new EntityPlayer[]{entityplayer})); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); - // CraftBukkit end - -- return playerQuitEvent.quitMessage(); // Paper - Adventure -+ return entityplayer.didPlayerJoinEvent ? playerQuitEvent.quitMessage() : null; // CraftBukkit // Paper - Adventure // Paper - don't print quit if we never printed join - } - - // CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer -@@ -0,0 +0,0 @@ public abstract class PlayerList { - list.add(entityplayer); - } - } -+ // Paper start - check pending players too -+ entityplayer = pendingPlayers.get(uuid); -+ if (entityplayer != null) { -+ this.pendingPlayers.remove(uuid); -+ disconnectPendingPlayer(entityplayer); -+ } -+ // Paper end - - Iterator iterator = list.iterator(); - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.lastY = d1; - this.lastZ = d4; - this.setPosition(d3, d1, d4); -- world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit -+ if (valid) world.getChunkAt((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); // CraftBukkit // Paper - } - - public void d(Vec3D vec3d) { diff --git a/Spigot-Server-Patches/LootTable-API-Replenishable-Lootables-Feature.patch b/Spigot-Server-Patches/LootTable-API-Replenishable-Lootables-Feature.patch deleted file mode 100644 index 3c7ced6215..0000000000 --- a/Spigot-Server-Patches/LootTable-API-Replenishable-Lootables-Feature.patch +++ /dev/null @@ -1,736 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 1 May 2016 21:19:14 -0400 -Subject: [PATCH] LootTable API & Replenishable Lootables Feature - -Provides an API to control the loot table for an object. -Also provides a feature that any Lootable Inventory (Chests in Structures) -can automatically replenish after a given time. - -This feature is good for long term worlds so that newer players -do not suffer with "Every chest has been looted" - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); - log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); - } -+ -+ public boolean autoReplenishLootables; -+ public boolean restrictPlayerReloot; -+ public boolean changeLootTableSeedOnFill; -+ public int maxLootableRefills; -+ public int lootableRegenMin; -+ public int lootableRegenMax; -+ private void enhancedLootables() { -+ autoReplenishLootables = getBoolean("lootables.auto-replenish", false); -+ restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); -+ changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); -+ maxLootableRefills = getInt("lootables.max-refills", -1); -+ lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); -+ lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); -+ if (autoReplenishLootables) { -+ log("Lootables: Replenishing every " + -+ PaperConfig.timeSummary(lootableRegenMin) + " to " + -+ PaperConfig.timeSummary(lootableRegenMax) + -+ (restrictPlayerReloot ? " (restricting reloot)" : "") -+ ); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.entity.TileEntityLootable; -+import org.bukkit.Chunk; -+import org.bukkit.block.Block; -+ -+public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { -+ -+ TileEntityLootable getTileEntity(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ @Override -+ default World getNMSWorld() { -+ return getTileEntity().getWorld(); -+ } -+ -+ default Block getBlock() { -+ final BlockPosition position = getTileEntity().getPosition(); -+ final Chunk bukkitChunk = getTileEntity().getWorld().getChunkAtWorldCoords(position).bukkitChunk; -+ return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getTileEntity().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.level.World; -+import org.bukkit.entity.Entity; -+ -+public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { -+ -+ net.minecraft.world.entity.Entity getHandle(); -+ -+ @Override -+ default LootableInventory getAPILootableInventory() { -+ return this; -+ } -+ -+ default Entity getEntity() { -+ return getHandle().getBukkitEntity(); -+ } -+ -+ @Override -+ default World getNMSWorld() { -+ return getHandle().getWorld(); -+ } -+ -+ @Override -+ default PaperLootableInventoryData getLootableData() { -+ return getHandle().lootableData; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.level.World; -+import org.bukkit.loot.Lootable; -+ -+import java.util.UUID; -+ -+public interface PaperLootableInventory extends LootableInventory, Lootable { -+ -+ PaperLootableInventoryData getLootableData(); -+ LootableInventory getAPILootableInventory(); -+ -+ World getNMSWorld(); -+ -+ default org.bukkit.World getBukkitWorld() { -+ return getNMSWorld().getWorld(); -+ } -+ -+ @Override -+ default boolean isRefillEnabled() { -+ return getNMSWorld().paperConfig.autoReplenishLootables; -+ } -+ -+ @Override -+ default boolean hasBeenFilled() { -+ return getLastFilled() != -1; -+ } -+ -+ @Override -+ default boolean hasPlayerLooted(UUID player) { -+ return getLootableData().hasPlayerLooted(player); -+ } -+ -+ @Override -+ default Long getLastLooted(UUID player) { -+ return getLootableData().getLastLooted(player); -+ } -+ -+ @Override -+ default boolean setHasPlayerLooted(UUID player, boolean looted) { -+ final boolean hasLooted = hasPlayerLooted(player); -+ if (hasLooted != looted) { -+ getLootableData().setPlayerLootedState(player, looted); -+ } -+ return hasLooted; -+ } -+ -+ @Override -+ default boolean hasPendingRefill() { -+ long nextRefill = getLootableData().getNextRefill(); -+ return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getLastFilled() { -+ return getLootableData().getLastFill(); -+ } -+ -+ @Override -+ default long getNextRefill() { -+ return getLootableData().getNextRefill(); -+ } -+ -+ @Override -+ default long setNextRefill(long refillAt) { -+ if (refillAt < -1) { -+ refillAt = -1; -+ } -+ return getLootableData().setNextRefill(refillAt); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.loottable; -+ -+import com.destroystokyo.paper.PaperWorldConfig; -+import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.world.entity.player.EntityHuman; -+import org.bukkit.entity.Player; -+import org.bukkit.loot.LootTable; -+ -+import javax.annotation.Nullable; -+import java.util.HashMap; -+import java.util.Map; -+import java.util.Random; -+import java.util.UUID; -+ -+public class PaperLootableInventoryData { -+ -+ private static final Random RANDOM = new Random(); -+ -+ private long lastFill = -1; -+ private long nextRefill = -1; -+ private int numRefills = 0; -+ private Map lootedPlayers; -+ private final PaperLootableInventory lootable; -+ -+ public PaperLootableInventoryData(PaperLootableInventory lootable) { -+ this.lootable = lootable; -+ } -+ -+ long getLastFill() { -+ return this.lastFill; -+ } -+ -+ long getNextRefill() { -+ return this.nextRefill; -+ } -+ -+ long setNextRefill(long nextRefill) { -+ long prev = this.nextRefill; -+ this.nextRefill = nextRefill; -+ return prev; -+ } -+ -+ public boolean shouldReplenish(@Nullable EntityHuman player) { -+ LootTable table = this.lootable.getLootTable(); -+ -+ // No Loot Table associated -+ if (table == null) { -+ return false; -+ } -+ -+ // ALWAYS process the first fill or if the feature is disabled -+ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { -+ return true; -+ } -+ -+ // Only process refills when a player is set -+ if (player == null) { -+ return false; -+ } -+ -+ // Chest is not scheduled for refill -+ if (this.nextRefill == -1) { -+ return false; -+ } -+ -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ -+ // Check if max refills has been hit -+ if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { -+ return false; -+ } -+ -+ // Refill has not been reached -+ if (this.nextRefill > System.currentTimeMillis()) { -+ return false; -+ } -+ -+ -+ final Player bukkitPlayer = (Player) player.getBukkitEntity(); -+ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); -+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) { -+ event.setCancelled(true); -+ } -+ return event.callEvent(); -+ } -+ public void processRefill(@Nullable EntityHuman player) { -+ this.lastFill = System.currentTimeMillis(); -+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; -+ if (paperConfig.autoReplenishLootables) { -+ int min = paperConfig.lootableRegenMin; -+ int max = paperConfig.lootableRegenMax; -+ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; -+ this.numRefills++; -+ if (paperConfig.changeLootTableSeedOnFill) { -+ this.lootable.setSeed(0); -+ } -+ if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific -+ this.setPlayerLootedState(player.getUniqueID(), true); -+ } -+ } else { -+ this.lootable.clearLootTable(); -+ } -+ } -+ -+ -+ public void loadNbt(NBTTagCompound base) { -+ if (!base.hasKeyOfType("Paper.LootableData", 10)) { // 10 = compound -+ return; -+ } -+ NBTTagCompound comp = base.getCompound("Paper.LootableData"); -+ if (comp.hasKey("lastFill")) { -+ this.lastFill = comp.getLong("lastFill"); -+ } -+ if (comp.hasKey("nextRefill")) { -+ this.nextRefill = comp.getLong("nextRefill"); -+ } -+ -+ if (comp.hasKey("numRefills")) { -+ this.numRefills = comp.getInt("numRefills"); -+ } -+ if (comp.hasKeyOfType("lootedPlayers", 9)) { // 9 = list -+ NBTTagList list = comp.getList("lootedPlayers", 10); // 10 = compound -+ final int size = list.size(); -+ if (size > 0) { -+ this.lootedPlayers = new HashMap<>(list.size()); -+ } -+ for (int i = 0; i < size; i++) { -+ final NBTTagCompound cmp = list.getCompound(i); -+ lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); -+ } -+ } -+ } -+ public void saveNbt(NBTTagCompound base) { -+ NBTTagCompound comp = new NBTTagCompound(); -+ if (this.nextRefill != -1) { -+ comp.setLong("nextRefill", this.nextRefill); -+ } -+ if (this.lastFill != -1) { -+ comp.setLong("lastFill", this.lastFill); -+ } -+ if (this.numRefills != 0) { -+ comp.setInt("numRefills", this.numRefills); -+ } -+ if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { -+ NBTTagList list = new NBTTagList(); -+ for (Map.Entry entry : this.lootedPlayers.entrySet()) { -+ NBTTagCompound cmp = new NBTTagCompound(); -+ cmp.setUUID("UUID", entry.getKey()); -+ cmp.setLong("Time", entry.getValue()); -+ list.add(cmp); -+ } -+ comp.set("lootedPlayers", list); -+ } -+ -+ if (!comp.isEmpty()) { -+ base.set("Paper.LootableData", comp); -+ } -+ } -+ -+ void setPlayerLootedState(UUID player, boolean looted) { -+ if (looted && this.lootedPlayers == null) { -+ this.lootedPlayers = new HashMap<>(); -+ } -+ if (looted) { -+ if (!this.lootedPlayers.containsKey(player)) { -+ this.lootedPlayers.put(player, System.currentTimeMillis()); -+ } -+ } else if (this.lootedPlayers != null) { -+ this.lootedPlayers.remove(player); -+ } -+ } -+ -+ boolean hasPlayerLooted(UUID player) { -+ return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); -+ } -+ -+ Long getLastLooted(UUID player) { -+ return lootedPlayers != null ? lootedPlayers.get(player) : null; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.vehicle.EntityMinecartContainer; -+import net.minecraft.world.level.World; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { -+ -+ private EntityMinecartContainer entity; -+ -+ public PaperMinecartLootableInventory(EntityMinecartContainer entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ entity.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return entity.lootTableSeed; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return entity.lootableData; -+ } -+ -+ @Override -+ public Entity getHandle() { -+ return entity; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ return (LootableInventory) entity.getBukkitEntity(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return entity.world; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.loottable; -+ -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.entity.TileEntityLootable; -+import org.bukkit.Bukkit; -+import org.bukkit.craftbukkit.util.CraftNamespacedKey; -+ -+public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { -+ private TileEntityLootable tileEntityLootable; -+ -+ public PaperTileEntityLootableInventory(TileEntityLootable tileEntityLootable) { -+ this.tileEntityLootable = tileEntityLootable; -+ } -+ -+ @Override -+ public org.bukkit.loot.LootTable getLootTable() { -+ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) { -+ setLootTable(table); -+ setSeed(seed); -+ } -+ -+ @Override -+ public void setLootTable(org.bukkit.loot.LootTable table) { -+ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); -+ } -+ -+ @Override -+ public void setSeed(long seed) { -+ tileEntityLootable.lootTableSeed = seed; -+ } -+ -+ @Override -+ public long getSeed() { -+ return tileEntityLootable.lootTableSeed; -+ } -+ -+ @Override -+ public PaperLootableInventoryData getLootableData() { -+ return tileEntityLootable.lootableData; -+ } -+ -+ @Override -+ public TileEntityLootable getTileEntity() { -+ return tileEntityLootable; -+ } -+ -+ @Override -+ public LootableInventory getAPILootableInventory() { -+ World world = tileEntityLootable.getWorld(); -+ if (world == null) { -+ return null; -+ } -+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getPosition())).getState(); -+ } -+ -+ @Override -+ public World getNMSWorld() { -+ return tileEntityLootable.getWorld(); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - }; - // Paper end - -+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java -@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - public long lootTableSeed; - - // CraftBukkit start -+ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper - public List transaction = new java.util.ArrayList(); - private int maxStack = MAX_STACK; - -@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - @Override - protected void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -+ this.lootableData.saveNbt(nbttagcompound); // Paper - if (this.lootTable != null) { - nbttagcompound.setString("LootTable", this.lootTable.toString()); - if (this.lootTableSeed != 0L) { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); - } -- } else { -+ } if (true) { // Paper - Always save the items, Table may stick around - ContainerUtil.a(nbttagcompound, this.items); - } - -@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - @Override - protected void loadData(NBTTagCompound nbttagcompound) { - super.loadData(nbttagcompound); -+ this.lootableData.loadNbt(nbttagcompound); // Paper - this.items = NonNullList.a(this.getSize(), ItemStack.b); - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); -- } else { -+ } if (true) { // Paper - always load the items, table may still remain - ContainerUtil.b(nbttagcompound, this.items); - } - -@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp - } - - public void d(@Nullable EntityHuman entityhuman) { -- if (this.lootTable != null && this.world.getMinecraftServer() != null) { -+ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper - LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); - - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(entityhuman); // Paper - LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, this.getPositionVector()).a(this.lootTableSeed); - - if (entityhuman != null) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -@@ -0,0 +0,0 @@ public abstract class TileEntityLootable extends TileEntityContainer { - @Nullable - public MinecraftKey lootTable; - public long lootTableSeed; -+ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper - - protected TileEntityLootable(TileEntityTypes tileentitytypes) { - super(tileentitytypes); -@@ -0,0 +0,0 @@ public abstract class TileEntityLootable extends TileEntityContainer { - } - - protected boolean b(NBTTagCompound nbttagcompound) { -+ this.lootableData.loadNbt(nbttagcompound); // Paper - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); -+ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); -- return true; -+ return false; // Paper - always load the items, table may still remain - } else { - return false; - } - } - - protected boolean c(NBTTagCompound nbttagcompound) { -+ this.lootableData.saveNbt(nbttagcompound); // Paper - if (this.lootTable == null) { - return false; - } else { -@@ -0,0 +0,0 @@ public abstract class TileEntityLootable extends TileEntityContainer { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); - } - -- return true; -+ return false; // Paper - always save the items, table may still remain - } - } - - public void d(@Nullable EntityHuman entityhuman) { -- if (this.lootTable != null && this.world.getMinecraftServer() != null) { -+ if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper - LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); - - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); - } - -- this.lootTable = null; -+ //this.lootTable = null; // Paper -+ this.lootableData.processRefill(entityhuman); // Paper - LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, Vec3D.a((BaseBlockPosition) this.position)).a(this.lootTableSeed); - - if (entityhuman != null) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockState - } - - // gets the wrapped TileEntity -- protected T getTileEntity() { -+ public T getTileEntity() { // Paper - protected -> public - return tileEntity; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.inventory.CraftInventory; - import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; - import org.bukkit.inventory.Inventory; -+import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper - --public class CraftChest extends CraftLootable implements Chest { -+public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper - - public CraftChest(final Block block) { - super(block, TileEntityChest.class); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; - import org.bukkit.loot.LootTable; - import org.bukkit.loot.Lootable; - --public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { -+public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper - - public CraftLootable(Block block, Class tileEntityClass) { - super(block, tileEntityClass); -@@ -0,0 +0,0 @@ public abstract class CraftLootable extends CraftC - setLootTable(getLootTable(), seed); - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - public - MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getSnapshot().setLootTable(key, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.minecart.StorageMinecart; - import org.bukkit.inventory.Inventory; - - @SuppressWarnings("deprecation") --public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { -+public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -@@ -0,0 +0,0 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo - return getHandle().lootTableSeed; - } - -- private void setLootTable(LootTable table, long seed) { -+ public void setLootTable(LootTable table, long seed) { // Paper - MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); - getHandle().setLootTable(newKey, seed); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.minecart.HopperMinecart; - import org.bukkit.inventory.Inventory; - --public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { -+public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper - private final CraftInventory inventory; - - public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { diff --git a/Spigot-Server-Patches/MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch b/Spigot-Server-Patches/MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch deleted file mode 100644 index 79bcd84bcf..0000000000 --- a/Spigot-Server-Patches/MC-114618-Fix-EntityAreaEffectCloud-from-going-negat.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 27 May 2019 17:35:39 -0500 -Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative - size - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -+++ b/src/main/java/net/minecraft/world/entity/EntityAreaEffectCloud.java -@@ -0,0 +0,0 @@ public class EntityAreaEffectCloud extends Entity { - super.tick(); - boolean flag = this.k(); - float f = this.getRadius(); -+ // Paper start - fix MC-114618 -+ if (f < 0.0F) { -+ this.die(); -+ return; -+ } -+ // Paper end - - if (this.world.isClientSide) { - ParticleParam particleparam = this.getParticle(); diff --git a/Spigot-Server-Patches/MC-135506-Experience-should-save-as-Integers.patch b/Spigot-Server-Patches/MC-135506-Experience-should-save-as-Integers.patch deleted file mode 100644 index 30c477e40d..0000000000 --- a/Spigot-Server-Patches/MC-135506-Experience-should-save-as-Integers.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 3 Aug 2018 00:04:54 -0400 -Subject: [PATCH] MC-135506: Experience should save as Integers - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - public void saveData(NBTTagCompound nbttagcompound) { - nbttagcompound.setShort("Health", (short) this.e); - nbttagcompound.setShort("Age", (short) this.c); -- nbttagcompound.setShort("Value", (short) this.value); -+ nbttagcompound.setInt("Value", this.value); // Paper - save as Integer - this.savePaperNBT(nbttagcompound); // Paper - } - -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - public void loadData(NBTTagCompound nbttagcompound) { - this.e = nbttagcompound.getShort("Health"); - this.c = nbttagcompound.getShort("Age"); -- this.value = nbttagcompound.getShort("Value"); -+ this.value = nbttagcompound.getInt("Value"); // Paper - load as Integer - this.loadPaperNBT(nbttagcompound); // Paper - } - diff --git a/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch deleted file mode 100644 index d1581e0c3c..0000000000 --- a/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 Mar 2019 16:12:35 -0500 -Subject: [PATCH] MC-145260: Fix Whitelist On/Off inconsistency - -mojang stored whitelist state in 2 places (Whitelist Object, PlayerList) - -some things checked PlayerList, some checked object. This moves -everything to the Whitelist object. - -https://github.com/PaperMC/Paper/issues/1880 - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; - import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.AdvancementDataPlayer; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { - boolean isOp = this.operators.d(gameprofile); -- boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); -+ boolean isWhitelisted = !this.getHasWhitelist() || isOp || this.whitelist.d(gameprofile); - final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -- event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.getHasWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); - event.callEvent(); - if (!event.isWhitelisted()) { - if (loginEvent != null) { diff --git a/Spigot-Server-Patches/MC-145656-Fix-Follow-Range-Initial-Target.patch b/Spigot-Server-Patches/MC-145656-Fix-Follow-Range-Initial-Target.patch deleted file mode 100644 index ec0a78043d..0000000000 --- a/Spigot-Server-Patches/MC-145656-Fix-Follow-Range-Initial-Target.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 18 Dec 2019 22:21:35 -0600 -Subject: [PATCH] MC-145656 Fix Follow Range Initial Target - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); - } -+ -+ public boolean entitiesTargetWithFollowRange = false; -+ private void entitiesTargetWithFollowRange() { -+ entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/PathfinderGoalNearestAttackableTarget.java -@@ -0,0 +0,0 @@ public class PathfinderGoalNearestAttackableTarget exten - this.b = i; - this.a(EnumSet.of(PathfinderGoal.Type.TARGET)); - this.d = (new PathfinderTargetCondition()).a(this.k()).a(predicate); -+ if (entityinsentient.world.paperConfig.entitiesTargetWithFollowRange) this.d.useFollowRange(); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/PathfinderTargetCondition.java -@@ -0,0 +0,0 @@ import java.util.function.Predicate; - import javax.annotation.Nullable; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.ai.attributes.AttributeModifiable; -+import net.minecraft.world.entity.ai.attributes.GenericAttributes; - - public class PathfinderTargetCondition { - -@@ -0,0 +0,0 @@ public class PathfinderTargetCondition { - - if (this.b > 0.0D) { - double d0 = this.g ? entityliving1.A(entityliving) : 1.0D; -- double d1 = Math.max(this.b * d0, 2.0D); -+ double d1 = Math.max((useFollowRange ? getFollowRange(entityliving) : this.b) * d0, 2.0D); // Paper - double d2 = entityliving.h(entityliving1.locX(), entityliving1.locY(), entityliving1.locZ()); - - if (d2 > d1 * d1) { -@@ -0,0 +0,0 @@ public class PathfinderTargetCondition { - return true; - } - } -+ -+ // Paper start -+ private boolean useFollowRange = false; -+ -+ public PathfinderTargetCondition useFollowRange() { -+ this.useFollowRange = true; -+ return this; -+ } -+ -+ private double getFollowRange(EntityLiving entityliving) { -+ AttributeModifiable attributeinstance = entityliving.getAttributeInstance(GenericAttributes.FOLLOW_RANGE); -+ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch b/Spigot-Server-Patches/MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch deleted file mode 100644 index 8959119e76..0000000000 --- a/Spigot-Server-Patches/MC-147729-Drop-items-that-are-extra-from-a-crafting-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Wed, 18 Mar 2020 00:07:46 -0500 -Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe - - -diff --git a/src/main/java/net/minecraft/recipebook/AutoRecipe.java b/src/main/java/net/minecraft/recipebook/AutoRecipe.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/recipebook/AutoRecipe.java -+++ b/src/main/java/net/minecraft/recipebook/AutoRecipe.java -@@ -0,0 +0,0 @@ public class AutoRecipe implements AutoRecipeAbstract -Date: Fri, 21 Aug 2020 21:05:28 -0400 -Subject: [PATCH] MC-197883: Bandaid decode issue - -Mojang has a mix of type and name in the data sets, but you can only -use one. - -This will retry as name if type is asked for and not found. - -diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -+++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java -@@ -0,0 +0,0 @@ public class KeyDispatchCodec extends MapCodec { - - @Override - public DataResult decode(final DynamicOps ops, final MapLike input) { -- final T elementName = input.get(typeKey); -+ // Paper start - bandaid MC-197883 -+ T elementName = input.get(typeKey); -+ if (elementName == null && "type".equals(typeKey)) { -+ elementName = input.get("name"); -+ } -+ // Paper end - if (elementName == null) { - return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input); - } diff --git a/Spigot-Server-Patches/MC-29274-Fix-Wither-hostility-towards-players.patch b/Spigot-Server-Patches/MC-29274-Fix-Wither-hostility-towards-players.patch deleted file mode 100644 index 9d393a6752..0000000000 --- a/Spigot-Server-Patches/MC-29274-Fix-Wither-hostility-towards-players.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: TheShermanTanker -Date: Thu, 1 Oct 2020 01:11:03 +0800 -Subject: [PATCH] MC-29274: Fix Wither hostility towards players - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void setUpdatePathfindingOnBlockUpdate() { - updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); - } -+ -+ public boolean fixWitherTargetingBug = false; -+ private void witherSettings() { -+ fixWitherTargetingBug = getBoolean("fix-wither-targeting-bug", false); -+ log("Withers properly target players: " + fixWitherTargetingBug); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F)); - this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this)); - this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, new Class[0])); -+ if(this.world.paperConfig.fixWitherTargetingBug) this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 0, false, false, null)); // Paper - Fix MC-29274 - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityInsentient.class, 0, false, false, EntityWither.by)); - } - diff --git a/Spigot-Server-Patches/MC-4-Fix-item-position-desync.patch b/Spigot-Server-Patches/MC-4-Fix-item-position-desync.patch deleted file mode 100644 index 8022542323..0000000000 --- a/Spigot-Server-Patches/MC-4-Fix-item-position-desync.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 8 Dec 2020 20:24:52 -0600 -Subject: [PATCH] MC-4: Fix item position desync - -This fixes item position desync (MC-4) by running the item coordinates -through the encode/decode methods of the packet that causes the precision -loss, which forces the server to lose the same precision as the client -keeping them in sync. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void trackPluginScoreboards() { - trackPluginScoreboards = getBoolean("settings.track-plugin-scoreboards", false); - } -+ -+ public static boolean fixEntityPositionDesync = true; -+ private static void fixEntityPositionDesync() { -+ fixEntityPositionDesync = getBoolean("settings.fix-entity-position-desync", fixEntityPositionDesync); -+ } - } -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutEntity.java -@@ -0,0 +0,0 @@ public class PacketPlayOutEntity implements Packet { - protected boolean i; - - public static long a(double d0) { -- return MathHelper.d(d0 * 4096.0D); -+ return MathHelper.d(d0 * 4096.0D); // Paper - check EntityItem#setPositionRaw on update - } - - public static Vec3D a(long i, long j, long k) { -- return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); -+ return (new Vec3D((double) i, (double) j, (double) k)).a(2.44140625E-4D); // Paper - check EntityItem#setPositionRaw on update - } - - public PacketPlayOutEntity() {} -diff --git a/src/main/java/net/minecraft/util/MathHelper.java b/src/main/java/net/minecraft/util/MathHelper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/MathHelper.java -+++ b/src/main/java/net/minecraft/util/MathHelper.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BaseBlockPosition; - public class MathHelper { - - public static final float a = c(2.0F); -- private static final float[] b = (float[]) SystemUtils.a((Object) (new float[65536]), (afloat) -> { -+ private static final float[] b = (float[]) SystemUtils.a((new float[65536]), (afloat) -> { // Paper - decompile error - for (int i = 0; i < afloat.length; ++i) { - afloat[i] = (float) Math.sin((double) i * 3.141592653589793D * 2.0D / 65536.0D); - } -@@ -0,0 +0,0 @@ public class MathHelper { - return d0 < (double) i ? i - 1 : i; - } - -+ public static long floorLong(double d0) { return d(d0); } // Paper - OBFHELPER - public static long d(double d0) { - long i = (long) d0; - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - public Packet P() { - return new PacketPlayOutSpawnEntity(this); - } -+ -+ // Paper start - fix MC-4 -+ public void setPositionRaw(double x, double y, double z) { -+ if (com.destroystokyo.paper.PaperConfig.fixEntityPositionDesync) { -+ // encode/decode from PacketPlayOutEntity -+ x = MathHelper.floorLong(x * 4096.0D) * (1 / 4096.0D); -+ y = MathHelper.floorLong(y * 4096.0D) * (1 / 4096.0D); -+ z = MathHelper.floorLong(z * 4096.0D) * (1 / 4096.0D); -+ } -+ super.setPositionRaw(x, y, z); -+ } -+ // Paper end - fix MC-4 - } diff --git a/Spigot-Server-Patches/MC-50319-Check-other-worlds-for-shooter-of-projectil.patch b/Spigot-Server-Patches/MC-50319-Check-other-worlds-for-shooter-of-projectil.patch deleted file mode 100644 index 38833ae95c..0000000000 --- a/Spigot-Server-Patches/MC-50319-Check-other-worlds-for-shooter-of-projectil.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 17 Oct 2018 19:17:27 -0400 -Subject: [PATCH] MC-50319: Check other worlds for shooter of projectiles - -Say a player shoots an arrow through a nether portal, the game -would lose the shooter for determining things such as Player Kills, -because the entity is in another world. - -If the projectile fails to find the shooter in the current world, check -other worlds. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -0,0 +0,0 @@ public abstract class IProjectile extends Entity { - - @Nullable - public Entity getShooter() { -- return this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); -+ // Paper start - MC-50319 - shooter might be in another world (arrows through portals) -+ Entity entity = this.shooter != null && this.world instanceof WorldServer ? ((WorldServer) this.world).getEntity(this.shooter) : (this.c != 0 ? this.world.getEntity(this.c) : null); -+ if (entity == null) { -+ for (WorldServer world : world.getMinecraftServer().getWorlds()) { -+ entity = world.getEntity(this.shooter); -+ if (entity != null) { -+ break; -+ } -+ } -+ } -+ return entity; -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/MC-Dev-fixes.patch b/Spigot-Server-Patches/MC-Dev-fixes.patch deleted file mode 100644 index e755fd705a..0000000000 --- a/Spigot-Server-Patches/MC-Dev-fixes.patch +++ /dev/null @@ -1,893 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 30 Mar 2016 19:36:20 -0400 -Subject: [PATCH] MC Dev fixes - - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -0,0 +0,0 @@ public class SystemUtils { - return Collectors.toMap(Entry::getKey, Entry::getValue); - } - -- public static > String a(IBlockState iblockstate, Object object) { -- return iblockstate.a((Comparable) object); -+ public static > String a(IBlockState iblockstate, T object) { // Paper - decompile fix -+ return iblockstate.a(object); // Paper - decompile fix - } - - public static String a(String s, @Nullable MinecraftKey minecraftkey) { -@@ -0,0 +0,0 @@ public class SystemUtils { - public static T b(Iterable iterable, @Nullable T t0) { - Iterator iterator = iterable.iterator(); - -- Object object; -- Object object1; -+ T object; // Paper - decompile fix -+ T object1; // Paper - decompile fix - - for (object1 = null; iterator.hasNext(); object1 = object) { - object = iterator.next(); -@@ -0,0 +0,0 @@ public class SystemUtils { - } - - public static Strategy k() { -- return SystemUtils.IdentityHashingStrategy.INSTANCE; -+ return (Strategy) SystemUtils.IdentityHashingStrategy.INSTANCE; // Paper - decompile fix - } - - public static CompletableFuture> b(List> list) { -@@ -0,0 +0,0 @@ public class SystemUtils { - list.forEach((completablefuture1) -> { - int i = list1.size(); - -- list1.add((Object) null); -+ list1.add(null); // Paper - decompile fix - acompletablefuture[i] = completablefuture1.whenComplete((object, throwable) -> { - if (throwable != null) { - completablefuture.completeExceptionally(throwable); -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - }; - } - -- public static Iterable a(BlockPosition blockposition, int i, int j, int k) { -- int l = i + j + k; -+ public static Iterable a(BlockPosition blockposition, int p_i, int p_j, int p_k) { // Paper - decompile issues - variable name conflicts to inner class field refs -+ int l_decompiled = p_i + p_j + p_k; // Paper - decompile issues - int i1 = blockposition.getX(); - int j1 = blockposition.getY(); - int k1 = blockposition.getZ(); -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - ++this.l; - if (this.l > this.j) { - ++this.i; -- if (this.i > l) { -+ if (this.i > l_decompiled) { // Paper - use proper l above (first line of this method) - return (BlockPosition) this.endOfData(); - } - -- this.j = Math.min(i, this.i); -+ this.j = Math.min(p_i, this.i); // Paper - decompile issues - this.l = -this.j; - } - -- this.k = Math.min(j, this.i - Math.abs(this.l)); -+ this.k = Math.min(p_j, this.i - Math.abs(this.l)); // Paper - decompile issues - this.m = -this.k; - } - -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - int i2 = this.m; - int j2 = this.i - Math.abs(l1) - Math.abs(i2); - -- if (j2 <= k) { -+ if (j2 <= p_k) { // Paper - decompile issues - this.n = j2 != 0; - blockposition_mutableblockposition = this.h.d(i1 + l1, j1 + i2, k1 + j2); - } -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - }; - } - -- public static Iterable a(BlockPosition blockposition, int i, EnumDirection enumdirection, EnumDirection enumdirection1) { -+ public static Iterable a(BlockPosition blockposition, int I, EnumDirection enumdirection, EnumDirection enumdirection1) { // Paper - decompile fix - Validate.validState(enumdirection.n() != enumdirection1.n(), "The two directions cannot be on the same axis", new Object[0]); - return () -> { - return new AbstractIterator() { - private final EnumDirection[] e = new EnumDirection[]{enumdirection, enumdirection1, enumdirection.opposite(), enumdirection1.opposite()}; - private final BlockPosition.MutableBlockPosition f = blockposition.i().c(enumdirection1); -- private final int g = 4 * i; -+ private final int g = 4 * I; - private int h = -1; - private int i; - private int j; -diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/RegistryBlockID.java -+++ b/src/main/java/net/minecraft/core/RegistryBlockID.java -@@ -0,0 +0,0 @@ public class RegistryBlockID implements Registry { - this.b.put(t0, i); - - while (this.c.size() <= i) { -- this.c.add((Object) null); -+ this.c.add(null); // Paper - decompile fix - } - - this.c.set(i, t0); -@@ -0,0 +0,0 @@ public class RegistryBlockID implements Registry { - this.a(t0, this.a); - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(T t) { -+ return getId(t); -+ } -+ // Paper end -+ - public int getId(T t0) { - Integer integer = (Integer) this.b.get(t0); - -diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTBase.java -+++ b/src/main/java/net/minecraft/nbt/NBTBase.java -@@ -0,0 +0,0 @@ public interface NBTBase { - - NBTTagType b(); - -- NBTBase clone(); -+ public NBTBase clone(); // Paper - decompile fix - - default String asString() { - return this.toString(); -diff --git a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -+++ b/src/main/java/net/minecraft/nbt/NBTCompressedStreamTools.java -@@ -0,0 +0,0 @@ import java.util.zip.GZIPOutputStream; - import net.minecraft.CrashReport; - import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; -+import io.netty.buffer.ByteBufInputStream; // Paper - - public class NBTCompressedStreamTools { - -@@ -0,0 +0,0 @@ public class NBTCompressedStreamTools { - - public static NBTTagCompound a(DataInput datainput, NBTReadLimiter nbtreadlimiter) throws IOException { - // Spigot start -- if ( datainput instanceof io.netty.buffer.ByteBufInputStream ) -+ if ( datainput instanceof ByteBufInputStream) // Paper - { - datainput = new DataInputStream(new org.spigotmc.LimitStream((InputStream) datainput, nbtreadlimiter)); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagList.java b/src/main/java/net/minecraft/nbt/NBTTagList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagList.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagList.java -@@ -0,0 +0,0 @@ public class NBTTagList extends NBTList { - return "TAG_List"; - } - }; -- private static final ByteSet b = new ByteOpenHashSet(Arrays.asList(1, 2, 3, 4, 5, 6)); -+ private static final ByteSet b = new ByteOpenHashSet(Arrays.asList((byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6)); // Paper - decompiler fix - private final List list; - private byte type; - -diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/EnumProtocol.java -+++ b/src/main/java/net/minecraft/network/EnumProtocol.java -@@ -0,0 +0,0 @@ import javax.annotation.Nullable; - import net.minecraft.SystemUtils; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketListenerPlayIn; -+import net.minecraft.network.protocol.game.PacketListenerPlayOut; - import net.minecraft.network.protocol.game.PacketPlayInAbilities; - import net.minecraft.network.protocol.game.PacketPlayInAdvancements; - import net.minecraft.network.protocol.game.PacketPlayInArmAnimation; -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutWindowItems; - import net.minecraft.network.protocol.game.PacketPlayOutWorldBorder; - import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.network.protocol.game.PacketPlayOutWorldParticles; -+import net.minecraft.network.protocol.handshake.PacketHandshakingInListener; - import net.minecraft.network.protocol.handshake.PacketHandshakingInSetProtocol; - import net.minecraft.network.protocol.login.PacketLoginInCustomPayload; - import net.minecraft.network.protocol.login.PacketLoginInEncryptionBegin; -+import net.minecraft.network.protocol.login.PacketLoginInListener; - import net.minecraft.network.protocol.login.PacketLoginInStart; - import net.minecraft.network.protocol.login.PacketLoginOutCustomPayload; - import net.minecraft.network.protocol.login.PacketLoginOutDisconnect; - import net.minecraft.network.protocol.login.PacketLoginOutEncryptionBegin; -+import net.minecraft.network.protocol.login.PacketLoginOutListener; - import net.minecraft.network.protocol.login.PacketLoginOutSetCompression; - import net.minecraft.network.protocol.login.PacketLoginOutSuccess; -+import net.minecraft.network.protocol.status.PacketStatusInListener; - import net.minecraft.network.protocol.status.PacketStatusInPing; - import net.minecraft.network.protocol.status.PacketStatusInStart; -+import net.minecraft.network.protocol.status.PacketStatusOutListener; - import net.minecraft.network.protocol.status.PacketStatusOutPong; - import net.minecraft.network.protocol.status.PacketStatusOutServerInfo; - import org.apache.logging.log4j.LogManager; - - public enum EnumProtocol { - -- HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a<>()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a<>()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); -+ // Paper - fix decompile error - add generic names to < > like PacketListenerPlayOut -+ HANDSHAKING(-1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketHandshakingInSetProtocol.class, PacketHandshakingInSetProtocol::new))), PLAY(0, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketPlayOutSpawnEntity.class, PacketPlayOutSpawnEntity::new).a(PacketPlayOutSpawnEntityExperienceOrb.class, PacketPlayOutSpawnEntityExperienceOrb::new).a(PacketPlayOutSpawnEntityLiving.class, PacketPlayOutSpawnEntityLiving::new).a(PacketPlayOutSpawnEntityPainting.class, PacketPlayOutSpawnEntityPainting::new).a(PacketPlayOutNamedEntitySpawn.class, PacketPlayOutNamedEntitySpawn::new).a(PacketPlayOutAnimation.class, PacketPlayOutAnimation::new).a(PacketPlayOutStatistic.class, PacketPlayOutStatistic::new).a(PacketPlayOutBlockBreak.class, PacketPlayOutBlockBreak::new).a(PacketPlayOutBlockBreakAnimation.class, PacketPlayOutBlockBreakAnimation::new).a(PacketPlayOutTileEntityData.class, PacketPlayOutTileEntityData::new).a(PacketPlayOutBlockAction.class, PacketPlayOutBlockAction::new).a(PacketPlayOutBlockChange.class, PacketPlayOutBlockChange::new).a(PacketPlayOutBoss.class, PacketPlayOutBoss::new).a(PacketPlayOutServerDifficulty.class, PacketPlayOutServerDifficulty::new).a(PacketPlayOutChat.class, PacketPlayOutChat::new).a(PacketPlayOutTabComplete.class, PacketPlayOutTabComplete::new).a(PacketPlayOutCommands.class, PacketPlayOutCommands::new).a(PacketPlayOutTransaction.class, PacketPlayOutTransaction::new).a(PacketPlayOutCloseWindow.class, PacketPlayOutCloseWindow::new).a(PacketPlayOutWindowItems.class, PacketPlayOutWindowItems::new).a(PacketPlayOutWindowData.class, PacketPlayOutWindowData::new).a(PacketPlayOutSetSlot.class, PacketPlayOutSetSlot::new).a(PacketPlayOutSetCooldown.class, PacketPlayOutSetCooldown::new).a(PacketPlayOutCustomPayload.class, PacketPlayOutCustomPayload::new).a(PacketPlayOutCustomSoundEffect.class, PacketPlayOutCustomSoundEffect::new).a(PacketPlayOutKickDisconnect.class, PacketPlayOutKickDisconnect::new).a(PacketPlayOutEntityStatus.class, PacketPlayOutEntityStatus::new).a(PacketPlayOutExplosion.class, PacketPlayOutExplosion::new).a(PacketPlayOutUnloadChunk.class, PacketPlayOutUnloadChunk::new).a(PacketPlayOutGameStateChange.class, PacketPlayOutGameStateChange::new).a(PacketPlayOutOpenWindowHorse.class, PacketPlayOutOpenWindowHorse::new).a(PacketPlayOutKeepAlive.class, PacketPlayOutKeepAlive::new).a(PacketPlayOutMapChunk.class, PacketPlayOutMapChunk::new).a(PacketPlayOutWorldEvent.class, PacketPlayOutWorldEvent::new).a(PacketPlayOutWorldParticles.class, PacketPlayOutWorldParticles::new).a(PacketPlayOutLightUpdate.class, PacketPlayOutLightUpdate::new).a(PacketPlayOutLogin.class, PacketPlayOutLogin::new).a(PacketPlayOutMap.class, PacketPlayOutMap::new).a(PacketPlayOutOpenWindowMerchant.class, PacketPlayOutOpenWindowMerchant::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMove.class, PacketPlayOutEntity.PacketPlayOutRelEntityMove::new).a(PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook.class, PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook::new).a(PacketPlayOutEntity.PacketPlayOutEntityLook.class, PacketPlayOutEntity.PacketPlayOutEntityLook::new).a(PacketPlayOutEntity.class, PacketPlayOutEntity::new).a(PacketPlayOutVehicleMove.class, PacketPlayOutVehicleMove::new).a(PacketPlayOutOpenBook.class, PacketPlayOutOpenBook::new).a(PacketPlayOutOpenWindow.class, PacketPlayOutOpenWindow::new).a(PacketPlayOutOpenSignEditor.class, PacketPlayOutOpenSignEditor::new).a(PacketPlayOutAutoRecipe.class, PacketPlayOutAutoRecipe::new).a(PacketPlayOutAbilities.class, PacketPlayOutAbilities::new).a(PacketPlayOutCombatEvent.class, PacketPlayOutCombatEvent::new).a(PacketPlayOutPlayerInfo.class, PacketPlayOutPlayerInfo::new).a(PacketPlayOutLookAt.class, PacketPlayOutLookAt::new).a(PacketPlayOutPosition.class, PacketPlayOutPosition::new).a(PacketPlayOutRecipes.class, PacketPlayOutRecipes::new).a(PacketPlayOutEntityDestroy.class, PacketPlayOutEntityDestroy::new).a(PacketPlayOutRemoveEntityEffect.class, PacketPlayOutRemoveEntityEffect::new).a(PacketPlayOutResourcePackSend.class, PacketPlayOutResourcePackSend::new).a(PacketPlayOutRespawn.class, PacketPlayOutRespawn::new).a(PacketPlayOutEntityHeadRotation.class, PacketPlayOutEntityHeadRotation::new).a(PacketPlayOutMultiBlockChange.class, PacketPlayOutMultiBlockChange::new).a(PacketPlayOutSelectAdvancementTab.class, PacketPlayOutSelectAdvancementTab::new).a(PacketPlayOutWorldBorder.class, PacketPlayOutWorldBorder::new).a(PacketPlayOutCamera.class, PacketPlayOutCamera::new).a(PacketPlayOutHeldItemSlot.class, PacketPlayOutHeldItemSlot::new).a(PacketPlayOutViewCentre.class, PacketPlayOutViewCentre::new).a(PacketPlayOutViewDistance.class, PacketPlayOutViewDistance::new).a(PacketPlayOutSpawnPosition.class, PacketPlayOutSpawnPosition::new).a(PacketPlayOutScoreboardDisplayObjective.class, PacketPlayOutScoreboardDisplayObjective::new).a(PacketPlayOutEntityMetadata.class, PacketPlayOutEntityMetadata::new).a(PacketPlayOutAttachEntity.class, PacketPlayOutAttachEntity::new).a(PacketPlayOutEntityVelocity.class, PacketPlayOutEntityVelocity::new).a(PacketPlayOutEntityEquipment.class, PacketPlayOutEntityEquipment::new).a(PacketPlayOutExperience.class, PacketPlayOutExperience::new).a(PacketPlayOutUpdateHealth.class, PacketPlayOutUpdateHealth::new).a(PacketPlayOutScoreboardObjective.class, PacketPlayOutScoreboardObjective::new).a(PacketPlayOutMount.class, PacketPlayOutMount::new).a(PacketPlayOutScoreboardTeam.class, PacketPlayOutScoreboardTeam::new).a(PacketPlayOutScoreboardScore.class, PacketPlayOutScoreboardScore::new).a(PacketPlayOutUpdateTime.class, PacketPlayOutUpdateTime::new).a(PacketPlayOutTitle.class, PacketPlayOutTitle::new).a(PacketPlayOutEntitySound.class, PacketPlayOutEntitySound::new).a(PacketPlayOutNamedSoundEffect.class, PacketPlayOutNamedSoundEffect::new).a(PacketPlayOutStopSound.class, PacketPlayOutStopSound::new).a(PacketPlayOutPlayerListHeaderFooter.class, PacketPlayOutPlayerListHeaderFooter::new).a(PacketPlayOutNBTQuery.class, PacketPlayOutNBTQuery::new).a(PacketPlayOutCollect.class, PacketPlayOutCollect::new).a(PacketPlayOutEntityTeleport.class, PacketPlayOutEntityTeleport::new).a(PacketPlayOutAdvancements.class, PacketPlayOutAdvancements::new).a(PacketPlayOutUpdateAttributes.class, PacketPlayOutUpdateAttributes::new).a(PacketPlayOutEntityEffect.class, PacketPlayOutEntityEffect::new).a(PacketPlayOutRecipeUpdate.class, PacketPlayOutRecipeUpdate::new).a(PacketPlayOutTags.class, PacketPlayOutTags::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketPlayInTeleportAccept.class, PacketPlayInTeleportAccept::new).a(PacketPlayInTileNBTQuery.class, PacketPlayInTileNBTQuery::new).a(PacketPlayInDifficultyChange.class, PacketPlayInDifficultyChange::new).a(PacketPlayInChat.class, PacketPlayInChat::new).a(PacketPlayInClientCommand.class, PacketPlayInClientCommand::new).a(PacketPlayInSettings.class, PacketPlayInSettings::new).a(PacketPlayInTabComplete.class, PacketPlayInTabComplete::new).a(PacketPlayInTransaction.class, PacketPlayInTransaction::new).a(PacketPlayInEnchantItem.class, PacketPlayInEnchantItem::new).a(PacketPlayInWindowClick.class, PacketPlayInWindowClick::new).a(PacketPlayInCloseWindow.class, PacketPlayInCloseWindow::new).a(PacketPlayInCustomPayload.class, PacketPlayInCustomPayload::new).a(PacketPlayInBEdit.class, PacketPlayInBEdit::new).a(PacketPlayInEntityNBTQuery.class, PacketPlayInEntityNBTQuery::new).a(PacketPlayInUseEntity.class, PacketPlayInUseEntity::new).a(PacketPlayInJigsawGenerate.class, PacketPlayInJigsawGenerate::new).a(PacketPlayInKeepAlive.class, PacketPlayInKeepAlive::new).a(PacketPlayInDifficultyLock.class, PacketPlayInDifficultyLock::new).a(PacketPlayInFlying.PacketPlayInPosition.class, PacketPlayInFlying.PacketPlayInPosition::new).a(PacketPlayInFlying.PacketPlayInPositionLook.class, PacketPlayInFlying.PacketPlayInPositionLook::new).a(PacketPlayInFlying.PacketPlayInLook.class, PacketPlayInFlying.PacketPlayInLook::new).a(PacketPlayInFlying.class, PacketPlayInFlying::new).a(PacketPlayInVehicleMove.class, PacketPlayInVehicleMove::new).a(PacketPlayInBoatMove.class, PacketPlayInBoatMove::new).a(PacketPlayInPickItem.class, PacketPlayInPickItem::new).a(PacketPlayInAutoRecipe.class, PacketPlayInAutoRecipe::new).a(PacketPlayInAbilities.class, PacketPlayInAbilities::new).a(PacketPlayInBlockDig.class, PacketPlayInBlockDig::new).a(PacketPlayInEntityAction.class, PacketPlayInEntityAction::new).a(PacketPlayInSteerVehicle.class, PacketPlayInSteerVehicle::new).a(PacketPlayInRecipeSettings.class, PacketPlayInRecipeSettings::new).a(PacketPlayInRecipeDisplayed.class, PacketPlayInRecipeDisplayed::new).a(PacketPlayInItemName.class, PacketPlayInItemName::new).a(PacketPlayInResourcePackStatus.class, PacketPlayInResourcePackStatus::new).a(PacketPlayInAdvancements.class, PacketPlayInAdvancements::new).a(PacketPlayInTrSel.class, PacketPlayInTrSel::new).a(PacketPlayInBeacon.class, PacketPlayInBeacon::new).a(PacketPlayInHeldItemSlot.class, PacketPlayInHeldItemSlot::new).a(PacketPlayInSetCommandBlock.class, PacketPlayInSetCommandBlock::new).a(PacketPlayInSetCommandMinecart.class, PacketPlayInSetCommandMinecart::new).a(PacketPlayInSetCreativeSlot.class, PacketPlayInSetCreativeSlot::new).a(PacketPlayInSetJigsaw.class, PacketPlayInSetJigsaw::new).a(PacketPlayInStruct.class, PacketPlayInStruct::new).a(PacketPlayInUpdateSign.class, PacketPlayInUpdateSign::new).a(PacketPlayInArmAnimation.class, PacketPlayInArmAnimation::new).a(PacketPlayInSpectate.class, PacketPlayInSpectate::new).a(PacketPlayInUseItem.class, PacketPlayInUseItem::new).a(PacketPlayInBlockPlace.class, PacketPlayInBlockPlace::new))), STATUS(1, b().a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketStatusInStart.class, PacketStatusInStart::new).a(PacketStatusInPing.class, PacketStatusInPing::new)).a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketStatusOutServerInfo.class, PacketStatusOutServerInfo::new).a(PacketStatusOutPong.class, PacketStatusOutPong::new))), LOGIN(2, b().a(EnumProtocolDirection.CLIENTBOUND, (new EnumProtocol.a()).a(PacketLoginOutDisconnect.class, PacketLoginOutDisconnect::new).a(PacketLoginOutEncryptionBegin.class, PacketLoginOutEncryptionBegin::new).a(PacketLoginOutSuccess.class, PacketLoginOutSuccess::new).a(PacketLoginOutSetCompression.class, PacketLoginOutSetCompression::new).a(PacketLoginOutCustomPayload.class, PacketLoginOutCustomPayload::new)).a(EnumProtocolDirection.SERVERBOUND, (new EnumProtocol.a()).a(PacketLoginInStart.class, PacketLoginInStart::new).a(PacketLoginInEncryptionBegin.class, PacketLoginInEncryptionBegin::new).a(PacketLoginInCustomPayload.class, PacketLoginInCustomPayload::new))); - - private static final EnumProtocol[] e = new EnumProtocol[4]; - private static final Map>, EnumProtocol> f = Maps.newHashMap(); -@@ -0,0 +0,0 @@ public enum EnumProtocol { - private final List>> b; - - private a() { -- this.a = (Object2IntMap) SystemUtils.a((Object) (new Object2IntOpenHashMap()), (object2intopenhashmap) -> { -+ this.a = (Object2IntMap) SystemUtils.a(new Object2IntOpenHashMap(), (object2intopenhashmap) -> { // Paper - fix decompile error - object2intopenhashmap.defaultReturnValue(-1); - }); - this.b = Lists.newArrayList(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrantmap(resourcepackrepository::a).filter(Objects::nonNull).map(ResourcePackLoader::d).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error - }, this).thenCompose((immutablelist) -> { -- return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); -+ return DataPackResources.a(immutablelist, this.j() ? CommandDispatcher.ServerType.DEDICATED : CommandDispatcher.ServerType.INTEGRATED, this.h(), this.executorService, this); // Paper - decompile error - }).thenAcceptAsync((datapackresources) -> { - this.dataPackResources.close(); - this.dataPackResources = datapackresources; -diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -@@ -0,0 +0,0 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - - public void queueUpdate() { - if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { -- this.b.a((Object) (() -> { -+ this.b.a((() -> { // Paper - decompile error - this.b(); - this.g.set(false); - })); -diff --git a/src/main/java/net/minecraft/server/level/Ticket.java b/src/main/java/net/minecraft/server/level/Ticket.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/Ticket.java -+++ b/src/main/java/net/minecraft/server/level/Ticket.java -@@ -0,0 +0,0 @@ public final class Ticket implements Comparable> { - } else { - int j = Integer.compare(System.identityHashCode(this.a), System.identityHashCode(ticket.a)); - -- return j != 0 ? j : this.a.a().compare(this.identifier, ticket.identifier); -+ return j != 0 ? j : this.a.a().compare(this.identifier, (T)ticket.identifier); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - // CraftBukkit - decompile error -- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(it.unimi.dsi.fastutil.objects.Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { -+ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Object2IntMap.Entry::getIntValue).reversed()).limit(5L).map((it_unimi_dsi_fastutil_objects_object2intmap_entry) -> { // Paper - decompile fix - return it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey() + ":" + it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue(); - }).collect(Collectors.joining(",")); - } catch (Exception exception) { -diff --git a/src/main/java/net/minecraft/stats/ServerStatisticManager.java b/src/main/java/net/minecraft/stats/ServerStatisticManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/stats/ServerStatisticManager.java -+++ b/src/main/java/net/minecraft/stats/ServerStatisticManager.java -@@ -0,0 +0,0 @@ public class ServerStatisticManager extends StatisticManager { - ObjectIterator objectiterator = this.a.object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry> it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - Statistic statistic = (Statistic) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); - - ((JsonObject) map.computeIfAbsent(statistic.getWrapper(), (statisticwrapper) -> { -diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/ArraySetSorted.java -+++ b/src/main/java/net/minecraft/util/ArraySetSorted.java -@@ -0,0 +0,0 @@ public class ArraySetSorted extends AbstractSet { - } - - public static > ArraySetSorted a(int i) { -- return new ArraySetSorted<>(i, Comparator.naturalOrder()); -+ return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } - - private static T[] a(Object[] aobject) { -- return (Object[]) aobject; -+ return (T[])aobject; // Paper - decompile fix - } - - private int c(T t0) { -@@ -0,0 +0,0 @@ public class ArraySetSorted extends AbstractSet { - } - - public boolean remove(Object object) { -- int i = this.c(object); -+ int i = this.c((T)object); // Paper - decompile fix - - if (i >= 0) { - this.d(i); -@@ -0,0 +0,0 @@ public class ArraySetSorted extends AbstractSet { - } - - public boolean contains(Object object) { -- int i = this.c(object); -+ int i = this.c((T)object); // Paper - decompile fix - - return i >= 0; - } -@@ -0,0 +0,0 @@ public class ArraySetSorted extends AbstractSet { - - public U[] toArray(U[] au) { - if (au.length < this.c) { -- return (Object[]) Arrays.copyOf(this.b, this.c, au.getClass()); -+ return (U[])Arrays.copyOf(this.b, this.c, au.getClass()); // Paper - decompile fix - } else { - System.arraycopy(this.b, 0, au, 0, this.c); - if (au.length > this.c) { -diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/RegistryID.java -+++ b/src/main/java/net/minecraft/util/RegistryID.java -@@ -0,0 +0,0 @@ public class RegistryID implements Registry { - - public RegistryID(int i) { - i = (int) ((float) i / 0.8F); -- this.b = (Object[]) (new Object[i]); -+ this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; -- this.d = (Object[]) (new Object[i]); -+ this.d = (K[]) (new Object[i]); // Paper - decompile fix - } - -+ // Paper start - decompile fix -+ @Override -+ public int a(K k) { -+ return getId(k); -+ } -+ // Paper end -+ - public int getId(@Nullable K k0) { - return this.c(this.b(k0, this.d(k0))); - } -@@ -0,0 +0,0 @@ public class RegistryID implements Registry { - K[] ak = this.b; - int[] aint = this.c; - -- this.b = (Object[]) (new Object[i]); -+ this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; -- this.d = (Object[]) (new Object[i]); -+ this.d = (K[]) (new Object[i]); // Paper - decompile fix - this.e = 0; - this.f = 0; - -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -0,0 +0,0 @@ public abstract class IAsyncTaskHandler implements Mailbox implements Mailbox implements Mailbox, AutoCloseable, Runnable { - - public void run() { - try { -- this.a((i) -> { -+ this.a((int i) -> { // Paper - decompile fix - return i == 0; - }); - } finally { -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - } - - private static boolean a(ChunkSection chunksection) { -- Set set = VillagePlaceType.x; -+ Set set = VillagePlaceType.x; // Paper - decompile error - -- set.getClass(); -+ //set.getClass(); // Paper - decompile error - return chunksection.a(set::contains); - } - -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - SectionPosition.b(new ChunkCoordIntPair(blockposition), Math.floorDiv(i, 16)).map((sectionposition) -> { - return Pair.of(sectionposition, this.d(sectionposition.s())); - }).filter((pair) -> { -- return !(Boolean) ((Optional) pair.getSecond()).map(VillagePlaceSection::a).orElse(false); -+ return !(Boolean) (pair.getSecond()).map(VillagePlaceSection::a).orElse(false); // Paper - decompile fix - }).map((pair) -> { - return ((SectionPosition) pair.getFirst()).r(); - }).filter((chunkcoordintpair) -> { -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - - private final Predicate d; - -- private Occupancy(Predicate predicate) { -+ private Occupancy(Predicate predicate) { // Paper - decompile fix - this.d = predicate; - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVindicator.java -@@ -0,0 +0,0 @@ public class EntityVindicator extends EntityIllagerAbstract { - this.goalSelector.a(2, new EntityIllagerAbstract.b(this)); - this.goalSelector.a(3, new EntityRaider.a(this, 10.0F)); - this.goalSelector.a(4, new EntityVindicator.c(this)); -- this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a()); -+ this.targetSelector.a(1, (new PathfinderGoalHurtByTarget(this, new Class[]{EntityRaider.class})).a(new Class[0])); // Paper - decompile fix - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, true)); - this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityIronGolem.class, true)); -diff --git a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -+++ b/src/main/java/net/minecraft/world/entity/npc/VillagerTrades.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; - - public class VillagerTrades { - -- public static final Map> a = (Map) SystemUtils.a((Object) Maps.newHashMap(), (hashmap) -> { -+ public static final Map> a = SystemUtils.a(Maps.newHashMap(), (hashmap) -> { // Paper - decompile fix - hashmap.put(VillagerProfession.FARMER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHEAT, 20, 16, 2), new VillagerTrades.b(Items.POTATO, 26, 16, 2), new VillagerTrades.b(Items.CARROT, 22, 16, 2), new VillagerTrades.b(Items.BEETROOT, 15, 16, 2), new VillagerTrades.h(Items.BREAD, 1, 6, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.PUMPKIN, 6, 12, 10), new VillagerTrades.h(Items.PUMPKIN_PIE, 1, 4, 5), new VillagerTrades.h(Items.APPLE, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.COOKIE, 3, 18, 10), new VillagerTrades.b(Blocks.MELON, 4, 12, 20)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Blocks.CAKE, 1, 1, 12, 15), new VillagerTrades.i(MobEffects.NIGHT_VISION, 100, 15), new VillagerTrades.i(MobEffects.JUMP, 160, 15), new VillagerTrades.i(MobEffects.WEAKNESS, 140, 15), new VillagerTrades.i(MobEffects.BLINDNESS, 120, 15), new VillagerTrades.i(MobEffects.POISON, 280, 15), new VillagerTrades.i(MobEffects.SATURATION, 7, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GOLDEN_CARROT, 3, 3, 30), new VillagerTrades.h(Items.GLISTERING_MELON_SLICE, 4, 3, 30)}))); -- hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); -+ hashmap.put(VillagerProfession.FISHERMAN, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 20, 16, 2), new VillagerTrades.b(Items.COAL, 10, 16, 2), new VillagerTrades.g(Items.COD, 6, Items.COOKED_COD, 6, 16, 1), new VillagerTrades.h(Items.COD_BUCKET, 3, 1, 16, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COD, 15, 16, 10), new VillagerTrades.g(Items.SALMON, 6, Items.COOKED_SALMON, 6, 16, 5), new VillagerTrades.h(Items.rn, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SALMON, 13, 16, 20), new VillagerTrades.e(Items.FISHING_ROD, 3, 3, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.TROPICAL_FISH, 6, 12, 30)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PUFFERFISH, 4, 12, 30), new VillagerTrades.c(1, 12, 30, ImmutableMap.builder().put(VillagerType.PLAINS, Items.OAK_BOAT).put(VillagerType.TAIGA, Items.SPRUCE_BOAT).put(VillagerType.SNOW, Items.SPRUCE_BOAT).put(VillagerType.DESERT, Items.JUNGLE_BOAT).put(VillagerType.JUNGLE, Items.JUNGLE_BOAT).put(VillagerType.SAVANNA, Items.ACACIA_BOAT).put(VillagerType.SWAMP, Items.DARK_OAK_BOAT).build())}))); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.SHEPHERD, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Blocks.WHITE_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BROWN_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.BLACK_WOOL, 18, 16, 2), new VillagerTrades.b(Blocks.GRAY_WOOL, 18, 16, 2), new VillagerTrades.h(Items.SHEARS, 2, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WHITE_DYE, 12, 16, 10), new VillagerTrades.b(Items.GRAY_DYE, 12, 16, 10), new VillagerTrades.b(Items.BLACK_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIGHT_BLUE_DYE, 12, 16, 10), new VillagerTrades.b(Items.LIME_DYE, 12, 16, 10), new VillagerTrades.h(Blocks.WHITE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.ORANGE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.YELLOW_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIME_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PINK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.CYAN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.PURPLE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLUE_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BROWN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.GREEN_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.RED_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.BLACK_WOOL, 1, 1, 16, 5), new VillagerTrades.h(Blocks.WHITE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.ORANGE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.MAGENTA_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.YELLOW_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIME_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PINK_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.LIGHT_GRAY_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.CYAN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.PURPLE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLUE_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BROWN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.GREEN_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.RED_CARPET, 1, 4, 16, 5), new VillagerTrades.h(Blocks.BLACK_CARPET, 1, 4, 16, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.YELLOW_DYE, 12, 16, 20), new VillagerTrades.b(Items.LIGHT_GRAY_DYE, 12, 16, 20), new VillagerTrades.b(Items.ORANGE_DYE, 12, 16, 20), new VillagerTrades.b(Items.RED_DYE, 12, 16, 20), new VillagerTrades.b(Items.PINK_DYE, 12, 16, 20), new VillagerTrades.h(Blocks.WHITE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.YELLOW_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.RED_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLACK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.BROWN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.CYAN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.GREEN_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_BLUE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIGHT_GRAY_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.LIME_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.MAGENTA_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.ORANGE_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PINK_BED, 3, 1, 12, 10), new VillagerTrades.h(Blocks.PURPLE_BED, 3, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BROWN_DYE, 12, 16, 30), new VillagerTrades.b(Items.PURPLE_DYE, 12, 16, 30), new VillagerTrades.b(Items.BLUE_DYE, 12, 16, 30), new VillagerTrades.b(Items.GREEN_DYE, 12, 16, 30), new VillagerTrades.b(Items.MAGENTA_DYE, 12, 16, 30), new VillagerTrades.b(Items.CYAN_DYE, 12, 16, 30), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 12, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 12, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.PAINTING, 2, 3, 30)}))); - hashmap.put(VillagerProfession.FLETCHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STICK, 32, 16, 2), new VillagerTrades.h(Items.ARROW, 1, 16, 1), new VillagerTrades.g(Blocks.GRAVEL, 10, Items.FLINT, 10, 12, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FLINT, 26, 12, 10), new VillagerTrades.h(Items.BOW, 2, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.STRING, 14, 16, 20), new VillagerTrades.h(Items.CROSSBOW, 3, 1, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.FEATHER, 24, 16, 30), new VillagerTrades.e(Items.BOW, 2, 3, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.es, 8, 12, 30), new VillagerTrades.e(Items.CROSSBOW, 3, 3, 15), new VillagerTrades.j(Items.ARROW, 5, Items.TIPPED_ARROW, 5, 2, 12, 30)}))); -- hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); -+ hashmap.put(VillagerProfession.LIBRARIAN, a(ImmutableMap.builder().put(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.d(1), new VillagerTrades.h(Blocks.BOOKSHELF, 9, 1, 12, 1)}).put(2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.BOOK, 4, 12, 10), new VillagerTrades.d(5), new VillagerTrades.h(Items.rk, 1, 1, 5)}).put(3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.INK_SAC, 5, 12, 20), new VillagerTrades.d(10), new VillagerTrades.h(Items.az, 1, 4, 10)}).put(4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.WRITABLE_BOOK, 2, 12, 30), new VillagerTrades.d(15), new VillagerTrades.h(Items.CLOCK, 5, 1, 15), new VillagerTrades.h(Items.COMPASS, 4, 1, 15)}).put(5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.NAME_TAG, 20, 1, 30)}).build())); // Paper - add to ImmutableMap..builder() - hashmap.put(VillagerProfession.CARTOGRAPHER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.PAPER, 24, 16, 2), new VillagerTrades.h(Items.MAP, 7, 1, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.dP, 11, 16, 10), new VillagerTrades.k(13, StructureGenerator.MONUMENT, MapIcon.Type.MONUMENT, 12, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COMPASS, 1, 12, 20), new VillagerTrades.k(14, StructureGenerator.MANSION, MapIcon.Type.MANSION, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.ITEM_FRAME, 7, 1, 15), new VillagerTrades.h(Items.WHITE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_BLUE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.RED_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PINK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GREEN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIME_BANNER, 3, 1, 15), new VillagerTrades.h(Items.GRAY_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BLACK_BANNER, 3, 1, 15), new VillagerTrades.h(Items.PURPLE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.MAGENTA_BANNER, 3, 1, 15), new VillagerTrades.h(Items.CYAN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.BROWN_BANNER, 3, 1, 15), new VillagerTrades.h(Items.YELLOW_BANNER, 3, 1, 15), new VillagerTrades.h(Items.ORANGE_BANNER, 3, 1, 15), new VillagerTrades.h(Items.LIGHT_GRAY_BANNER, 3, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.h(Items.GLOBE_BANNER_PATTERN, 8, 1, 30)}))); - hashmap.put(VillagerProfession.CLERIC, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.ROTTEN_FLESH, 32, 16, 2), new VillagerTrades.h(Items.REDSTONE, 1, 2, 1)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.GOLD_INGOT, 3, 12, 10), new VillagerTrades.h(Items.LAPIS_LAZULI, 1, 1, 5)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.RABBIT_FOOT, 2, 12, 20), new VillagerTrades.h(Blocks.GLOWSTONE, 4, 1, 12, 10)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.SCUTE, 4, 12, 30), new VillagerTrades.b(Items.GLASS_BOTTLE, 9, 12, 30), new VillagerTrades.h(Items.ENDER_PEARL, 5, 1, 15)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.NETHER_WART, 22, 12, 30), new VillagerTrades.h(Items.EXPERIENCE_BOTTLE, 3, 1, 30)}))); - hashmap.put(VillagerProfession.ARMORER, a(ImmutableMap.of(1, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.COAL, 15, 16, 2), new VillagerTrades.h(new ItemStack(Items.IRON_LEGGINGS), 7, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_BOOTS), 4, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_HELMET), 5, 1, 12, 1, 0.2F), new VillagerTrades.h(new ItemStack(Items.IRON_CHESTPLATE), 9, 1, 12, 1, 0.2F)}, 2, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.IRON_INGOT, 4, 12, 10), new VillagerTrades.h(new ItemStack(Items.rj), 36, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_BOOTS), 1, 1, 12, 5, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_LEGGINGS), 3, 1, 12, 5, 0.2F)}, 3, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.b(Items.LAVA_BUCKET, 1, 12, 20), new VillagerTrades.b(Items.DIAMOND, 1, 12, 20), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_HELMET), 1, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.CHAINMAIL_CHESTPLATE), 4, 1, 12, 10, 0.2F), new VillagerTrades.h(new ItemStack(Items.SHIELD), 5, 1, 12, 10, 0.2F)}, 4, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_LEGGINGS, 14, 3, 15, 0.2F), new VillagerTrades.e(Items.DIAMOND_BOOTS, 8, 3, 15, 0.2F)}, 5, new VillagerTrades.IMerchantRecipeOption[]{new VillagerTrades.e(Items.DIAMOND_HELMET, 8, 3, 30, 0.2F), new VillagerTrades.e(Items.DIAMOND_CHESTPLATE, 16, 3, 30, 0.2F)}))); -diff --git a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -+++ b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java -@@ -0,0 +0,0 @@ public class CraftingManager extends ResourceDataJson { - } - - this.recipes = (Map) map1.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry1) -> { -- return (entry1.getValue()); // CraftBukkit -+ return entry1.getValue(); // CraftBukkit // Paper - decompile fix - *shrugs internally* - })); - CraftingManager.LOGGER.info("Loaded {} recipes", map1.size()); - } -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -0,0 +0,0 @@ public interface IEntityAccess { - - @Nullable - default T a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -- return this.a(this.a(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); -+ return this.a(this.a(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - - @Nullable - default T b(Class oclass, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2, AxisAlignedBB axisalignedbb) { -- return this.a(this.b(oclass, axisalignedbb, (Predicate) null), pathfindertargetcondition, entityliving, d0, d1, d2); -+ return this.a(this.b(oclass, axisalignedbb, null), pathfindertargetcondition, entityliving, d0, d1, d2); // Paper - decompile fix - } - - @Nullable - default T a(List list, PathfinderTargetCondition pathfindertargetcondition, @Nullable EntityLiving entityliving, double d0, double d1, double d2) { - double d3 = -1.0D; - T t0 = null; -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t1 = (EntityLiving) iterator.next(); -+ T t1 = iterator.next(); // Paper - decompile fix - - if (pathfindertargetcondition.a(entityliving, t1)) { - double d4 = t1.h(d0, d1, d2); -@@ -0,0 +0,0 @@ public interface IEntityAccess { - default List a(Class oclass, PathfinderTargetCondition pathfindertargetcondition, EntityLiving entityliving, AxisAlignedBB axisalignedbb) { - List list = this.a(oclass, axisalignedbb, (Predicate) null); - List list1 = Lists.newArrayList(); -- Iterator iterator = list.iterator(); -+ Iterator iterator = list.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (EntityLiving) iterator.next(); -+ T t0 = iterator.next(); // Paper - decompile fix - - if (pathfindertargetcondition.a(entityliving, t0)) { - list1.add(t0); -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -0,0 +0,0 @@ public class NextTickListEntry { - return this.a.hashCode(); - } - -- public static Comparator> a() { -+ public static Comparator a() { // Paper - decompile fix - return Comparator.comparingLong((nextticklistentry) -> { -- return nextticklistentry.b; -+ return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix - }).thenComparing((nextticklistentry) -> { -- return nextticklistentry.c; -+ return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix - }).thenComparingLong((nextticklistentry) -> { -- return nextticklistentry.f; -+ return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix - }); - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - public final class BiomeBase { - - public static final Logger LOGGER = LogManager.getLogger(); -+ // Paper start -+ private static class dProxy extends BiomeBase.d { -+ private dProxy(Precipitation biomebase_precipitation, float f, TemperatureModifier biomebase_temperaturemodifier, float f1) { -+ super(biomebase_precipitation, f, biomebase_temperaturemodifier, f1); -+ } -+ }; -+ // Paper end - public static final Codec b = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -+ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper - return biomebase.j; - }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { - return biomebase.o; -@@ -0,0 +0,0 @@ public final class BiomeBase { - })).apply(instance, BiomeBase::new); - }); - public static final Codec c = RecordCodecBuilder.create((instance) -> { -- return instance.group(BiomeBase.d.a.forGetter((biomebase) -> { -+ return instance.group(dProxy.a.forGetter((biomebase) -> { // Paper - return biomebase.j; - }), BiomeBase.Geography.r.fieldOf("category").forGetter((biomebase) -> { - return biomebase.o; -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -0,0 +0,0 @@ public class TileEntityPiston extends TileEntity implements ITickable { - private static void a(EnumDirection enumdirection, Entity entity, double d0, EnumDirection enumdirection1) { - TileEntityPiston.h.set(enumdirection); - entity.move(EnumMoveType.PISTON, new Vec3D(d0 * (double) enumdirection1.getAdjacentX(), d0 * (double) enumdirection1.getAdjacentY(), d0 * (double) enumdirection1.getAdjacentZ())); -- TileEntityPiston.h.set((Object) null); -+ TileEntityPiston.h.set(null); // Paper - decompile fix - } - - private void g(float f) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -@@ -0,0 +0,0 @@ public abstract class IBlockDataHolder { - } else { - IBlockState iblockstate = (IBlockState) entry.getKey(); - -- return iblockstate.getName() + "=" + this.a(iblockstate, (Comparable) entry.getValue()); -+ return iblockstate.getName() + "=" + this.a((IBlockState) iblockstate, (Comparable) entry.getValue()); // Paper - decompile fix - } - } - -- private > String a(IBlockState iblockstate, Comparable comparable) { -+ private > String a(IBlockState iblockstate, T comparable) { // Paper - decompile error - return iblockstate.a(comparable); - } - }; -@@ -0,0 +0,0 @@ public abstract class IBlockDataHolder { - } - - public > S a(IBlockState iblockstate) { -- return this.set(iblockstate, (Comparable) a(iblockstate.getValues(), (Object) this.get(iblockstate))); -+ return this.set(iblockstate, a(iblockstate.getValues(), this.get(iblockstate))); // Paper - decompile error - } - - protected static T a(Collection collection, T t0) { -- Iterator iterator = collection.iterator(); -+ Iterator iterator = collection.iterator(); // Paper - - do { - if (!iterator.hasNext()) { -@@ -0,0 +0,0 @@ public abstract class IBlockDataHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.c); - } else { -- return (Comparable) iblockstate.getType().cast(comparable); -+ return iblockstate.getType().cast(comparable); // Paper - decompile error - } - } - -@@ -0,0 +0,0 @@ public abstract class IBlockDataHolder { - if (comparable == null) { - throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.c); - } else if (comparable == v0) { -- return this; -+ return (S) this; // Paper - decompile error - } else { - S s0 = this.e.get(iblockstate, v0); - -@@ -0,0 +0,0 @@ public abstract class IBlockDataHolder { - return codec.dispatch("Name", (iblockdataholder) -> { - return iblockdataholder.c; - }, (object) -> { -- S s0 = (IBlockDataHolder) function.apply(object); -+ S s0 = function.apply(object); // Paper - decompile error - - return s0.getStateMap().isEmpty() ? Codec.unit(s0) : s0.d.fieldOf("Properties").codec(); - }); -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -@@ -0,0 +0,0 @@ public class BlockStateEnum & INamable> extends IBlockState - protected BlockStateEnum(String s, Class oclass, Collection collection) { - super(s, oclass); - this.a = ImmutableSet.copyOf(collection); -- Iterator iterator = collection.iterator(); -+ Iterator iterator = collection.iterator(); // Paper - decompile fix - - while (iterator.hasNext()) { -- T t0 = (Enum) iterator.next(); -+ T t0 = iterator.next(); // Paper - Decompile fix - String s1 = ((INamable) t0).getName(); - - if (this.b.containsKey(s1)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -@@ -0,0 +0,0 @@ public abstract class IBlockState> { - private final Codec> e; - - protected IBlockState(String s, Class oclass) { -- this.d = Codec.STRING.comapFlatMap((s1) -> { -- return (DataResult) this.b(s1).map(DataResult::success).orElseGet(() -> { -- return DataResult.error("Unable to read property: " + this + " with value: " + s1); -- }); -- }, this::a); -- this.e = this.d.xmap(this::b, IBlockState.a::b); -+ this.d = Codec.STRING.comapFlatMap((s1) -> this.b(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error -+ return DataResult.error("Unable to read property: " + this + " with value: " + s1); -+ }), this::a); -+ this.e = this.d.xmap(this::b, (IBlockState.a param) -> param.b()); // Paper - decompile fix - this.a = oclass; - this.b = s; - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -0,0 +0,0 @@ public class IOWorker implements AutoCloseable { - return this.a(() -> { - try { - this.d.a(); -- return Either.left((Object) null); -+ return Either.left(null); // Paper - decompile error - } catch (Exception exception) { - IOWorker.LOGGER.warn("Failed to synchronized chunks", exception); - return Either.right(exception); -@@ -0,0 +0,0 @@ public class IOWorker implements AutoCloseable { - } - - private void c() { -- this.c.a((Object) (new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); -+ this.c.a((new PairedQueue.b(IOWorker.Priority.LOW.ordinal(), this::b))); // Paper - decompile error - } - - private void a(ChunkCoordIntPair chunkcoordintpair, IOWorker.a ioworker_a) { - try { - this.d.write(chunkcoordintpair, ioworker_a.a); -- ioworker_a.b.complete((Object) null); -+ ioworker_a.b.complete(null); // Paper - decompile fix - } catch (Exception exception) { - IOWorker.LOGGER.error("Failed to store chunk {}", chunkcoordintpair, exception); - ioworker_a.b.completeExceptionally(exception); -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -0,0 +0,0 @@ public class EnderDragonBattle { - } - } - -- worldgenendtrophy.b((WorldGenFeatureConfiguration) WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); -+ worldgenendtrophy.b(WorldGenFeatureConfiguration.k).a(this.world, this.world.getChunkProvider().getChunkGenerator(), new Random(), this.exitPortalLocation); // Paper - decompile fix - } - - private EntityEnderDragon o() { -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -0,0 +0,0 @@ public abstract class StructureGenerator - public static final StructureGenerator BASTION_REMNANT = a("Bastion_Remnant", new WorldGenFeatureBastionRemnant(WorldGenFeatureVillageConfiguration.a), WorldGenStage.Decoration.SURFACE_STRUCTURES); - public static final List> t = ImmutableList.of(StructureGenerator.PILLAGER_OUTPOST, StructureGenerator.VILLAGE, StructureGenerator.NETHER_FOSSIL); - private static final MinecraftKey w = new MinecraftKey("jigsaw"); -- private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); -+ private static final Map x = ImmutableMap.builder().put(new MinecraftKey("nvi"), StructureGenerator.w).put(new MinecraftKey("pcp"), StructureGenerator.w).put(new MinecraftKey("bastionremnant"), StructureGenerator.w).put(new MinecraftKey("runtime"), StructureGenerator.w).build(); // Paper - decompile fix - private final Codec>> y; - - private static > F a(String s, F f0, WorldGenStage.Decoration worldgenstage_decoration) { - StructureGenerator.a.put(s.toLowerCase(Locale.ROOT), f0); - StructureGenerator.u.put(f0, worldgenstage_decoration); -- return (StructureGenerator) IRegistry.a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), (Object) f0); -+ return (F) IRegistry.>a(IRegistry.STRUCTURE_FEATURE, s.toLowerCase(Locale.ROOT), f0); // Paper - decomp fix - } - - public StructureGenerator(Codec codec) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage= l) { -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldPersistentData.java -@@ -0,0 +0,0 @@ public class WorldPersistentData { - if (t0 != null) { - return t0; - } else { -- T t1 = (PersistentBase) supplier.get(); -+ T t1 = supplier.get(); // Paper - decompile fix - - this.a(t1); - return t1; -@@ -0,0 +0,0 @@ public class WorldPersistentData { - - @Nullable - public T b(Supplier supplier, String s) { -- PersistentBase persistentbase = (PersistentBase) this.data.get(s); -+ T persistentbase = (T) this.data.get(s); // Paper - decompile fix - - if (persistentbase == null && !this.data.containsKey(s)) { - persistentbase = this.c(supplier, s); -@@ -0,0 +0,0 @@ public class WorldPersistentData { - File file = this.a(s); - - if (file.exists()) { -- T t0 = (PersistentBase) supplier.get(); -+ T t0 = supplier.get(); // Paper - decompile fix - NBTTagCompound nbttagcompound = this.a(s, SharedConstants.getGameVersion().getWorldVersion()); - - t0.a(nbttagcompound.getCompound("data")); -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootEntryAbstract.java -@@ -0,0 +0,0 @@ public abstract class LootEntryAbstract implements LootEntryChildren { - - // CraftBukkit start - @Override -- public final void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { -+ public void a(JsonObject jsonobject, T t0, JsonSerializationContext jsonserializationcontext) { // Paper - remove final - if (!org.apache.commons.lang3.ArrayUtils.isEmpty(t0.d)) { - jsonobject.add("conditions", jsonserializationcontext.serialize(t0.d)); - } -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootSelectorEntry.java -@@ -0,0 +0,0 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - @Override - public T b(LootItemFunction.a lootitemfunction_a) { - this.c.add(lootitemfunction_a.b()); -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - - protected LootItemFunction[] a() { -@@ -0,0 +0,0 @@ public abstract class LootSelectorEntry extends LootEntryAbstract { - - public T a(int i) { - this.a = i; -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - - public T b(int i) { - this.b = i; -- return (LootSelectorEntry.a) this.d(); -+ return this.d(); // Paper - decompile fix - } - } - -diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -+++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/LootItemFunctionExplorationMap.java -@@ -0,0 +0,0 @@ public class LootItemFunctionExplorationMap extends LootItemFunctionConditional - public b() {} - - public void a(JsonObject jsonobject, LootItemFunctionExplorationMap lootitemfunctionexplorationmap, JsonSerializationContext jsonserializationcontext) { -- super.a(jsonobject, (LootItemFunctionConditional) lootitemfunctionexplorationmap, jsonserializationcontext); -+ super.a(jsonobject, lootitemfunctionexplorationmap, jsonserializationcontext); // Paper - decompile fix - if (!lootitemfunctionexplorationmap.e.equals(LootItemFunctionExplorationMap.a)) { - jsonobject.add("destination", jsonserializationcontext.serialize(lootitemfunctionexplorationmap.e.i())); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -@@ -0,0 +0,0 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { - double d1 = flag4 ? doublelist.getDouble(i++) : doublelist1.getDouble(j++); - - if ((i != 0 && flag2 || flag4 || flag1) && (j != 0 && flag3 || !flag4 || flag)) { -- if (d0 < d1 - 1.0E-7D) { -+ if (!(d0 >= d1 - 1.0E-7D)) { // Paper - decompile error - welcome to hell - this.b.add(i - 1); - this.c.add(j - 1); - this.a.add(d1); diff --git a/Spigot-Server-Patches/MC-Utils.patch b/Spigot-Server-Patches/MC-Utils.patch deleted file mode 100644 index 596d96722b..0000000000 --- a/Spigot-Server-Patches/MC-Utils.patch +++ /dev/null @@ -1,4850 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 20:55:47 -0400 -Subject: [PATCH] MC Utils - - -diff --git a/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/concurrent/WeakSeqLock.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.concurrent; -+ -+import java.util.concurrent.atomic.AtomicLong; -+ -+/** -+ * copied from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/lock/WeakSeqLock.java -+ * @author Spottedleaf -+ */ -+public final class WeakSeqLock { -+ // TODO when the switch to J11 is made, nuke this class from orbit -+ -+ protected final AtomicLong lock = new AtomicLong(); -+ -+ public WeakSeqLock() { -+ //VarHandle.storeStoreFence(); // warn: usages must be checked to ensure this behaviour isn't needed -+ } -+ -+ public void acquireWrite() { -+ // must be release-type write -+ this.lock.lazySet(this.lock.get() + 1); -+ } -+ -+ public boolean canRead(final long read) { -+ return (read & 1) == 0; -+ } -+ -+ public boolean tryAcquireWrite() { -+ this.acquireWrite(); -+ return true; -+ } -+ -+ public void releaseWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock + 1); -+ } -+ -+ public void abortWrite() { -+ // must be acquire-type write -+ final long lock = this.lock.get(); // volatile here acts as store-store -+ this.lock.lazySet(lock ^ 1); -+ } -+ -+ public long acquireRead() { -+ int failures = 0; -+ long curr; -+ -+ for (curr = this.lock.get(); !this.canRead(curr); curr = this.lock.get()) { -+ // without j11, our only backoff is the yield() call... -+ -+ if (++failures > 5_000) { /* TODO determine a threshold */ -+ Thread.yield(); -+ } -+ /* Better waiting is beyond the scope of this lock; if it is needed the lock is being misused */ -+ } -+ -+ //VarHandle.loadLoadFence(); // volatile acts as the load-load barrier -+ return curr; -+ } -+ -+ public boolean tryReleaseRead(final long read) { -+ return this.lock.get() == read; // volatile acts as the load-load barrier -+ } -+ -+ public long getSequentialCounter() { -+ return this.lock.get(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Int.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -+import it.unimi.dsi.fastutil.objects.ObjectIterator; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Int { -+ -+ protected final Long2IntOpenHashMap updatingMap; -+ protected final Long2IntOpenHashMap visibleMap; -+ protected final Long2IntOpenHashMap queuedPuts; -+ protected final LongOpenHashSet queuedRemove; -+ -+ protected int queuedDefaultReturnValue; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Int() { -+ this(16, 0.75f); -+ } -+ -+ public QueuedChangesMapLong2Int(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.visibleMap = new Long2IntOpenHashMap(capacity, loadFactor); -+ this.queuedPuts = new Long2IntOpenHashMap(); -+ this.queuedRemove = new LongOpenHashSet(); -+ } -+ -+ public void queueDefaultReturnValue(final int dfl) { -+ this.queuedDefaultReturnValue = dfl; -+ this.updatingMap.defaultReturnValue(dfl); -+ } -+ -+ public int queueUpdate(final long k, final int v) { -+ this.queuedRemove.remove(k); -+ this.queuedPuts.put(k, v); -+ -+ return this.updatingMap.put(k, v); -+ } -+ -+ public int queueRemove(final long k) { -+ this.queuedPuts.remove(k); -+ this.queuedRemove.add(k); -+ -+ return this.updatingMap.remove(k); -+ } -+ -+ public int getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public int getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public int getVisibleAsync(final long k) { -+ long readlock; -+ int ret = 0; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean performUpdates() { -+ this.updatingMapSeqLock.acquireWrite(); -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ this.updatingMapSeqLock.releaseWrite(); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.put(key, val); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.remove(key); -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ this.visibleMap.defaultReturnValue(this.queuedDefaultReturnValue); -+ -+ if (this.queuedPuts.isEmpty() && this.queuedRemove.isEmpty()) { -+ return false; -+ } -+ -+ // update puts -+ final ObjectIterator iterator0 = this.queuedPuts.long2IntEntrySet().fastIterator(); -+ while (iterator0.hasNext()) { -+ final Long2IntMap.Entry entry = iterator0.next(); -+ final long key = entry.getLongKey(); -+ final int val = entry.getIntValue(); -+ -+ this.visibleMap.put(key, val); -+ } -+ -+ this.queuedPuts.clear(); -+ -+ final LongIterator iterator1 = this.queuedRemove.iterator(); -+ while (iterator1.hasNext()) { -+ final long key = iterator1.nextLong(); -+ -+ this.visibleMap.remove(key); -+ } -+ -+ this.queuedRemove.clear(); -+ -+ return true; -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/QueuedChangesMapLong2Object.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.map; -+ -+import com.destroystokyo.paper.util.concurrent.WeakSeqLock; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+/** -+ * @author Spottedleaf -+ */ -+public class QueuedChangesMapLong2Object { -+ -+ protected static final Object REMOVED = new Object(); -+ -+ protected final Long2ObjectLinkedOpenHashMap updatingMap; -+ protected final Long2ObjectLinkedOpenHashMap visibleMap; -+ protected final Long2ObjectLinkedOpenHashMap queuedChanges; -+ -+ // we use a seqlock as writes are not common. -+ protected final WeakSeqLock updatingMapSeqLock = new WeakSeqLock(); -+ -+ public QueuedChangesMapLong2Object() { -+ this(16, 0.75f); // dfl for fastutil -+ } -+ -+ public QueuedChangesMapLong2Object(final int capacity, final float loadFactor) { -+ this.updatingMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.visibleMap = new Long2ObjectLinkedOpenHashMap<>(capacity, loadFactor); -+ this.queuedChanges = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ -+ public V queueUpdate(final long k, final V value) { -+ this.queuedChanges.put(k, value); -+ return this.updatingMap.put(k, value); -+ } -+ -+ public V queueRemove(final long k) { -+ this.queuedChanges.put(k, REMOVED); -+ return this.updatingMap.remove(k); -+ } -+ -+ public V getUpdating(final long k) { -+ return this.updatingMap.get(k); -+ } -+ -+ public boolean updatingContainsKey(final long k) { -+ return this.updatingMap.containsKey(k); -+ } -+ -+ public V getVisible(final long k) { -+ return this.visibleMap.get(k); -+ } -+ -+ public boolean visibleContainsKey(final long k) { -+ return this.visibleMap.containsKey(k); -+ } -+ -+ public V getVisibleAsync(final long k) { -+ long readlock; -+ V ret = null; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.get(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public boolean visibleContainsKeyAsync(final long k) { -+ long readlock; -+ boolean ret = false; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ -+ try { -+ ret = this.visibleMap.containsKey(k); -+ } catch (final Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // ignore... -+ continue; -+ } -+ -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getVisibleMap() { -+ return this.visibleMap; -+ } -+ -+ public Long2ObjectLinkedOpenHashMap getUpdatingMap() { -+ return this.updatingMap; -+ } -+ -+ public int getVisibleSize() { -+ return this.visibleMap.size(); -+ } -+ -+ public int getVisibleSizeAsync() { -+ long readlock; -+ int ret; -+ -+ do { -+ readlock = this.updatingMapSeqLock.acquireRead(); -+ ret = this.visibleMap.size(); -+ } while (!this.updatingMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getUpdatingValues() { -+ return this.updatingMap.values(); -+ } -+ -+ public List getUpdatingValuesCopy() { -+ return new ArrayList<>(this.updatingMap.values()); -+ } -+ -+ // unlike mojang's impl this cannot be used async since it's not a view of an immutable map -+ public Collection getVisibleValues() { -+ return this.visibleMap.values(); -+ } -+ -+ public List getVisibleValuesCopy() { -+ return new ArrayList<>(this.visibleMap.values()); -+ } -+ -+ public boolean performUpdates() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ this.updatingMapSeqLock.acquireWrite(); -+ try { -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+ -+ public boolean performUpdatesLockMap() { -+ if (this.queuedChanges.isEmpty()) { -+ return false; -+ } -+ -+ final ObjectBidirectionalIterator> iterator = this.queuedChanges.long2ObjectEntrySet().fastIterator(); -+ -+ try { -+ this.updatingMapSeqLock.acquireWrite(); -+ -+ while (iterator.hasNext()) { -+ final Long2ObjectMap.Entry entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final Object val = entry.getValue(); -+ -+ if (val == REMOVED) { -+ this.visibleMap.remove(key); -+ } else { -+ this.visibleMap.put(key, (V)val); -+ } -+ } -+ } finally { -+ this.updatingMapSeqLock.releaseWrite(); -+ } -+ -+ this.queuedChanges.clear(); -+ return true; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/ChunkList.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import net.minecraft.world.level.chunk.Chunk; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class ChunkList implements Iterable { -+ -+ protected final Long2IntOpenHashMap chunkToIndex = new Long2IntOpenHashMap(2, 0.8f); -+ { -+ this.chunkToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final Chunk[] EMPTY_LIST = new Chunk[0]; -+ -+ protected Chunk[] chunks = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final Chunk chunk) { -+ return this.chunkToIndex.containsKey(chunk.coordinateKey); -+ } -+ -+ public boolean remove(final Chunk chunk) { -+ final int index = this.chunkToIndex.remove(chunk.coordinateKey); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final Chunk end = this.chunks[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.chunkToIndex.put(end.coordinateKey, index); // update index -+ } -+ this.chunks[index] = end; -+ this.chunks[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final Chunk chunk) { -+ final int count = this.count; -+ final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ Chunk[] list = this.chunks; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.chunks = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = chunk; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public Chunk getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.chunks[index]; -+ } -+ -+ public Chunk getUnchecked(final int index) { -+ return this.chunks[index]; -+ } -+ -+ public Chunk[] getRawData() { -+ return this.chunks; -+ } -+ -+ public void clear() { -+ this.chunkToIndex.clear(); -+ Arrays.fill(this.chunks, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Chunk lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < ChunkList.this.count; -+ } -+ -+ @Override -+ public Chunk next() { -+ if (this.current >= ChunkList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = ChunkList.this.chunks[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final Chunk lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ ChunkList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/EntityList.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -+import net.minecraft.world.entity.Entity; -+import java.util.Arrays; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// list with O(1) remove & contains -+/** -+ * @author Spottedleaf -+ */ -+public final class EntityList implements Iterable { -+ -+ protected final Int2IntOpenHashMap entityToIndex = new Int2IntOpenHashMap(2, 0.8f); -+ { -+ this.entityToIndex.defaultReturnValue(Integer.MIN_VALUE); -+ } -+ -+ protected static final Entity[] EMPTY_LIST = new Entity[0]; -+ -+ protected Entity[] entities = EMPTY_LIST; -+ protected int count; -+ -+ public int size() { -+ return this.count; -+ } -+ -+ public boolean contains(final Entity entity) { -+ return this.entityToIndex.containsKey(entity.getId()); -+ } -+ -+ public boolean remove(final Entity entity) { -+ final int index = this.entityToIndex.remove(entity.getId()); -+ if (index == Integer.MIN_VALUE) { -+ return false; -+ } -+ -+ // move the entity at the end to this index -+ final int endIndex = --this.count; -+ final Entity end = this.entities[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.entityToIndex.put(end.getId(), index); // update index -+ } -+ this.entities[index] = end; -+ this.entities[endIndex] = null; -+ -+ return true; -+ } -+ -+ public boolean add(final Entity entity) { -+ final int count = this.count; -+ final int currIndex = this.entityToIndex.putIfAbsent(entity.getId(), count); -+ -+ if (currIndex != Integer.MIN_VALUE) { -+ return false; // already in this list -+ } -+ -+ Entity[] list = this.entities; -+ -+ if (list.length == count) { -+ // resize required -+ list = this.entities = Arrays.copyOf(list, (int)Math.max(4L, count * 2L)); // overflow results in negative -+ } -+ -+ list[count] = entity; -+ this.count = count + 1; -+ -+ return true; -+ } -+ -+ public Entity getChecked(final int index) { -+ if (index < 0 || index >= this.count) { -+ throw new IndexOutOfBoundsException("Index: " + index + " is out of bounds, size: " + this.count); -+ } -+ return this.entities[index]; -+ } -+ -+ public Entity getUnchecked(final int index) { -+ return this.entities[index]; -+ } -+ -+ public Entity[] getRawData() { -+ return this.entities; -+ } -+ -+ public void clear() { -+ this.entityToIndex.clear(); -+ Arrays.fill(this.entities, 0, this.count, null); -+ this.count = 0; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Entity lastRet; -+ int current; -+ -+ @Override -+ public boolean hasNext() { -+ return this.current < EntityList.this.count; -+ } -+ -+ @Override -+ public Entity next() { -+ if (this.current >= EntityList.this.count) { -+ throw new NoSuchElementException(); -+ } -+ return this.lastRet = EntityList.this.entities[this.current++]; -+ } -+ -+ @Override -+ public void remove() { -+ final Entity lastRet = this.lastRet; -+ -+ if (lastRet == null) { -+ throw new IllegalStateException(); -+ } -+ this.lastRet = null; -+ -+ EntityList.this.remove(lastRet); -+ --this.current; -+ } -+ }; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/maplist/IBlockDataList.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.maplist; -+ -+import it.unimi.dsi.fastutil.longs.LongIterator; -+import it.unimi.dsi.fastutil.shorts.Short2LongOpenHashMap; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.DataPaletteGlobal; -+import java.util.Arrays; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IBlockDataList { -+ -+ static final DataPaletteGlobal GLOBAL_PALETTE = (DataPaletteGlobal) ChunkSection.GLOBAL_PALETTE; -+ -+ // map of location -> (index | (location << 16) | (palette id << 32)) -+ private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); -+ { -+ this.map.defaultReturnValue(Long.MAX_VALUE); -+ } -+ -+ private static final long[] EMPTY_LIST = new long[0]; -+ -+ private long[] byIndex = EMPTY_LIST; -+ private int size; -+ -+ public static int getLocationKey(final int x, final int y, final int z) { -+ return (x & 15) | (((z & 15) << 4)) | ((y & 255) << (4 + 4)); -+ } -+ -+ public static IBlockData getBlockDataFromRaw(final long raw) { -+ return GLOBAL_PALETTE.getObject((int)(raw >>> 32)); -+ } -+ -+ public static int getIndexFromRaw(final long raw) { -+ return (int)(raw & 0xFFFF); -+ } -+ -+ public static int getLocationFromRaw(final long raw) { -+ return (int)((raw >>> 16) & 0xFFFF); -+ } -+ -+ public static long getRawFromValues(final int index, final int location, final IBlockData data) { -+ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.getOrCreateIdFor(data)) << 32); -+ } -+ -+ public static long setIndexRawValues(final long value, final int index) { -+ return value & ~(0xFFFF) | (index); -+ } -+ -+ public long add(final int x, final int y, final int z, final IBlockData data) { -+ return this.add(getLocationKey(x, y, z), data); -+ } -+ -+ public long add(final int location, final IBlockData data) { -+ final long curr = this.map.get((short)location); -+ -+ if (curr == Long.MAX_VALUE) { -+ final int index = this.size++; -+ final long raw = getRawFromValues(index, location, data); -+ this.map.put((short)location, raw); -+ -+ if (index >= this.byIndex.length) { -+ this.byIndex = Arrays.copyOf(this.byIndex, (int)Math.max(4L, this.byIndex.length * 2L)); -+ } -+ -+ this.byIndex[index] = raw; -+ return raw; -+ } else { -+ final int index = getIndexFromRaw(curr); -+ final long raw = this.byIndex[index] = getRawFromValues(index, location, data); -+ -+ this.map.put((short)location, raw); -+ -+ return raw; -+ } -+ } -+ -+ public long remove(final int x, final int y, final int z) { -+ return this.remove(getLocationKey(x, y, z)); -+ } -+ -+ public long remove(final int location) { -+ final long ret = this.map.remove((short)location); -+ final int index = getIndexFromRaw(ret); -+ if (ret == Long.MAX_VALUE) { -+ return ret; -+ } -+ -+ // move the entry at the end to this index -+ final int endIndex = --this.size; -+ final long end = this.byIndex[endIndex]; -+ if (index != endIndex) { -+ // not empty after this call -+ this.map.put((short)getLocationFromRaw(end), setIndexRawValues(end, index)); -+ } -+ this.byIndex[index] = end; -+ this.byIndex[endIndex] = 0L; -+ -+ return ret; -+ } -+ -+ public int size() { -+ return this.size; -+ } -+ -+ public long getRaw(final int index) { -+ return this.byIndex[index]; -+ } -+ -+ public int getLocation(final int index) { -+ return getLocationFromRaw(this.getRaw(index)); -+ } -+ -+ public IBlockData getData(final int index) { -+ return getBlockDataFromRaw(this.getRaw(index)); -+ } -+ -+ public void clear() { -+ this.size = 0; -+ this.map.clear(); -+ } -+ -+ public LongIterator getRawIterator() { -+ return this.map.values().iterator(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/IntegerUtil.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.math; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class IntegerUtil { -+ -+ public static final int HIGH_BIT_U32 = Integer.MIN_VALUE; -+ public static final long HIGH_BIT_U64 = Long.MIN_VALUE; -+ -+ public static int ceilLog2(final int value) { -+ return Integer.SIZE - Integer.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static long ceilLog2(final long value) { -+ return Long.SIZE - Long.numberOfLeadingZeros(value - 1); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final int value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Integer.SIZE - 1) ^ Integer.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int floorLog2(final long value) { -+ // xor is optimized subtract for 2^n -1 -+ // note that (2^n -1) - k = (2^n -1) ^ k for k <= (2^n - 1) -+ return (Long.SIZE - 1) ^ Long.numberOfLeadingZeros(value); // see doc of numberOfLeadingZeros -+ } -+ -+ public static int roundCeilLog2(final int value) { -+ // optimized variant of 1 << (32 - leading(val - 1)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (32 - leading(val - 1)) = HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - (32 - leading(val - 1))) -+ // HIGH_BIT_32 >>> (31 - 32 + leading(val - 1)) -+ // HIGH_BIT_32 >>> (-1 + leading(val - 1)) -+ return HIGH_BIT_U32 >>> (Integer.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static long roundCeilLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> (Long.numberOfLeadingZeros(value - 1) - 1); -+ } -+ -+ public static int roundFloorLog2(final int value) { -+ // optimized variant of 1 << (31 - leading(val)) -+ // given -+ // 1 << n = HIGH_BIT_32 >>> (31 - n) for n [0, 32) -+ // 1 << (31 - leading(val)) = HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - (31 - leading(val))) -+ // HIGH_BIT_32 >> (31 - 31 + leading(val)) -+ return HIGH_BIT_U32 >>> Integer.numberOfLeadingZeros(value); -+ } -+ -+ public static long roundFloorLog2(final long value) { -+ // see logic documented above -+ return HIGH_BIT_U64 >>> Long.numberOfLeadingZeros(value); -+ } -+ -+ public static boolean isPowerOfTwo(final int n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ public static boolean isPowerOfTwo(final long n) { -+ // 2^n has one bit -+ // note: this rets true for 0 still -+ return IntegerUtil.getTrailingBit(n) == n; -+ } -+ -+ -+ public static int getTrailingBit(final int n) { -+ return -n & n; -+ } -+ -+ public static long getTrailingBit(final long n) { -+ return -n & n; -+ } -+ -+ public static int trailingZeros(final int n) { -+ return Integer.numberOfTrailingZeros(n); -+ } -+ -+ public static long trailingZeros(final long n) { -+ return Long.numberOfTrailingZeros(n); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorMultiple(final long numbers) { -+ return (int)(numbers >>> 32); -+ } -+ -+ // from hacker's delight (signed division magic value) -+ public static int getDivisorShift(final long numbers) { -+ return (int)numbers; -+ } -+ -+ // copied from hacker's delight (signed division magic value) -+ // http://www.hackersdelight.org/hdcodetxt/magic.c.txt -+ public static long getDivisorNumbers(final int d) { -+ final int ad = IntegerUtil.branchlessAbs(d); -+ -+ if (ad < 2) { -+ throw new IllegalArgumentException("|number| must be in [2, 2^31 -1], not: " + d); -+ } -+ -+ final int two31 = 0x80000000; -+ final long mask = 0xFFFFFFFFL; // mask for enforcing unsigned behaviour -+ -+ int p = 31; -+ -+ // all these variables are UNSIGNED! -+ int t = two31 + (d >>> 31); -+ int anc = t - 1 - t%ad; -+ int q1 = (int)((two31 & mask)/(anc & mask)); -+ int r1 = two31 - q1*anc; -+ int q2 = (int)((two31 & mask)/(ad & mask)); -+ int r2 = two31 - q2*ad; -+ int delta; -+ -+ do { -+ p = p + 1; -+ q1 = 2*q1; // Update q1 = 2**p/|nc|. -+ r1 = 2*r1; // Update r1 = rem(2**p, |nc|). -+ if ((r1 & mask) >= (anc & mask)) {// (Must be an unsigned comparison here) -+ q1 = q1 + 1; -+ r1 = r1 - anc; -+ } -+ q2 = 2*q2; // Update q2 = 2**p/|d|. -+ r2 = 2*r2; // Update r2 = rem(2**p, |d|). -+ if ((r2 & mask) >= (ad & mask)) {// (Must be an unsigned comparison here) -+ q2 = q2 + 1; -+ r2 = r2 - ad; -+ } -+ delta = ad - r2; -+ } while ((q1 & mask) < (delta & mask) || (q1 == delta && r1 == 0)); -+ -+ int magicNum = q2 + 1; -+ if (d < 0) { -+ magicNum = -magicNum; -+ } -+ int shift = p - 32; -+ return ((long)magicNum << 32) | shift; -+ } -+ -+ public static int branchlessAbs(final int val) { -+ // -n = -1 ^ n + 1 -+ final int mask = val >> (Integer.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ public static long branchlessAbs(final long val) { -+ // -n = -1 ^ n + 1 -+ final long mask = val >> (Long.SIZE - 1); // -1 if < 0, 0 if >= 0 -+ return (mask ^ val) - mask; // if val < 0, then (0 ^ val) - 0 else (-1 ^ val) + 1 -+ } -+ -+ //https://github.com/skeeto/hash-prospector for hash functions -+ -+ //score = ~590.47984224483832 -+ public static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ //score = ~310.01596637036749 -+ public static int hash1(int x) { -+ x ^= x >>> 15; -+ x *= 0x356aaaad; -+ x ^= x >>> 17; -+ return x; -+ } -+ -+ public static int hash2(int x) { -+ x ^= x >>> 16; -+ x *= 0x7feb352d; -+ x ^= x >>> 15; -+ x *= 0x846ca68b; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public static int hash3(int x) { -+ x ^= x >>> 17; -+ x *= 0xed5ad4bb; -+ x ^= x >>> 11; -+ x *= 0xac4c1b51; -+ x ^= x >>> 15; -+ x *= 0x31848bab; -+ x ^= x >>> 14; -+ return x; -+ } -+ -+ //score = ~365.79959673201887 -+ public static long hash1(long x) { -+ x ^= x >>> 27; -+ x *= 0xb24924b71d2d354bL; -+ x ^= x >>> 28; -+ return x; -+ } -+ -+ //h2 hash -+ public static long hash2(long x) { -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ x *= 0xd6e8feb86659fd93L; -+ x ^= x >>> 32; -+ return x; -+ } -+ -+ public static long hash3(long x) { -+ x ^= x >>> 45; -+ x *= 0xc161abe5704b6c79L; -+ x ^= x >>> 41; -+ x *= 0xe3e5389aedbc90f7L; -+ x ^= x >>> 56; -+ x *= 0x1f9aba75a52db073L; -+ x ^= x >>> 53; -+ return x; -+ } -+ -+ private IntegerUtil() { -+ throw new RuntimeException(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import javax.annotation.Nullable; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public abstract class AreaMap { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/520419c6f41ef348fe9926ce674b7217 */ -+ -+ protected final Object2LongOpenHashMap objectToLastCoordinate = new Object2LongOpenHashMap<>(); -+ protected final Object2IntOpenHashMap objectToViewDistance = new Object2IntOpenHashMap<>(); -+ -+ { -+ this.objectToViewDistance.defaultReturnValue(-1); -+ this.objectToLastCoordinate.defaultReturnValue(Long.MIN_VALUE); -+ } -+ -+ // we use linked for better iteration. -+ // map of: coordinate to set of objects in coordinate -+ protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); -+ protected final PooledLinkedHashSets pooledHashSets; -+ -+ protected final ChangeCallback addCallback; -+ protected final ChangeCallback removeCallback; -+ protected final ChangeSourceCallback changeSourceCallback; -+ -+ public AreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public AreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null); -+ } -+ -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ public AreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ this.pooledHashSets = pooledHashSets; -+ this.addCallback = addCallback; -+ this.removeCallback = removeCallback; -+ this.changeSourceCallback = changeSourceCallback; -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final long key) { -+ return this.areaMap.get(key); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkCoordIntPair chunkPos) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final int chunkX, final int chunkZ) { -+ return this.areaMap.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ // Long.MIN_VALUE indicates the object is not mapped -+ public final long getLastCoordinate(final E object) { -+ return this.objectToLastCoordinate.getOrDefault(object, Long.MIN_VALUE); -+ } -+ -+ // -1 indicates the object is not mapped -+ public final int getLastViewDistance(final E object) { -+ return this.objectToViewDistance.getOrDefault(object, -1); -+ } -+ -+ // returns the total number of mapped chunks -+ public final int size() { -+ return this.areaMap.size(); -+ } -+ -+ public final void addOrUpdate(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.put(object, viewDistance); -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ -+ if (oldViewDistance == -1) { -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ } else { -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ } -+ -+ public final boolean update(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.replace(object, viewDistance); -+ if (oldViewDistance == -1) { -+ return false; -+ } else { -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final long oldPos = this.objectToLastCoordinate.put(object, newPos); -+ this.updateObject(object, oldPos, newPos, oldViewDistance, viewDistance); -+ this.updateObjectCallback(object, oldPos, newPos, oldViewDistance, viewDistance); -+ } -+ //this.validate(object, viewDistance); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void updateObjectCallback(final E Object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (newPosition != oldPosition && this.changeSourceCallback != null) { -+ this.changeSourceCallback.accept(Object, oldPosition, newPosition); -+ } -+ } -+ -+ public final boolean add(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int oldViewDistance = this.objectToViewDistance.putIfAbsent(object, viewDistance); -+ if (oldViewDistance != -1) { -+ return false; -+ } -+ -+ final long newPos = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ this.objectToLastCoordinate.put(object, newPos); -+ this.addObject(object, chunkX, chunkZ, Integer.MIN_VALUE, Integer.MIN_VALUE, viewDistance); -+ this.addObjectCallback(object, chunkX, chunkZ, viewDistance); -+ -+ //this.validate(object, viewDistance); -+ -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ public final boolean remove(final E object) { -+ final long position = this.objectToLastCoordinate.removeLong(object); -+ final int viewDistance = this.objectToViewDistance.removeInt(object); -+ -+ if (viewDistance == -1) { -+ return false; -+ } -+ -+ final int currentX = MCUtil.getCoordinateX(position); -+ final int currentZ = MCUtil.getCoordinateZ(position); -+ -+ this.removeObject(object, currentX, currentZ, currentX, currentZ, viewDistance); -+ this.removeObjectCallback(object, currentX, currentZ, viewDistance); -+ //this.validate(object, -1); -+ return true; -+ } -+ -+ // called after the distance map updates -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) {} -+ -+ protected abstract PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final E object); -+ -+ // expensive op, only for debug -+ protected void validate(final E object, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ if (viewDistance < 0) { -+ expectedEntries = 0; -+ } -+ -+ final long currPosition = this.objectToLastCoordinate.getLong(object); -+ -+ final int centerX = MCUtil.getCoordinateX(currPosition); -+ final int centerZ = MCUtil.getCoordinateZ(currPosition); -+ -+ for (Iterator>> iterator = this.areaMap.long2ObjectEntrySet().fastIterator(); -+ iterator.hasNext();) { -+ -+ final Long2ObjectLinkedOpenHashMap.Entry> entry = iterator.next(); -+ final long key = entry.getLongKey(); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.contains(object)) { -+ ++entiesGot; -+ -+ final int chunkX = MCUtil.getCoordinateX(key); -+ final int chunkZ = MCUtil.getCoordinateZ(key); -+ -+ final int dist = Math.max(IntegerUtil.branchlessAbs(chunkX - centerX), IntegerUtil.branchlessAbs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addObjectTo(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet empty = this.getEmptySetFor(object); -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.putIfAbsent(key, empty); -+ -+ if (current != null) { -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWith(current, object); -+ if (next == current) { -+ throw new IllegalStateException("Expected different map: got " + next.toString()); -+ } -+ this.areaMap.put(key, next); -+ -+ current = next; -+ // fall through to callback -+ } else { -+ current = empty; -+ } -+ -+ if (this.addCallback != null) { -+ try { -+ this.addCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, current); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Add callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void removeObjectFrom(final E object, final int chunkX, final int chunkZ, final int currChunkX, -+ final int currChunkZ, final int prevChunkX, final int prevChunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet current = this.areaMap.get(key); -+ -+ if (current == null) { -+ throw new IllegalStateException("Current map may not be null for " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ PooledLinkedHashSets.PooledObjectLinkedOpenHashSet next = this.pooledHashSets.findMapWithout(current, object); -+ -+ if (next == current) { -+ throw new IllegalStateException("Current map [" + next.toString() + "] should have contained " + object + ", (" + chunkX + "," + chunkZ + ")"); -+ } -+ -+ if (next != null) { -+ this.areaMap.put(key, next); -+ } else { -+ this.areaMap.remove(key); -+ } -+ -+ if (this.removeCallback != null) { -+ try { -+ this.removeCallback.accept(object, chunkX, chunkZ, currChunkX, currChunkZ, prevChunkX, prevChunkZ, next); -+ } catch (final Throwable ex) { -+ if (ex instanceof ThreadDeath) { -+ throw (ThreadDeath)ex; -+ } -+ MinecraftServer.LOGGER.error("Remove callback for map threw exception ", ex); -+ } -+ } -+ } -+ -+ private void addObject(final E object, final int chunkX, final int chunkZ, final int prevChunkX, final int prevChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.addObjectTo(object, x, z, chunkX, chunkZ, prevChunkX, prevChunkZ); -+ } -+ } -+ } -+ -+ private void removeObject(final E object, final int chunkX, final int chunkZ, final int currentChunkX, final int currentChunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.removeObjectFrom(object, x, z, currentChunkX, currentChunkZ, chunkX, chunkZ); -+ } -+ } -+ } -+ -+ /* math sign function except 0 returns 1 */ -+ protected static int sign(int val) { -+ return 1 | (val >> (Integer.SIZE - 1)); -+ } -+ -+ private void updateObject(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObject(object, fromX, fromZ, fromX, fromZ, oldViewDistance); -+ this.addObject(object, toX, toZ, fromX, fromZ, newViewDistance); -+ return; -+ } -+ -+ if (oldViewDistance != newViewDistance) { -+ // remove loop -+ -+ final int oldMinX = fromX - oldViewDistance; -+ final int oldMinZ = fromZ - oldViewDistance; -+ final int oldMaxX = fromX + oldViewDistance; -+ final int oldMaxZ = fromZ + oldViewDistance; -+ for (int currX = oldMinX; currX <= oldMaxX; ++currX) { -+ for (int currZ = oldMinZ; currZ <= oldMaxZ; ++currZ) { -+ -+ // only remove if we're outside the new view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - toX), IntegerUtil.branchlessAbs(currZ - toZ)) > newViewDistance) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ // add loop -+ -+ final int newMinX = toX - newViewDistance; -+ final int newMinZ = toZ - newViewDistance; -+ final int newMaxX = toX + newViewDistance; -+ final int newMaxZ = toZ + newViewDistance; -+ for (int currX = newMinX; currX <= newMaxX; ++currX) { -+ for (int currZ = newMinZ; currZ <= newMaxZ; ++currZ) { -+ -+ // only add if we're outside the old view distance... -+ if (Math.max(IntegerUtil.branchlessAbs(currX - fromX), IntegerUtil.branchlessAbs(currZ - fromZ)) > oldViewDistance) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ // same view distance -+ -+ // used for relative positioning -+ final int up = sign(dz); // 1 if dz >= 0, -1 otherwise -+ final int right = sign(dx); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addObjectTo(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removeObjectFrom(object, currX, currZ, toX, toZ, fromX, fromZ); -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeCallback { -+ -+ // if there is no previous position, then prevPos = Integer.MIN_VALUE -+ void accept(final E object, final int rangeX, final int rangeZ, final int currPosX, final int currPosZ, final int prevPosX, final int prevPosZ, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState); -+ -+ } -+ -+ @FunctionalInterface -+ public static interface ChangeSourceCallback { -+ void accept(final E object, final long prevPos, final long newPos); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/DistanceTrackingAreaMap.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import com.destroystokyo.paper.util.math.IntegerUtil; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.ChunkCoordIntPair; -+ -+/** @author Spottedleaf */ -+public abstract class DistanceTrackingAreaMap extends AreaMap { -+ -+ // use this map only if you need distance tracking, the tracking here is obviously going to hit harder. -+ -+ protected final Long2IntOpenHashMap chunkToNearestDistance = new Long2IntOpenHashMap(1024, 0.7f); -+ { -+ this.chunkToNearestDistance.defaultReturnValue(-1); -+ } -+ -+ protected final DistanceChangeCallback distanceChangeCallback; -+ -+ public DistanceTrackingAreaMap() { -+ this(new PooledLinkedHashSets<>()); -+ } -+ -+ // let users define a "global" or "shared" pooled sets if they wish -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ this(pooledHashSets, null, null, null); -+ } -+ -+ public DistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, final ChangeCallback removeCallback, -+ final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback); -+ this.distanceChangeCallback = distanceChangeCallback; -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final long key) { -+ return this.chunkToNearestDistance.get(key); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final ChunkCoordIntPair chunkPos) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); -+ } -+ -+ // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final int chunkX, final int chunkZ) { -+ return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ } -+ -+ protected final void recalculateDistance(final int chunkX, final int chunkZ) { -+ final long key = MCUtil.getCoordinateKey(chunkX, chunkZ); -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state = this.areaMap.get(key); -+ if (state == null) { -+ final int oldDistance = this.chunkToNearestDistance.remove(key); -+ // nothing here. -+ if (oldDistance == -1) { -+ // nothing was here previously -+ return; -+ } -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, -1, null); -+ } -+ return; -+ } -+ -+ int newDistance = Integer.MAX_VALUE; -+ -+ final Object[] rawData = state.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ final Object raw = rawData[i]; -+ -+ if (raw == null) { -+ continue; -+ } -+ -+ final E object = (E)raw; -+ final long location = this.objectToLastCoordinate.getLong(object); -+ -+ final int distance = Math.max(IntegerUtil.branchlessAbs(chunkX - MCUtil.getCoordinateX(location)), IntegerUtil.branchlessAbs(chunkZ - MCUtil.getCoordinateZ(location))); -+ -+ if (distance < newDistance) { -+ newDistance = distance; -+ } -+ } -+ -+ final int oldDistance = this.chunkToNearestDistance.put(key, newDistance); -+ -+ if (oldDistance != newDistance) { -+ if (this.distanceChangeCallback != null) { -+ this.distanceChangeCallback.accept(chunkX, chunkZ, oldDistance, newDistance, state); -+ } -+ } -+ } -+ -+ @Override -+ protected void addObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void removeObjectCallback(final E object, final int chunkX, final int chunkZ, final int viewDistance) { -+ final int maxX = chunkX + viewDistance; -+ final int maxZ = chunkZ + viewDistance; -+ final int minX = chunkX - viewDistance; -+ final int minZ = chunkZ - viewDistance; -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ this.recalculateDistance(x, z); -+ } -+ } -+ } -+ -+ @Override -+ protected void updateObjectCallback(final E object, final long oldPosition, final long newPosition, final int oldViewDistance, final int newViewDistance) { -+ if (oldPosition == newPosition && newViewDistance == oldViewDistance) { -+ return; -+ } -+ -+ final int toX = MCUtil.getCoordinateX(newPosition); -+ final int toZ = MCUtil.getCoordinateZ(newPosition); -+ final int fromX = MCUtil.getCoordinateX(oldPosition); -+ final int fromZ = MCUtil.getCoordinateZ(oldPosition); -+ -+ final int totalX = IntegerUtil.branchlessAbs(fromX - toX); -+ final int totalZ = IntegerUtil.branchlessAbs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * Math.max(newViewDistance, oldViewDistance))) { -+ // teleported? -+ this.removeObjectCallback(object, fromX, fromZ, oldViewDistance); -+ this.addObjectCallback(object, toX, toZ, newViewDistance); -+ return; -+ } -+ -+ final int minX = Math.min(fromX - oldViewDistance, toX - newViewDistance); -+ final int maxX = Math.max(fromX + oldViewDistance, toX + newViewDistance); -+ final int minZ = Math.min(fromZ - oldViewDistance, toZ - newViewDistance); -+ final int maxZ = Math.max(fromZ + oldViewDistance, toZ + newViewDistance); -+ -+ for (int x = minX; x <= maxX; ++x) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ final int distXOld = IntegerUtil.branchlessAbs(x - fromX); -+ final int distZOld = IntegerUtil.branchlessAbs(z - fromZ); -+ -+ if (Math.max(distXOld, distZOld) <= oldViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ -+ final int distXNew = IntegerUtil.branchlessAbs(x - toX); -+ final int distZNew = IntegerUtil.branchlessAbs(z - toZ); -+ -+ if (Math.max(distXNew, distZNew) <= newViewDistance) { -+ this.recalculateDistance(x, z); -+ continue; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DistanceChangeCallback { -+ -+ void accept(final int posX, final int posZ, final int oldNearestDistance, final int newNearestDistance, -+ final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet state); -+ -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.EntityPlayer; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class PlayerAreaMap extends AreaMap { -+ -+ public PlayerAreaMap() { -+ super(); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback) { -+ this(pooledHashSets, addCallback, removeCallback, null); -+ } -+ -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { -+ super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerDistanceTrackingAreaMap.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import net.minecraft.server.level.EntityPlayer; -+ -+public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { -+ -+ public PlayerDistanceTrackingAreaMap() { -+ super(); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { -+ super(pooledHashSets); -+ } -+ -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { -+ super(pooledHashSets, addCallback, removeCallback, distanceChangeCallback); -+ } -+ -+ @Override -+ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final EntityPlayer player) { -+ return player.cachedSingleHashSet; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/misc/PooledLinkedHashSets.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.misc; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -+import java.lang.ref.WeakReference; -+ -+/** @author Spottedleaf */ -+public class PooledLinkedHashSets { -+ -+ /* Tested via https://gist.github.com/Spottedleaf/a93bb7a8993d6ce142d3efc5932bf573 */ -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(128, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateAddCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ decrementReferenceCount(current); -+ -+ if (cached.referenceCount == 0) { -+ // bring the map back from the dead -+ PooledObjectLinkedOpenHashSet contending = this.mapPool.putIfAbsent(cached, cached); -+ if (contending != null) { -+ // a map already exists with the elements we want -+ if (contending.referenceCount != -1) { -+ ++contending.referenceCount; -+ } -+ current.updateRemoveCache(object, contending); -+ return contending; -+ } -+ -+ cached.referenceCount = 1; -+ } else if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ static final class RawSetObjectLinkedOpenHashSet extends ObjectOpenHashSet { -+ -+ public RawSetObjectLinkedOpenHashSet() { -+ super(); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity) { -+ super(capacity); -+ } -+ -+ public RawSetObjectLinkedOpenHashSet(final int capacity, final float loadFactor) { -+ super(capacity, loadFactor); -+ } -+ -+ @Override -+ public RawSetObjectLinkedOpenHashSet clone() { -+ return (RawSetObjectLinkedOpenHashSet)super.clone(); -+ } -+ -+ public E[] getRawSet() { -+ return this.key; -+ } -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference<>(null); -+ -+ final RawSetObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet(final PooledLinkedHashSets pooledSets) { -+ this.set = new RawSetObjectLinkedOpenHashSet<>(2, 0.8f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this((PooledLinkedHashSets)null); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ private static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ return this.lastAddMap.get(); -+ } -+ -+ PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ return this.lastRemoveMap.get(); -+ } -+ -+ void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ public boolean contains(final Object element) { -+ return this.set.contains(element); -+ } -+ -+ public E[] getBackingSet() { -+ return this.set.getRawSet(); -+ } -+ -+ public int size() { -+ return this.set.size(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/pooled/PooledObjects.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.pooled; -+ -+import net.minecraft.server.MCUtil; -+import org.apache.commons.lang3.mutable.MutableInt; -+ -+import java.util.ArrayDeque; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class PooledObjects { -+ -+ /** -+ * Wrapper for an object that will be have a cleaner registered for it, and may be automatically returned to pool. -+ */ -+ public class AutoReleased { -+ private final E object; -+ private final Runnable cleaner; -+ -+ public AutoReleased(E object, Runnable cleaner) { -+ this.object = object; -+ this.cleaner = cleaner; -+ } -+ -+ public final E getObject() { -+ return object; -+ } -+ -+ public final Runnable getCleaner() { -+ return cleaner; -+ } -+ } -+ -+ public static final PooledObjects POOLED_MUTABLE_INTEGERS = new PooledObjects<>(MutableInt::new, 1024); -+ -+ private final Supplier creator; -+ private final Consumer releaser; -+ private final int maxPoolSize; -+ private final ArrayDeque queue; -+ -+ public PooledObjects(final Supplier creator, int maxPoolSize) { -+ this(creator, maxPoolSize, null); -+ } -+ public PooledObjects(final Supplier creator, int maxPoolSize, Consumer releaser) { -+ if (creator == null) { -+ throw new NullPointerException("Creator must not be null"); -+ } -+ if (maxPoolSize <= 0) { -+ throw new IllegalArgumentException("Max pool size must be greater-than 0"); -+ } -+ -+ this.queue = new ArrayDeque<>(maxPoolSize); -+ this.maxPoolSize = maxPoolSize; -+ this.creator = creator; -+ this.releaser = releaser; -+ } -+ -+ public AutoReleased acquireCleaner(Object holder) { -+ return acquireCleaner(holder, this::release); -+ } -+ -+ public AutoReleased acquireCleaner(Object holder, Consumer releaser) { -+ E resource = acquire(); -+ Runnable cleaner = MCUtil.registerCleaner(holder, resource, releaser); -+ return new AutoReleased(resource, cleaner); -+ } -+ -+ public final E acquire() { -+ E value; -+ synchronized (queue) { -+ value = this.queue.pollLast(); -+ } -+ return value != null ? value : this.creator.get(); -+ } -+ -+ public final void release(final E value) { -+ if (this.releaser != null) { -+ this.releaser.accept(value); -+ } -+ synchronized (this.queue) { -+ if (queue.size() < this.maxPoolSize) { -+ this.queue.addLast(value); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/OptimizedSmallEnumSet.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Collection; -+ -+/** -+ * @author Spottedleaf -+ */ -+public final class OptimizedSmallEnumSet> { -+ -+ private final Class enumClass; -+ private long backingSet; -+ -+ public OptimizedSmallEnumSet(final Class clazz) { -+ if (clazz == null) { -+ throw new IllegalArgumentException("Null class"); -+ } -+ if (!clazz.isEnum()) { -+ throw new IllegalArgumentException("Class must be enum, not " + clazz.getCanonicalName()); -+ } -+ this.enumClass = clazz; -+ } -+ -+ public boolean addUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev | key; -+ -+ return (prev & key) == 0; -+ } -+ -+ public boolean removeUnchecked(final E element) { -+ final int ordinal = element.ordinal(); -+ final long key = 1L << ordinal; -+ -+ final long prev = this.backingSet; -+ this.backingSet = prev & ~key; -+ -+ return (prev & key) != 0; -+ } -+ -+ public void clear() { -+ this.backingSet = 0L; -+ } -+ -+ public int size() { -+ return Long.bitCount(this.backingSet); -+ } -+ -+ public void addAllUnchecked(final Collection enums) { -+ for (final E element : enums) { -+ if (element == null) { -+ throw new NullPointerException("Null element"); -+ } -+ this.backingSet |= (1L << element.ordinal()); -+ } -+ } -+ -+ public long getBackingSet() { -+ return this.backingSet; -+ } -+ -+ public boolean hasCommonElements(final OptimizedSmallEnumSet other) { -+ return (other.backingSet & this.backingSet) != 0; -+ } -+} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -0,0 +0,0 @@ public class SystemUtils { - } - - public static long getMonotonicNanos() { -- return SystemUtils.a.getAsLong(); -+ return System.nanoTime(); // Paper - } - - public static long getTimeMillis() { -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -0,0 +0,0 @@ public class BaseBlockPosition implements Comparable { - return IntStream.of(new int[]{baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()}); - }); - public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); -- private int a; -- private int b; -- private int e; -+ private int a;public final void setX(final int x) { this.a = x; } // Paper - OBFHELPER -+ private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER -+ private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER - - public BaseBlockPosition(int i, int j, int k) { - this.a = i; -@@ -0,0 +0,0 @@ public class BaseBlockPosition implements Comparable { - return this.e; - } - -- protected void o(int i) { -+ public void o(int i) { // Paper - protected -> public - this.a = i; - } - -- protected void p(int i) { -+ public void p(int i) { // Paper - protected -> public - this.b = i; - } - -- protected void q(int i) { -+ public void q(int i) { // Paper - protected -> public - this.e = i; - } - -@@ -0,0 +0,0 @@ public class BaseBlockPosition implements Comparable { - return this.distanceSquared(iposition.getX(), iposition.getY(), iposition.getZ(), true) < d0 * d0; - } - -+ public final double distanceSquared(BaseBlockPosition baseblockposition) { return j(baseblockposition); } // Paper - OBFHELPER - public double j(BaseBlockPosition baseblockposition) { - return this.distanceSquared((double) baseblockposition.getX(), (double) baseblockposition.getY(), (double) baseblockposition.getZ(), true); - } -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - return d0 == 0.0D && d1 == 0.0D && d2 == 0.0D ? this : new BlockPosition((double) this.getX() + d0, (double) this.getY() + d1, (double) this.getZ() + d2); - } - -+ public final BlockPosition add(int i, int j, int k) {return b(i, j, k);} // Paper - OBFHELPER - public BlockPosition b(int i, int j, int k) { - return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); - } -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - return super.a(enumblockrotation).immutableCopy(); - } - -+ public final BlockPosition.MutableBlockPosition setValues(int i, int j, int k) { return d(i, j, k);} // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition d(int i, int j, int k) { - this.o(i); - this.p(j); -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - return this; - } - -+ public final BlockPosition.MutableBlockPosition setValues(double d0, double d1, double d2) { return c(d0, d1, d2);} // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition c(double d0, double d1, double d2) { - return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - } - } - -+ /* // Paper start - comment out useless overrides @Override - @Override - public void o(int i) { - super.o(i); -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - super.p(i); - } - -- @Override - public void q(int i) { - super.q(i); - } -+ */ // Paper end - - @Override - public BlockPosition immutableCopy() { -diff --git a/src/main/java/net/minecraft/core/RegistryBlockID.java b/src/main/java/net/minecraft/core/RegistryBlockID.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/RegistryBlockID.java -+++ b/src/main/java/net/minecraft/core/RegistryBlockID.java -@@ -0,0 +0,0 @@ public class RegistryBlockID implements Registry { - return Iterators.filter(this.c.iterator(), Predicates.notNull()); - } - -+ public int size() { return this.a(); } // Paper - OBFHELPER - public int a() { - return this.b.size(); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - return "TAG_Compound"; - } - }; -- private final Map map; -+ public final Map map; // Paper - - protected NBTTagCompound(Map map) { - this.map = map; -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - this.map.put(s, NBTTagLong.a(i)); - } - -+ public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER - public void a(String s, UUID uuid) { - this.map.put(s, GameProfileSerializer.a(uuid)); - } - -+ -+ /** -+ * You must use {@link #hasUUID(String)} before or else it will throw an NPE. -+ */ -+ public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER - public UUID a(String s) { - return GameProfileSerializer.a(this.get(s)); - } -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - } - -+ private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER - private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - EnumProtocol enumprotocol = EnumProtocol.a(packet); - EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - } - -+ private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER - private void p() { - if (this.channel != null && this.channel.isOpen()) { - Queue queue = this.packetQueue; -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - - static class QueuedPacket { - -- private final Packet a; -+ private final Packet a; private final Packet getPacket() { return this.a; } // Paper - OBFHELPER - @Nullable -- private final GenericFutureListener> b; -+ private final GenericFutureListener> b; private final GenericFutureListener> getGenericFutureListener() { return this.b; } // Paper - OBFHELPER - - public QueuedPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - this.a = packet; -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - this.a = bytebuf; - } - -+ public static int countBytes(int i) { return PacketDataSerializer.a(i); } // Paper - OBFHELPER - public static int a(int i) { - for (int j = 1; j < 5; ++j) { - if ((i & -1 << j * 7) == 0) { -diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketEncoder.java -+++ b/src/main/java/net/minecraft/network/PacketEncoder.java -@@ -0,0 +0,0 @@ public class PacketEncoder extends MessageToByteEncoder> { - packet.b(packetdataserializer); - } catch (Throwable throwable) { - PacketEncoder.LOGGER.error(throwable); -+ throwable.printStackTrace(); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? - if (packet.a()) { - throw new SkipEncodeException(throwable); - } else { -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInBEdit.java -@@ -0,0 +0,0 @@ import net.minecraft.world.item.ItemStack; - - public class PacketPlayInBEdit implements Packet { - -- private ItemStack a; -+ private ItemStack a; public ItemStack getBook() { return a; } // Paper - OBFHELPER - private boolean b; - private int c; - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMapChunk.java -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - private NBTTagCompound d; - @Nullable - private int[] e; -- private byte[] f; -+ private byte[] f; private byte[] getData() { return this.f; } // Paper - OBFHELPER - private List g; - private boolean h; - -@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - return bytebuf; - } - -+ public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, chunkSectionSelector); } // Paper - OBFHELPER - public int a(PacketDataSerializer packetdataserializer, Chunk chunk, int i) { - int j = 0; - ChunkSection[] achunksection = chunk.getSections(); -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ -+package net.minecraft.server; -+ -+import com.destroystokyo.paper.block.TargetBlockInfo; -+import com.google.common.util.concurrent.ThreadFactoryBuilder; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.RayTrace; -+import net.minecraft.world.level.World; -+import org.apache.commons.lang.exception.ExceptionUtils; -+import org.bukkit.Location; -+import org.bukkit.block.BlockFace; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.craftbukkit.util.Waitable; -+import org.spigotmc.AsyncCatcher; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.List; -+import java.util.Queue; -+import java.util.concurrent.CompletableFuture; -+import java.util.concurrent.ExecutionException; -+import java.util.concurrent.LinkedBlockingQueue; -+import java.util.concurrent.ThreadPoolExecutor; -+import java.util.concurrent.TimeUnit; -+import java.util.concurrent.TimeoutException; -+import java.util.concurrent.atomic.AtomicBoolean; -+import java.util.function.BiConsumer; -+import java.util.function.Consumer; -+import java.util.function.Supplier; -+ -+public final class MCUtil { -+ public static final ThreadPoolExecutor asyncExecutor = new ThreadPoolExecutor( -+ 0, 2, 60L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Async Task Handler Thread - %1$d").build() -+ ); -+ public static final ThreadPoolExecutor cleanerExecutor = new ThreadPoolExecutor( -+ 1, 1, 0L, TimeUnit.SECONDS, -+ new LinkedBlockingQueue(), -+ new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build() -+ ); -+ -+ public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE); -+ -+ -+ public static Runnable once(Runnable run) { -+ AtomicBoolean ran = new AtomicBoolean(false); -+ return () -> { -+ if (ran.compareAndSet(false, true)) { -+ run.run(); -+ } -+ }; -+ } -+ -+ public static Runnable once(List list, Consumer cb) { -+ return once(() -> { -+ list.forEach(cb); -+ }); -+ } -+ -+ private static Runnable makeCleanerCallback(Runnable run) { -+ return once(() -> cleanerExecutor.execute(run)); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param run -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, Runnable run) { -+ // Wrap callback in its own method above or the lambda will leak object -+ Runnable cleaner = makeCleanerCallback(run); -+ co.aikar.cleaner.Cleaner.register(obj, cleaner); -+ return cleaner; -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param list -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerListCleaner(Object obj, List list, Consumer cleaner) { -+ return registerCleaner(obj, () -> { -+ list.forEach(cleaner); -+ list.clear(); -+ }); -+ } -+ -+ /** -+ * DANGER WILL ROBINSON: Be sure you do not use a lambda that lives in the object being monitored, or leaky leaky! -+ * @param obj -+ * @param resource -+ * @param cleaner -+ * @param -+ * @return -+ */ -+ public static Runnable registerCleaner(Object obj, T resource, java.util.function.Consumer cleaner) { -+ return registerCleaner(obj, () -> cleaner.accept(resource)); -+ } -+ -+ public static List getSpiralOutChunks(BlockPosition blockposition, int radius) { -+ List list = com.google.common.collect.Lists.newArrayList(); -+ -+ list.add(new ChunkCoordIntPair(blockposition.getX() >> 4, blockposition.getZ() >> 4)); -+ for (int r = 1; r <= radius; r++) { -+ int x = -r; -+ int z = r; -+ -+ // Iterates the edge of half of the box; then negates for other half. -+ while (x <= r && z > -r) { -+ list.add(new ChunkCoordIntPair((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); -+ list.add(new ChunkCoordIntPair((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); -+ -+ if (x < r) { -+ x++; -+ } else { -+ z--; -+ } -+ } -+ } -+ return list; -+ } -+ -+ public static int fastFloor(double x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static int fastFloor(float x) { -+ int truncated = (int)x; -+ return x < (double)truncated ? truncated - 1 : truncated; -+ } -+ -+ public static float normalizeYaw(float f) { -+ float f1 = f % 360.0F; -+ -+ if (f1 >= 180.0F) { -+ f1 -= 360.0F; -+ } -+ -+ if (f1 < -180.0F) { -+ f1 += 360.0F; -+ } -+ -+ return f1; -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location -+ * -+ * @return Stacktrace -+ */ -+ public static String stack() { -+ return ExceptionUtils.getFullStackTrace(new Throwable()); -+ } -+ -+ /** -+ * Quickly generate a stack trace for current location with message -+ * -+ * @param str -+ * @return Stacktrace -+ */ -+ public static String stack(String str) { -+ return ExceptionUtils.getFullStackTrace(new Throwable(str)); -+ } -+ -+ public static long getCoordinateKey(final BlockPosition blockPos) { -+ return ((long)(blockPos.getZ() >> 4) << 32) | ((blockPos.getX() >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final Entity entity) { -+ return ((long)(MCUtil.fastFloor(entity.locZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.locX()) >> 4) & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final ChunkCoordIntPair pair) { -+ return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); -+ } -+ -+ public static long getCoordinateKey(final int x, final int z) { -+ return ((long)z << 32) | (x & 0xFFFFFFFFL); -+ } -+ -+ public static int getCoordinateX(final long key) { -+ return (int)key; -+ } -+ -+ public static int getCoordinateZ(final long key) { -+ return (int)(key >>> 32); -+ } -+ -+ public static int getChunkCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate) >> 4; -+ } -+ -+ public static int getBlockCoordinate(final double coordinate) { -+ return MCUtil.fastFloor(coordinate); -+ } -+ -+ public static long getBlockKey(final int x, final int y, final int z) { -+ return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); -+ } -+ -+ public static long getBlockKey(final BlockPosition pos) { -+ return ((long)pos.getX() & 0x7FFFFFF) | (((long)pos.getZ() & 0x7FFFFFF) << 27) | ((long)pos.getY() << 54); -+ } -+ -+ public static long getBlockKey(final Entity entity) { -+ return getBlockKey(getBlockCoordinate(entity.locX()), getBlockCoordinate(entity.locY()), getBlockCoordinate(entity.locZ())); -+ } -+ -+ // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable -+ public static void mergeSortedSets(final java.util.function.Consumer consumer, final java.util.Comparator comparator, final java.util.SortedSet...sets) { -+ final ObjectRBTreeSet all = new ObjectRBTreeSet<>(comparator); -+ // note: this is done in log(n!) ~ nlogn time. It could be improved if it were to mimic what mergesort does. -+ for (java.util.SortedSet set : sets) { -+ if (set != null) { -+ all.addAll(set); -+ } -+ } -+ all.forEach(consumer); -+ } -+ -+ private MCUtil() {} -+ -+ public static final java.util.concurrent.Executor MAIN_EXECUTOR = (run) -> { -+ if (!isMainThread()) { -+ MinecraftServer.getServer().execute(run); -+ } else { -+ run.run(); -+ } -+ }; -+ -+ public static CompletableFuture ensureMain(CompletableFuture future) { -+ return future.thenApplyAsync(r -> r, MAIN_EXECUTOR); -+ } -+ -+ public static void thenOnMain(CompletableFuture future, Consumer consumer) { -+ future.thenAcceptAsync(consumer, MAIN_EXECUTOR); -+ } -+ public static void thenOnMain(CompletableFuture future, BiConsumer consumer) { -+ future.whenCompleteAsync(consumer, MAIN_EXECUTOR); -+ } -+ -+ public static boolean isMainThread() { -+ return MinecraftServer.getServer().isMainThread(); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { -+ return scheduleTask(ticks, runnable, null); -+ } -+ -+ public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable, String taskName) { -+ return MinecraftServer.getServer().server.getScheduler().scheduleInternalTask(runnable, ticks, taskName); -+ } -+ -+ public static void processQueue() { -+ Runnable runnable; -+ Queue processQueue = getProcessQueue(); -+ while ((runnable = processQueue.poll()) != null) { -+ try { -+ runnable.run(); -+ } catch (Exception e) { -+ MinecraftServer.LOGGER.error("Error executing task", e); -+ } -+ } -+ } -+ public static T processQueueWhileWaiting(CompletableFuture future) { -+ try { -+ if (isMainThread()) { -+ while (!future.isDone()) { -+ try { -+ return future.get(1, TimeUnit.MILLISECONDS); -+ } catch (TimeoutException ignored) { -+ processQueue(); -+ } -+ } -+ } -+ return future.get(); -+ } catch (Exception e) { -+ throw new RuntimeException(e); -+ } -+ } -+ -+ public static void ensureMain(Runnable run) { -+ ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @return -+ */ -+ public static void ensureMain(String reason, Runnable run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "!").printStackTrace(); -+ } -+ getProcessQueue().add(run); -+ return; -+ } -+ run.run(); -+ } -+ -+ private static Queue getProcessQueue() { -+ return MinecraftServer.getServer().processQueue; -+ } -+ -+ public static T ensureMain(Supplier run) { -+ return ensureMain(null, run); -+ } -+ /** -+ * Ensures the target code is running on the main thread -+ * @param reason -+ * @param run -+ * @param -+ * @return -+ */ -+ public static T ensureMain(String reason, Supplier run) { -+ if (AsyncCatcher.enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread) { -+ if (reason != null) { -+ new IllegalStateException("Asynchronous " + reason + "! Blocking thread until it returns ").printStackTrace(); -+ } -+ Waitable wait = new Waitable() { -+ @Override -+ protected T evaluate() { -+ return run.get(); -+ } -+ }; -+ getProcessQueue().add(wait); -+ try { -+ return wait.get(); -+ } catch (InterruptedException | ExecutionException e) { -+ e.printStackTrace(); -+ } -+ return null; -+ } -+ return run.get(); -+ } -+ -+ /** -+ * Calculates distance between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(Entity e1, Entity e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ -+ /** -+ * Calculates distance between 2 block positions -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distance(BlockPosition e1, BlockPosition e2) { -+ return Math.sqrt(distanceSq(e1, e2)); -+ } -+ -+ /** -+ * Gets the distance between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distance(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return Math.sqrt(distanceSq(x1, y1, z1, x2, y2, z2)); -+ } -+ -+ /** -+ * Get's the distance squared between 2 entities -+ * @param e1 -+ * @param e2 -+ * @return -+ */ -+ public static double distanceSq(Entity e1, Entity e2) { -+ return distanceSq(e1.locX(),e1.locY(),e1.locZ(), e2.locX(),e2.locY(),e2.locZ()); -+ } -+ -+ /** -+ * Gets the distance sqaured between 2 block positions -+ * @param pos1 -+ * @param pos2 -+ * @return -+ */ -+ public static double distanceSq(BlockPosition pos1, BlockPosition pos2) { -+ return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); -+ } -+ -+ /** -+ * Gets the distance squared between 2 positions -+ * @param x1 -+ * @param y1 -+ * @param z1 -+ * @param x2 -+ * @param y2 -+ * @param z2 -+ * @return -+ */ -+ public static double distanceSq(double x1, double y1, double z1, double x2, double y2, double z2) { -+ return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param x -+ * @param y -+ * @param z -+ * @return -+ */ -+ public static Location toLocation(World world, double x, double y, double z) { -+ return new Location(world.getWorld(), x, y, z); -+ } -+ -+ /** -+ * Converts a NMS World/BlockPosition to Bukkit Location -+ * @param world -+ * @param pos -+ * @return -+ */ -+ public static Location toLocation(World world, BlockPosition pos) { -+ return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ /** -+ * Converts an NMS entity's current location to a Bukkit Location -+ * @param entity -+ * @return -+ */ -+ public static Location toLocation(Entity entity) { -+ return new Location(entity.getWorld().getWorld(), entity.locX(), entity.locY(), entity.locZ()); -+ } -+ -+ public static org.bukkit.block.Block toBukkitBlock(World world, BlockPosition pos) { -+ return world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); -+ } -+ -+ public static BlockPosition toBlockPosition(Location loc) { -+ return new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); -+ } -+ -+ public static boolean isEdgeOfChunk(BlockPosition pos) { -+ final int modX = pos.getX() & 15; -+ final int modZ = pos.getZ() & 15; -+ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); -+ } -+ -+ /** -+ * Posts a task to be executed asynchronously -+ * @param run -+ */ -+ public static void scheduleAsyncTask(Runnable run) { -+ asyncExecutor.execute(run); -+ } -+ -+ @Nonnull -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.World world) { -+ return ((CraftWorld) world).getHandle(); -+ } -+ -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { -+ return getNMSWorld(entity.getWorld()); -+ } -+ -+ public static RayTrace.FluidCollisionOption getNMSFluidCollisionOption(TargetBlockInfo.FluidMode fluidMode) { -+ if (fluidMode == TargetBlockInfo.FluidMode.NEVER) { -+ return RayTrace.FluidCollisionOption.NONE; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.SOURCE_ONLY) { -+ return RayTrace.FluidCollisionOption.SOURCE_ONLY; -+ } -+ if (fluidMode == TargetBlockInfo.FluidMode.ALWAYS) { -+ return RayTrace.FluidCollisionOption.ANY; -+ } -+ return null; -+ } -+ -+ public static BlockFace toBukkitBlockFace(EnumDirection enumDirection) { -+ switch (enumDirection) { -+ case DOWN: -+ return BlockFace.DOWN; -+ case UP: -+ return BlockFace.UP; -+ case NORTH: -+ return BlockFace.NORTH; -+ case SOUTH: -+ return BlockFace.SOUTH; -+ case WEST: -+ return BlockFace.WEST; -+ case EAST: -+ return BlockFace.EAST; -+ default: -+ return null; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant public - private final LightEngineThreaded lightEngine; - private final ChunkProviderServer.a serverThreadQueue; - public final PlayerChunkMap playerChunkMap; -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - private final IChunkAccess[] cacheChunk = new IChunkAccess[4]; - @Nullable - private SpawnerCreature.d p; -+ // Paper start -+ final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); -+ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); -+ -+ private final Chunk[] lastLoadedChunks = new Chunk[4 * 4]; -+ -+ private static int getChunkCacheKey(int x, int z) { -+ return x & 3 | ((z & 3) << 2); -+ } -+ -+ public void addLoadedChunk(Chunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.put(chunk.coordinateKey, chunk); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ this.lastLoadedChunks[cacheKey] = chunk; -+ } -+ -+ public void removeLoadedChunk(Chunk chunk) { -+ this.loadedChunkMapSeqLock.acquireWrite(); -+ try { -+ this.loadedChunkMap.remove(chunk.coordinateKey); -+ } finally { -+ this.loadedChunkMapSeqLock.releaseWrite(); -+ } -+ -+ // rewrite cache if we have to -+ // we do this since we also cache null chunks -+ int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { -+ this.lastLoadedChunks[cacheKey] = null; -+ } -+ } -+ -+ public final Chunk getChunkAtIfLoadedMainThread(int x, int z) { -+ int cacheKey = getChunkCacheKey(x, z); -+ -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; -+ if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { -+ return this.lastLoadedChunks[cacheKey]; -+ } -+ -+ long chunkKey = ChunkCoordIntPair.pair(x, z); -+ -+ cachedChunk = this.loadedChunkMap.get(chunkKey); -+ // Skipping a null check to avoid extra instructions to improve inline capability -+ this.lastLoadedChunks[cacheKey] = cachedChunk; -+ return cachedChunk; -+ } -+ -+ public final Chunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { -+ return this.loadedChunkMap.get(ChunkCoordIntPair.pair(x, z)); -+ } -+ -+ public final Chunk getChunkAtMainThread(int x, int z) { -+ Chunk ret = this.getChunkAtIfLoadedMainThread(x, z); -+ if (ret != null) { -+ return ret; -+ } -+ return (Chunk)this.getChunkAt(x, z, ChunkStatus.FULL, true); -+ } -+ -+ private long chunkFutureAwaitCounter; -+ -+ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getEntityTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 31, PlayerChunk::getEntityTickingFuture, onLoad); -+ } -+ -+ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getTickingChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 32, PlayerChunk::getTickingFuture, onLoad); -+ } -+ -+ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ this.serverThreadQueue.execute(() -> { -+ ChunkProviderServer.this.getFullChunkAsync(x, z, onLoad); -+ }); -+ return; -+ } -+ this.getChunkFutureAsynchronously(x, z, 33, PlayerChunk::getFullChunkFuture, onLoad); -+ } -+ -+ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { -+ throw new IllegalStateException(); -+ } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); -+ Long identifier = this.chunkFutureAwaitCounter++; -+ this.chunkMapDistance.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ this.tickDistanceManager(); -+ -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(chunkPos.pair()); -+ -+ if (chunk == null) { -+ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.world.getWorld().getName() + "'"); -+ } -+ -+ CompletableFuture> future = futureGet.apply(chunk); -+ -+ future.whenCompleteAsync((either, throwable) -> { -+ try { -+ if (throwable != null) { -+ if (throwable instanceof ThreadDeath) { -+ throw (ThreadDeath)throwable; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", throwable); -+ } else if (either.right().isPresent()) { -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "': " + either.right().get().toString()); -+ } -+ -+ try { -+ if (onLoad != null) { -+ playerChunkMap.callbackExecutor.execute(() -> { -+ onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. -+ }); -+ } -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ChunkProviderServer.this.world.getWorld().getName() + "'", thr); -+ return; -+ } -+ } finally { -+ // due to odd behaviour with CB unload implementation we need to have these AFTER the load callback. -+ ChunkProviderServer.this.chunkMapDistance.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); -+ ChunkProviderServer.this.chunkMapDistance.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ } -+ }, this.serverThreadQueue); -+ } -+ // Paper end - - public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { - this.world = worldserver; -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - this.cacheChunk[0] = ichunkaccess; - } - -+ // Paper start - "real" get chunk if loaded -+ // Note: Partially copied from the getChunkAt method below -+ @Nullable -+ public Chunk getChunkAtIfCachedImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe -+ -+ PlayerChunk playerChunk = this.getChunk(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getFullChunkIfCached(); -+ } -+ -+ @Nullable -+ public Chunk getChunkAtIfLoadedImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ if (Thread.currentThread() == this.serverThread) { -+ return this.getChunkAtIfLoadedMainThread(x, z); -+ } -+ -+ Chunk ret = null; -+ long readlock; -+ do { -+ readlock = this.loadedChunkMapSeqLock.acquireRead(); -+ try { -+ ret = this.loadedChunkMap.get(k); -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ // re-try, this means a CME occurred... -+ continue; -+ } -+ } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); -+ -+ return ret; -+ } -+ // Paper end -+ - @Nullable - @Override - public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - - this.p = spawnercreature_d; - this.world.getMethodProfiler().exit(); -- List list = Lists.newArrayList(this.playerChunkMap.f()); -- -- Collections.shuffle(list); -- list.forEach((playerchunk) -> { -+ //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper -+ //Collections.shuffle(list); // Paper -+ this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public Integer clientViewDistance; - // CraftBukkit end - -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.c(worldserver); - this.co = minecraftserver.a(this); - -+ this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper -+ - // CraftBukkit start - this.displayName = this.getName(); - this.canPickUpLoot = true; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - private static final List CHUNK_STATUSES = ChunkStatus.a(); - private static final PlayerChunk.State[] CHUNK_STATES = PlayerChunk.State.values(); - private final AtomicReferenceArray>> statusFutures; -- private volatile CompletableFuture> fullChunkFuture; -- private volatile CompletableFuture> tickingFuture; -- private volatile CompletableFuture> entityTickingFuture; -+ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> tickingFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage -+ private volatile CompletableFuture> entityTickingFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage - private CompletableFuture chunkSave; - public int oldTicketLevel; - private int ticketLevel; -@@ -0,0 +0,0 @@ public class PlayerChunk { - private boolean hasBeenLoaded; - private boolean x; - -+ private final PlayerChunkMap chunkMap; // Paper -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -0,0 +0,0 @@ public class PlayerChunk { - this.ticketLevel = this.oldTicketLevel; - this.n = this.oldTicketLevel; - this.a(i); -+ this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper -+ } -+ -+ // Paper start -+ @Nullable -+ public final Chunk getEntityTickingChunk() { -+ CompletableFuture> completablefuture = this.entityTickingFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final Chunk getTickingChunk() { -+ CompletableFuture> completablefuture = this.tickingFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ @Nullable -+ public final Chunk getFullReadyChunk() { -+ CompletableFuture> completablefuture = this.fullChunkFuture; -+ Either either = completablefuture.getNow(null); -+ -+ return either == null ? null : either.left().orElse(null); -+ } -+ -+ public final boolean isEntityTickingReady() { -+ return this.isEntityTickingReady; -+ } -+ -+ public final boolean isTickingReady() { -+ return this.isTickingReady; -+ } -+ -+ public final boolean isFullChunkReady() { -+ return this.isFullChunkReady; - } -+ // Paper end - - // CraftBukkit start -- public Chunk getFullChunk() { -+ public final Chunk getFullChunk() { // Paper - final for inline - if (!getChunkState(this.oldTicketLevel).isAtLeast(PlayerChunk.State.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks - return this.getFullChunkUnchecked(); - } -@@ -0,0 +0,0 @@ public class PlayerChunk { - return (either == null) ? null : (Chunk) either.left().orElse(null); - } - // CraftBukkit end -+ // Paper start - "real" get full chunk immediately -+ public final Chunk getFullChunkIfCached() { -+ // Note: Copied from above without ticket level check -+ CompletableFuture> statusFuture = this.getStatusFutureUnchecked(ChunkStatus.FULL); -+ Either either = (Either) statusFuture.getNow(null); -+ return either == null ? null : (Chunk) either.left().orElse(null); -+ } -+ // Paper end - - public CompletableFuture> getStatusFutureUnchecked(ChunkStatus chunkstatus) { - CompletableFuture> completablefuture = (CompletableFuture) this.statusFutures.get(chunkstatus.c()); -@@ -0,0 +0,0 @@ public class PlayerChunk { - return getChunkStatus(this.ticketLevel).b(chunkstatus) ? this.getStatusFutureUnchecked(chunkstatus) : PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE; - } - -- public CompletableFuture> a() { -+ public final CompletableFuture> getTickingFuture() { return this.a(); } // Paper - OBFHELPER -+ public final CompletableFuture> a() { // Paper - final for inline - return this.tickingFuture; - } - -- public CompletableFuture> b() { -+ public final CompletableFuture> getEntityTickingFuture() { return this.b(); } // Paper - OBFHELPER -+ public final CompletableFuture> b() { // Paper - final for inline - return this.entityTickingFuture; - } - -- public CompletableFuture> c() { -+ public final CompletableFuture> getFullChunkFuture() { return this.c(); } // Paper - OBFHELPER -+ public final CompletableFuture> c() { // Paper - final for inline - return this.fullChunkFuture; - } - - @Nullable -- public Chunk getChunk() { -+ public final Chunk getChunk() { // Paper - final for inline - CompletableFuture> completablefuture = this.a(); - Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error - -@@ -0,0 +0,0 @@ public class PlayerChunk { - return null; - } - -- public CompletableFuture getChunkSave() { -+ public final CompletableFuture getChunkSave() { // Paper - final for inline - return this.chunkSave; - } - -@@ -0,0 +0,0 @@ public class PlayerChunk { - }); - } - -- public ChunkCoordIntPair i() { -+ public final ChunkCoordIntPair i() { // Paper - final for inline - return this.location; - } - -- public int getTicketLevel() { -+ public final int getTicketLevel() { // Paper - final for inline - return this.ticketLevel; - } - -@@ -0,0 +0,0 @@ public class PlayerChunk { - - this.hasBeenLoaded |= flag3; - if (!flag2 && flag3) { -- this.fullChunkFuture = playerchunkmap.b(this); -+ // Paper start - cache ticking ready status -+ int expectCreateCount = ++this.fullChunkCreateCount; -+ this.fullChunkFuture = playerchunkmap.b(this); this.fullChunkFuture.thenAccept((either) -> { -+ if (either.left().isPresent() && PlayerChunk.this.fullChunkCreateCount == expectCreateCount) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk fullChunk = either.left().get(); -+ PlayerChunk.this.isFullChunkReady = true; -+ fullChunk.playerChunk = PlayerChunk.this; -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.fullChunkFuture); - } - - if (flag2 && !flag3) { - completablefuture = this.fullChunkFuture; - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -+ ++this.fullChunkCreateCount; // Paper - cache ticking ready status -+ this.isFullChunkReady = false; // Paper - cache ticking ready status - this.a(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error - playerchunkmap.getClass(); - return either1.ifLeft(playerchunkmap::a); -@@ -0,0 +0,0 @@ public class PlayerChunk { - boolean flag5 = playerchunk_state1.isAtLeast(PlayerChunk.State.TICKING); - - if (!flag4 && flag5) { -- this.tickingFuture = playerchunkmap.a(this); -+ // Paper start - cache ticking ready status -+ this.tickingFuture = playerchunkmap.a(this); this.tickingFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk tickingChunk = either.left().get(); -+ PlayerChunk.this.isTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.tickingFuture); - } - - if (flag4 && !flag5) { -- this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); -+ this.tickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage - this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -@@ -0,0 +0,0 @@ public class PlayerChunk { - throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException())); - } - -- this.entityTickingFuture = playerchunkmap.b(this.location); -+ // Paper start - cache ticking ready status -+ this.entityTickingFuture = playerchunkmap.b(this.location); this.entityTickingFuture.thenAccept((either) -> { -+ if (either.left().isPresent()) { -+ // note: Here is a very good place to add callbacks to logic waiting on this. -+ Chunk entityTickingChunk = either.left().get(); -+ PlayerChunk.this.isEntityTickingReady = true; -+ -+ -+ -+ -+ } -+ }); -+ // Paper end - this.a(this.entityTickingFuture); - } - - if (flag6 && !flag7) { -- this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); -+ this.entityTickingFuture.complete(PlayerChunk.UNLOADED_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage - this.entityTickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - // CraftBukkit end - -+ // Paper start - distance maps -+ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ -+ void addPlayerToDistanceMaps(EntityPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ -+ void removePlayerFromDistanceMaps(EntityPlayer player) { -+ -+ } -+ -+ void updateMaps(EntityPlayer player) { -+ int chunkX = MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); -+ // Note: players need to be explicitly added to distance maps before they can be updated -+ } -+ // Paper end -+ - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); - this.visibleChunks = this.updatingChunks.clone(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - }; - } - -+ // Paper start -+ public final int getEffectiveViewDistance() { -+ // TODO this needs to be checked on update -+ // Mojang currently sets it to +1 of the configured view distance. So subtract one to get the one we really want. -+ return this.viewDistance - 1; -+ } -+ // Paper end -+ - private CompletableFuture, PlayerChunk.Failure>> a(ChunkCoordIntPair chunkcoordintpair, int i, IntFunction intfunction) { - List>> list = Lists.newArrayList(); - int j = chunkcoordintpair.x; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!flag1) { - this.chunkDistanceManager.a(SectionPosition.a((Entity) entityplayer), entityplayer); - } -+ this.addPlayerToDistanceMaps(entityplayer); // Paper - distance maps - } else { - SectionPosition sectionposition = entityplayer.O(); - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!flag2) { - this.chunkDistanceManager.b(sectionposition, entityplayer); - } -+ this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps - } - - for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -+ this.updateMaps(entityplayer); // Paper - distance maps -+ - } - - @Override -diff --git a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -+++ b/src/main/java/net/minecraft/server/level/RegionLimitedWorldAccess.java -@@ -0,0 +0,0 @@ public class RegionLimitedWorldAccess implements GeneratorAccessSeed { - return i >= this.n.x && i <= this.o.x && j >= this.n.z && j <= this.o.z; - } - -+ // Paper start - if loaded util -+ @Nullable -+ @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return this.getChunkAt(x, z, ChunkStatus.FULL, false); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4).getType(blockposition); -diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/TicketType.java -+++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -0,0 +0,0 @@ public class TicketType { - public static final TicketType UNKNOWN = a("unknown", Comparator.comparingLong(ChunkCoordIntPair::pair), 1); - public static final TicketType PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit - public static final TicketType PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit -+ public static final TicketType FUTURE_AWAIT = a("future_await", Long::compareTo); // Paper - - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry; - import it.unimi.dsi.fastutil.longs.LongSet; - import it.unimi.dsi.fastutil.longs.LongSets; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; - import java.io.BufferedWriter; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private final Map entitiesByUUID = Maps.newHashMap(); - private final Queue entitiesToAdd = Queues.newArrayDeque(); - private final List players = Lists.newArrayList(); -- private final ChunkProviderServer chunkProvider; -+ public final ChunkProviderServer chunkProvider; // Paper - public - boolean tickingEntities; - private final MinecraftServer server; - public final WorldDataServer worldDataServer; // CraftBukkit - type -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - ObjectIterator objectiterator = spawnercreature_d.b().object2IntEntrySet().iterator(); - - while (objectiterator.hasNext()) { -- it.unimi.dsi.fastutil.objects.Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (it.unimi.dsi.fastutil.objects.Object2IntMap.Entry) objectiterator.next(); -+ Object2IntMap.Entry it_unimi_dsi_fastutil_objects_object2intmap_entry = (Object2IntMap.Entry) objectiterator.next(); // Paper - decompile fix - - bufferedwriter.write(String.format("spawn_count.%s: %d\n", ((EnumCreatureType) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey()).b(), it_unimi_dsi_fastutil_objects_object2intmap_entry.getIntValue())); - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private final MinecraftServer minecraftServer; - public EntityPlayer player; - private int e; -- private long lastKeepAlive; -- private boolean awaitingKeepAlive; -- private long h; -+ private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -+ private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER -+ private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -0,0 +0,0 @@ public class DataBits { - return (int) (k >> l & this.d); - } - -+ public final long[] getDataBits() { return this.a(); } // Paper - OBFHELPER - public long[] a() { - return this.b; - } -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -+++ b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java -@@ -0,0 +0,0 @@ public abstract class IAsyncTaskHandler implements Mailbox entitytypes, World world) { - super(entitytypes, world); - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - return this.goalTarget; - } - -+ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper - public void setGoalTarget(@Nullable EntityLiving entityliving) { - // CraftBukkit start - fire event - setGoalTarget(entityliving, EntityTargetEvent.TargetReason.UNKNOWN, true); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - public boolean collides = true; - public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; -+ public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper - - @Override - public float getBukkitYaw() { -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ package net.minecraft.world.entity; - import com.google.common.collect.ImmutableSet; - import java.util.Optional; - import java.util.Set; // Paper -+import java.util.Map; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -0,0 +0,0 @@ public class EntityTypes { - return this.br.height; - } - -- @Nullable -- public T a(World world) { -+ public T create(World world) { return this.a(world); } // Paper - OBFHELPER -+ @Nullable public T a(World world) { // Paper - OBFHELPER - return this.bf.create(this, world); - } - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityMonster.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.WorldAccess; - - public abstract class EntityMonster extends EntityCreature implements IMonster { - -+ public org.bukkit.craftbukkit.entity.CraftMonster getBukkitMonster() { return (org.bukkit.craftbukkit.entity.CraftMonster) super.getBukkitEntity(); } // Paper - protected EntityMonster(EntityTypes entitytypes, World world) { - super(entitytypes, world); - this.f = 5; -diff --git a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -+++ b/src/main/java/net/minecraft/world/entity/player/PlayerInventory.java -@@ -0,0 +0,0 @@ public class PlayerInventory implements IInventory, INamableTileEntity { - public final NonNullList items; - public final NonNullList armor; - public final NonNullList extraSlots; -- private final List> f; -+ private final List> f; public final List> getComponents() { return f; } // Paper - OBFHELPER - public int itemInHandIndex; - public final EntityHuman player; - private ItemStack carried; -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - })).apply(instance, ItemStack::new); - }); - private static final Logger LOGGER = LogManager.getLogger(); -- public static final ItemStack b = new ItemStack((Item) null); -+ public static final ItemStack b = new ItemStack((Item) null);public static final ItemStack NULL_ITEM = b; // Paper - OBFHELPER - public static final DecimalFormat c = (DecimalFormat) SystemUtils.a((new DecimalFormat("#.##")), (decimalformat) -> { // CraftBukkit - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); -@@ -0,0 +0,0 @@ public final class ItemStack { - return this.tag != null ? this.tag.getList("Enchantments", 10) : new NBTTagList(); - } - -+ // Paper start - (this is just a good no conflict location) -+ public org.bukkit.inventory.ItemStack asBukkitMirror() { -+ return CraftItemStack.asCraftMirror(this); -+ } -+ public org.bukkit.inventory.ItemStack asBukkitCopy() { -+ return CraftItemStack.asCraftMirror(this.cloneItemStack()); -+ } -+ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) { -+ return CraftItemStack.asNMSCopy(itemstack); -+ } -+ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack; -+ public org.bukkit.inventory.ItemStack getBukkitStack() { -+ if (bukkitStack == null || bukkitStack.getHandle() != this) { -+ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this); -+ } -+ return bukkitStack; -+ } -+ // Paper end - public void setTag(@Nullable NBTTagCompound nbttagcompound) { - this.tag = nbttagcompound; - if (this.getItem().usesDurability()) { -@@ -0,0 +0,0 @@ public final class ItemStack { - return this.tag != null && this.tag.hasKeyOfType("Enchantments", 9) ? !this.tag.getList("Enchantments", 10).isEmpty() : false; - } - -+ public void getOrCreateTagAndSet(String s, NBTBase nbtbase) { a(s, nbtbase);} // Paper - OBFHELPER - public void a(String s, NBTBase nbtbase) { - this.getOrCreateTag().set(s, nbtbase); - } -@@ -0,0 +0,0 @@ public final class ItemStack { - // CraftBukkit start - @Deprecated - public void setItem(Item item) { -+ this.bukkitStack = null; // Paper - this.item = item; - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -+++ b/src/main/java/net/minecraft/world/item/alchemy/PotionUtil.java -@@ -0,0 +0,0 @@ public class PotionUtil { - return nbttagcompound == null ? Potions.EMPTY : PotionRegistry.a(nbttagcompound.getString("Potion")); - } - -+ public static ItemStack addPotionToItemStack(ItemStack itemstack, PotionRegistry potionregistry) { return a(itemstack, potionregistry); } // Paper - OBFHELPER - public static ItemStack a(ItemStack itemstack, PotionRegistry potionregistry) { - MinecraftKey minecraftkey = IRegistry.POTION.getKey(potionregistry); - -diff --git a/src/main/java/net/minecraft/world/level/BlockAccessAir.java b/src/main/java/net/minecraft/world/level/BlockAccessAir.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/BlockAccessAir.java -+++ b/src/main/java/net/minecraft/world/level/BlockAccessAir.java -@@ -0,0 +0,0 @@ public enum BlockAccessAir implements IBlockAccess { - return null; - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - return Blocks.AIR.getBlockData(); -diff --git a/src/main/java/net/minecraft/world/level/ChunkCache.java b/src/main/java/net/minecraft/world/level/ChunkCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCache.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCache.java -@@ -0,0 +0,0 @@ import java.util.function.Predicate; - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -@@ -0,0 +0,0 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - protected final int b; - protected final IChunkAccess[][] c; - protected boolean d; -- protected final World e; -+ protected final World e; protected final World getWorld() { return e; } // Paper - OBFHELPER - - public ChunkCache(World world, BlockPosition blockposition, BlockPosition blockposition1) { - this.e = world; -@@ -0,0 +0,0 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - - for (k = this.a; k <= i; ++k) { - for (l = this.b; l <= j; ++l) { -- this.c[k - this.a][l - this.b] = ichunkprovider.a(k, l); -+ this.c[k - this.a][l - this.b] = ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(k, l); // Paper - } - } - -@@ -0,0 +0,0 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - int k = i - this.a; - int l = j - this.b; - -- if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { -+ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { // Paper - if this changes, update getChunkIfLoaded below - IChunkAccess ichunkaccess = this.c[k][l]; - - return (IChunkAccess) (ichunkaccess != null ? ichunkaccess : new ChunkEmpty(this.e, new ChunkCoordIntPair(i, j))); -@@ -0,0 +0,0 @@ public class ChunkCache implements IBlockAccess, ICollisionAccess { - return this.a(i, j); - } - -+ // Paper start - if loaded util -+ private IChunkAccess getChunkIfLoaded(int x, int z) { -+ int k = x - this.a; -+ int l = z - this.b; -+ -+ if (k >= 0 && k < this.c.length && l >= 0 && l < this.c[k].length) { -+ return this.c[k][l]; -+ } -+ return null; -+ } -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ // Paper end -+ - @Nullable - @Override - public TileEntity getTileEntity(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -0,0 +0,0 @@ public class ChunkCoordIntPair { - public static final long a = pair(1875016, 1875016); - public final int x; - public final int z; -+ public final long longKey; // Paper - - public ChunkCoordIntPair(int i, int j) { - this.x = i; - this.z = j; -+ this.longKey = pair(this.x, this.z); // Paper - } - - public ChunkCoordIntPair(BlockPosition blockposition) { - this.x = blockposition.getX() >> 4; - this.z = blockposition.getZ() >> 4; -+ this.longKey = pair(this.x, this.z); // Paper - } - - public ChunkCoordIntPair(long i) { - this.x = (int) i; - this.z = (int) (i >> 32); -+ this.longKey = pair(this.x, this.z); // Paper - } - - public long pair() { -- return pair(this.x, this.z); -+ return longKey; // Paper - } - -- public static long pair(int i, int j) { -+ public static long pair(final BlockPosition pos) { return pair(pos.getX() >> 4, pos.getZ() >> 4); } // Paper - OBFHELPER -+ public static long pair(int i, int j) { - return (long) i & 4294967295L | ((long) j & 4294967295L) << 32; - } - -diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/IBlockAccess.java -+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java -@@ -0,0 +0,0 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.entity.TileEntity; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.material.Fluid; -+import net.minecraft.world.level.material.Material; - import net.minecraft.world.phys.AxisAlignedBB; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; -@@ -0,0 +0,0 @@ public interface IBlockAccess { - TileEntity getTileEntity(BlockPosition blockposition); - - IBlockData getType(BlockPosition blockposition); -+ // Paper start - if loaded util -+ IBlockData getTypeIfLoaded(BlockPosition blockposition); -+ default Material getMaterialIfLoaded(BlockPosition blockposition) { -+ IBlockData type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getMaterial(); -+ } -+ -+ default Block getBlockIfLoaded(BlockPosition blockposition) { -+ IBlockData type = this.getTypeIfLoaded(blockposition); -+ return type == null ? null : type.getBlock(); -+ } -+ Fluid getFluidIfLoaded(BlockPosition blockposition); -+ // Paper end - - Fluid getFluid(BlockPosition blockposition); - -diff --git a/src/main/java/net/minecraft/world/level/IWorldReader.java b/src/main/java/net/minecraft/world/level/IWorldReader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/IWorldReader.java -+++ b/src/main/java/net/minecraft/world/level/IWorldReader.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.AxisAlignedBB; - - public interface IWorldReader extends IBlockLightAccess, ICollisionAccess, BiomeManager.Provider { - -+ @Nullable IChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) - @Nullable - IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag); - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -+import org.bukkit.craftbukkit.block.CraftBlockState; - import org.bukkit.craftbukkit.block.data.CraftBlockData; - import org.bukkit.event.block.BlockPhysicsEvent; - // CraftBukkit end -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return i < 0 || i >= 256; - } - -- public Chunk getChunkAtWorldCoords(BlockPosition blockposition) { -+ public final Chunk getChunkAtWorldCoords(BlockPosition blockposition) { // Paper - help inline - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); - } - - @Override -- public Chunk getChunkAt(int i, int j) { -- return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL); -+ public final Chunk getChunkAt(int i, int j) { // Paper - final to help inline -+ return (Chunk) this.getChunkAt(i, j, ChunkStatus.FULL, true); // Paper - avoid a method jump -+ } -+ -+ // Paper start - if loaded -+ @Nullable -+ @Override -+ public final IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return ((WorldServer)this).chunkProvider.getChunkAtIfLoadedImmediately(x, z); - } - - @Override -- public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -+ public final IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ // CraftBukkit start - tree generation -+ if (captureTreeGeneration) { -+ CraftBlockState previous = capturedBlockStates.get(blockposition); -+ if (previous != null) { -+ return previous.getHandle(); -+ } -+ } -+ // CraftBukkit end -+ if (!isValidLocation(blockposition)) { -+ return Blocks.AIR.getBlockData(); -+ } -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getType(blockposition); -+ } -+ -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ -+ return chunk == null ? null : chunk.getFluid(blockposition); -+ } -+ // Paper end -+ -+ @Override -+ public final IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { // Paper - final for inline - IChunkAccess ichunkaccess = this.getChunkProvider().getChunkAt(i, j, chunkstatus, flag); - - if (ichunkaccess == null && flag) { -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - @Override -- public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { -+ public final boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) { // Paper - final for inline - return this.a(blockposition, iblockdata, i, 512); - } - -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public void a(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1) {} - -- @Override -- public boolean a(BlockPosition blockposition, boolean flag) { -+ public boolean setAir(BlockPosition blockposition) { return this.a(blockposition, false); } // Paper - OBFHELPER -+ public boolean setAir(BlockPosition blockposition, boolean moved) { return this.a(blockposition, moved); } // Paper - OBFHELPER -+ @Override public boolean a(BlockPosition blockposition, boolean flag) { // Paper - OBFHELPER - Fluid fluid = this.getFluid(blockposition); - - return this.setTypeAndData(blockposition, fluid.getBlockData(), 3 | (flag ? 64 : 0)); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - if (isOutsideWorld(blockposition)) { - return Blocks.VOID_AIR.getBlockData(); - } else { -- Chunk chunk = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ Chunk chunk = (Chunk) this.getChunkProvider().getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, true); // Paper - manually inline to reduce hops and avoid unnecessary null check to reduce total byte code size, this should never return null and if it does we will see it the next line but the real stack trace will matter in the chunk engine - - return chunk.getType(blockposition); - } -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -0,0 +0,0 @@ public abstract class BlockBase { - return this.a != null ? this.a.d : Block.a(this.getCollisionShape(iblockaccess, blockposition)); - } - -+ public final IBlockData getBlockData() { return p(); } // Paper - OBFHELPER - protected abstract IBlockData p(); - - public boolean isRequiresSpecialTool() { -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -0,0 +0,0 @@ public class WorldBorder { - return this.b(entity.locX(), entity.locZ()); - } - -+ public final VoxelShape asVoxelShape(){ return c();} // Paper - OBFHELPER - public VoxelShape c() { - return this.j.m(); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - private static final Logger LOGGER = LogManager.getLogger(); - @Nullable -- public static final ChunkSection a = null; -+ public static final ChunkSection a = null; public static final ChunkSection EMPTY_CHUNK_SECTION = a; // Paper - OBFHELPER - private final ChunkSection[] sections; - private BiomeStorage d; - private final Map e; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - private Supplier u; - @Nullable - private Consumer v; -- private final ChunkCoordIntPair loc; -+ private final ChunkCoordIntPair loc; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key - private volatile boolean x; - - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage) { -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - this.n = new ShortList[16]; - this.entitySlices = (List[]) (new List[16]); // Spigot - this.world = (WorldServer) world; // CraftBukkit - type -- this.loc = chunkcoordintpair; -+ this.locX = chunkcoordintpair.x; this.locZ = chunkcoordintpair.z; // Paper - reduce need for field look ups -+ this.loc = chunkcoordintpair; this.coordinateKey = ChunkCoordIntPair.pair(locX, locZ); // Paper - cache long key - this.i = chunkconverter; - HeightMap.Type[] aheightmap_type = HeightMap.Type.values(); - int j = aheightmap_type.length; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); - // CraftBukkit end - -+ // Paper start -+ public final com.destroystokyo.paper.util.maplist.EntityList entities = new com.destroystokyo.paper.util.maplist.EntityList(); -+ public PlayerChunk playerChunk; -+ -+ static final int NEIGHBOUR_CACHE_RADIUS = 3; -+ public static int getNeighbourCacheRadius() { -+ return NEIGHBOUR_CACHE_RADIUS; -+ } -+ -+ boolean loadedTicketLevel; -+ private long neighbourChunksLoadedBitset; -+ private final Chunk[] loadedNeighbourChunks = new Chunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; -+ -+ private static int getNeighbourIndex(final int relativeX, final int relativeZ) { -+ // index = (relativeX + NEIGHBOUR_CACHE_RADIUS) + (relativeZ + NEIGHBOUR_CACHE_RADIUS) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1) -+ // optimised variant of the above by moving some of the ops to compile time -+ return relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))); -+ } -+ -+ public final Chunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { -+ return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; -+ } -+ -+ public final boolean isNeighbourLoaded(final int relativeX, final int relativeZ) { -+ return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; -+ } -+ -+ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final Chunk chunk) { -+ if (chunk == null) { -+ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.loc); -+ } -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = chunk; -+ this.neighbourChunksLoadedBitset |= (1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void setNeighbourUnloaded(final int relativeX, final int relativeZ) { -+ final long before = this.neighbourChunksLoadedBitset; -+ final int index = getNeighbourIndex(relativeX, relativeZ); -+ this.loadedNeighbourChunks[index] = null; -+ this.neighbourChunksLoadedBitset &= ~(1L << index); -+ this.onNeighbourChange(before, this.neighbourChunksLoadedBitset); -+ } -+ -+ public final void resetNeighbours() { -+ final long before = this.neighbourChunksLoadedBitset; -+ this.neighbourChunksLoadedBitset = 0L; -+ java.util.Arrays.fill(this.loadedNeighbourChunks, null); -+ this.onNeighbourChange(before, 0L); -+ } -+ -+ protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ -+ } -+ -+ public final boolean isAnyNeighborsLoaded() { -+ return neighbourChunksLoadedBitset != 0; -+ } -+ public final boolean areNeighboursLoaded(final int radius) { -+ return Chunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); -+ } -+ -+ public static boolean areNeighboursLoaded(final long bitset, final int radius) { -+ // index = relativeX + (relativeZ * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)) + (NEIGHBOUR_CACHE_RADIUS + NEIGHBOUR_CACHE_RADIUS * ((NEIGHBOUR_CACHE_RADIUS * 2 + 1))) -+ switch (radius) { -+ case 0: { -+ return (bitset & (1L << getNeighbourIndex(0, 0))) != 0; -+ } -+ case 1: { -+ long mask = 0L; -+ for (int dx = -1; dx <= 1; ++dx) { -+ for (int dz = -1; dz <= 1; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 2: { -+ long mask = 0L; -+ for (int dx = -2; dx <= 2; ++dx) { -+ for (int dz = -2; dz <= 2; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ case 3: { -+ long mask = 0L; -+ for (int dx = -3; dx <= 3; ++dx) { -+ for (int dz = -3; dz <= 3; ++dz) { -+ mask |= (1L << getNeighbourIndex(dx, dz)); -+ } -+ } -+ return (bitset & mask) == mask; -+ } -+ -+ default: -+ throw new IllegalArgumentException("Radius not recognized: " + radius); -+ } -+ } -+ // Paper end -+ - public Chunk(World world, ProtoChunk protochunk) { - this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.getInhabitedTime(), protochunk.getSections(), (Consumer) null); - Iterator iterator = protochunk.y().iterator(); -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public Fluid getFluid(BlockPosition blockposition) { - return this.a(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - entity.chunkX = this.loc.x; - entity.chunkY = k; - entity.chunkZ = this.loc.z; -+ this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); - } - -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - - this.entitySlices[i].remove(entity); -+ this.entities.remove(entity); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - return this.a(blockposition, Chunk.EnumTileEntityState.CHECK); - } - -+ @Nullable public final TileEntity getTileEntityImmediately(BlockPosition pos) { return this.a(pos, EnumTileEntityState.IMMEDIATE); } // Paper - OBFHELPER - @Nullable - public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { - // CraftBukkit start -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - // CraftBukkit start - public void loadCallback() { -+ // Paper start - neighbour cache -+ int chunkX = this.loc.x; -+ int chunkZ = this.loc.z; -+ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourLoaded(-dx, -dz, this); -+ // should be in cached already -+ this.setNeighbourLoaded(dx, dz, neighbour); -+ } -+ } -+ } -+ this.setNeighbourLoaded(0, 0, this); -+ this.loadedTicketLevel = true; -+ // Paper end - neighbour cache - org.bukkit.Server server = this.world.getServer(); -+ ((WorldServer)this.world).getChunkProvider().addLoadedChunk(this); // Paper - if (server != null) { - /* - * If it's a new world, the first few chunks are generated inside -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - server.getPluginManager().callEvent(unloadEvent); - // note: saving can be prevented, but not forced if no saving is actually required - this.mustNotSave = !unloadEvent.isSaveChunk(); -+ ((WorldServer)this.world).getChunkProvider().removeLoadedChunk(this); // Paper -+ // Paper start - neighbour cache -+ int chunkX = this.loc.x; -+ int chunkZ = this.loc.z; -+ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); -+ for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) { -+ for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) { -+ Chunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); -+ if (neighbour != null) { -+ neighbour.setNeighbourUnloaded(-dx, -dz); -+ } -+ } -+ } -+ this.loadedTicketLevel = false; -+ this.resetNeighbours(); -+ // Paper end - } - // CraftBukkit end - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -0,0 +0,0 @@ public class ChunkSection { - return this.blockIds; - } - -+ public void writeChunkSection(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER - public void b(PacketDataSerializer packetdataserializer) { - packetdataserializer.writeShort(this.nonEmptyBlockCount); - this.blockIds.b(packetdataserializer); -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPalette.java -@@ -0,0 +0,0 @@ import net.minecraft.network.PacketDataSerializer; - - public interface DataPalette { - -+ default int getOrCreateIdFor(T object) { return this.a(object); } // Paper - OBFHELPER - int a(T t0); - - boolean a(Predicate predicate); - -+ @Nullable default T getObject(int dataBits) { return this.a(dataBits); } // Paper - OBFHELPER - @Nullable - T a(int i); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -0,0 +0,0 @@ import net.minecraft.util.MathHelper; - - public class DataPaletteBlock implements DataPaletteExpandable { - -- private final DataPalette b; -+ private final DataPalette b; private final DataPalette getDataPaletteGlobal() { return this.b; } // Paper - OBFHELPER - private final DataPaletteExpandable c = (i, object) -> { - return 0; - }; -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private final Function e; - private final Function f; - private final T g; -- protected DataBits a; -- private DataPalette h; -- private int i; -+ protected DataBits a; public final DataBits getDataBits() { return this.a; } // Paper - OBFHELPER -+ private DataPalette h; private DataPalette getDataPalette() { return this.h; } // Paper - OBFHELPER -+ private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER - private final ReentrantLock j = new ReentrantLock(); - - public void a() { -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return j << 8 | k << 4 | i; - } - -+ private void initialize(int bitsPerObject) { this.b(bitsPerObject); } // Paper - OBFHELPER - private void b(int i) { - if (i != this.i) { - this.i = i; -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - return t0 == null ? this.g : t0; - } - -+ public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER - public void b(PacketDataSerializer packetdataserializer) { - this.a(); - packetdataserializer.writeByte(this.i); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -0,0 +0,0 @@ public class ProtoChunk implements IChunkAccess { - - } - -+ // Paper start - If loaded util -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); -+ } -+ // Paper end -+ - @Override - public IBlockData getType(BlockPosition blockposition) { - int i = blockposition.getY(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/IOWorker.java -@@ -0,0 +0,0 @@ public class IOWorker implements AutoCloseable { - private static final Logger LOGGER = LogManager.getLogger(); - private final AtomicBoolean b = new AtomicBoolean(); - private final ThreadedMailbox c; -- private final RegionFileCache d; -+ private final RegionFileCache d;public RegionFileCache getRegionFileCache() { return d; } // Paper - OBFHELPER - private final Map e = Maps.newLinkedHashMap(); - - protected IOWorker(File file, boolean flag, String s) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java -@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - return this.e.resolve(s); - } - -+ @Nullable public synchronized DataInputStream getReadStream(ChunkCoordIntPair chunkCoordIntPair) throws IOException { return a(chunkCoordIntPair);} // Paper - OBFHELPER - @Nullable - public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) throws IOException { - int i = this.getOffset(chunkcoordintpair); -diff --git a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -+++ b/src/main/java/net/minecraft/world/phys/AxisAlignedBB.java -@@ -0,0 +0,0 @@ public class AxisAlignedBB { - return this.d(vec3d.x, vec3d.y, vec3d.z); - } - -+ public final boolean intersects(AxisAlignedBB axisalignedbb) { return this.c(axisalignedbb); } // Paper - OBFHELPER - public boolean c(AxisAlignedBB axisalignedbb) { - return this.a(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ); - } - -+ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return a(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER - public boolean a(double d0, double d1, double d2, double d3, double d4, double d5) { - return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; - } -@@ -0,0 +0,0 @@ public class AxisAlignedBB { - return d0 >= this.minX && d0 < this.maxX && d1 >= this.minY && d1 < this.maxY && d2 >= this.minZ && d2 < this.maxZ; - } - -+ public final double getAverageSideLength(){return a();} // Paper - OBFHELPER - public double a() { - double d0 = this.b(); - double d1 = this.c(); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -0,0 +0,0 @@ public final class VoxelShapes { - public static final VoxelShape a = create(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); - private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); - -+ public static final VoxelShape empty() {return a();} // Paper - OBFHELPER - public static VoxelShape a() { - return VoxelShapes.c; - } - -+ public static final VoxelShape fullCube() {return b();} // Paper - OBFHELPER - public static VoxelShape b() { - return VoxelShapes.b; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java -@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack { - } - - net.minecraft.world.item.ItemStack handle; -+ public net.minecraft.world.item.ItemStack getHandle() { return handle; } // Paper - - /** - * Mirror -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ import org.bukkit.scheduler.BukkitWorker; - */ - public class CraftScheduler implements BukkitScheduler { - -+ static Plugin MINECRAFT = new MinecraftInternalPlugin(); - /** - * Counter for IDs. Order doesn't matter, only uniqueness. - */ -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - runTaskTimer(plugin, (Object) task, delay, period); - } - -+ public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -+ final CraftTask task = new CraftTask(run, nextId(), taskName); -+ return handle(task, delay); -+ } -+ - public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { - validate(plugin, runnable); - if (delay < 0L) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - task.run(); - task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { -- task.getOwner().getLogger().log( -+ // Paper start -+ String msg = String.format( -+ "Task #%s for %s generated an exception", -+ task.getTaskId(), -+ task.getOwner().getDescription().getFullName()); -+ if (task.getOwner() == MINECRAFT) { -+ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); -+ } else { -+ task.getOwner().getLogger().log( - Level.WARNING, -- String.format( -- "Task #%s for %s generated an exception", -- task.getTaskId(), -- task.getOwner().getDescription().getFullName()), -+ msg, - throwable); -+ } -+ // Paper end - } finally { - currentTask = null; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - CraftTask(final Object task) { - this(null, task, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -+ // Paper start -+ public String taskName = null; -+ boolean internal = false; -+ CraftTask(final Object task, int id, String taskName) { -+ this.rTask = (Runnable) task; -+ this.cTask = null; -+ this.plugin = CraftScheduler.MINECRAFT; -+ this.taskName = taskName; -+ this.internal = true; -+ this.id = id; -+ this.period = CraftTask.NO_REPEATING; -+ this.taskName = taskName; -+ this.timings = null; // Will be changed in later patch -+ } -+ // Paper end - - CraftTask(final Plugin plugin, final Object task, final int id, final long period) { - this.plugin = plugin; -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java -@@ -0,0 +0,0 @@ -+package org.bukkit.craftbukkit.scheduler; -+ -+ -+import org.bukkit.Server; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.configuration.file.FileConfiguration; -+import org.bukkit.generator.ChunkGenerator; -+import org.bukkit.plugin.PluginBase; -+import org.bukkit.plugin.PluginDescriptionFile; -+import org.bukkit.plugin.PluginLoader; -+import org.bukkit.plugin.PluginLogger; -+ -+import java.io.File; -+import java.io.InputStream; -+import java.util.List; -+ -+public class MinecraftInternalPlugin extends PluginBase { -+ private boolean enabled = true; -+ -+ private final String pluginName; -+ private PluginDescriptionFile pdf; -+ -+ public MinecraftInternalPlugin() { -+ this.pluginName = "Minecraft"; -+ pdf = new PluginDescriptionFile(pluginName, "1.0", "nms"); -+ } -+ -+ public void setEnabled(boolean enabled) { -+ this.enabled = enabled; -+ } -+ -+ @Override -+ public File getDataFolder() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginDescriptionFile getDescription() { -+ return pdf; -+ } -+ -+ @Override -+ public FileConfiguration getConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public InputStream getResource(String filename) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveDefaultConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void saveResource(String resourcePath, boolean replace) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void reloadConfig() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLogger getLogger() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public PluginLoader getPluginLoader() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public Server getServer() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isEnabled() { -+ return enabled; -+ } -+ -+ @Override -+ public void onDisable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onLoad() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void onEnable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean isNaggable() { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public void setNaggable(boolean canNag) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+ -+ @Override -+ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { -+ throw new UnsupportedOperationException("Not supported."); -+ } -+} -diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java -@@ -0,0 +0,0 @@ public class DummyGeneratorAccess implements GeneratorAccess { - public Fluid getFluid(BlockPosition blockposition) { - throw new UnsupportedOperationException("Not supported yet."); - } -+ // Paper start - if loaded util -+ @javax.annotation.Nullable -+ @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ -+ @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } - -+ @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ throw new UnsupportedOperationException("Not supported yet."); -+ } -+ // Paper end - @Override - public WorldBorder getWorldBorder() { - throw new UnsupportedOperationException("Not supported yet."); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/UnsafeList.java -@@ -0,0 +0,0 @@ import java.util.RandomAccess; - public class UnsafeList extends AbstractList implements List, RandomAccess, Cloneable, Serializable { - private static final long serialVersionUID = 8683452581112892191L; - -- private transient Object[] data; -+ private transient Object[] data; public final Object[] getRawDataArray() { return this.data; } // Paper - expose for raw get - private int size; - private int initialCapacity; - -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -0,0 +0,0 @@ public class SpigotConfig - } - } - } -- -+ // Paper start -+ SpigotConfig.save(); -+ } -+ public static void save() { -+ // Paper end - try - { - config.save( CONFIG_FILE ); diff --git a/Spigot-Server-Patches/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/Spigot-Server-Patches/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch deleted file mode 100644 index b467c4075e..0000000000 --- a/Spigot-Server-Patches/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 2 Sep 2018 19:34:33 -0700 -Subject: [PATCH] Make CraftWorld#loadChunk(int, int, false) load unconverted - chunks - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); -+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper - - // If generate = false, but the chunk already exists, we will get this back. - if (chunk instanceof ProtoChunkExtension) { diff --git a/Spigot-Server-Patches/Make-EnderDragon-implement-Mob.patch b/Spigot-Server-Patches/Make-EnderDragon-implement-Mob.patch deleted file mode 100644 index e43453584d..0000000000 --- a/Spigot-Server-Patches/Make-EnderDragon-implement-Mob.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 10 Aug 2018 22:11:49 -0400 -Subject: [PATCH] Make EnderDragon implement Mob - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexLivingEntity.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - -+import net.minecraft.world.entity.EntityInsentient; // Paper - import net.minecraft.world.entity.EntityLiving; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.ComplexLivingEntity; - --public abstract class CraftComplexLivingEntity extends CraftLivingEntity implements ComplexLivingEntity { -- public CraftComplexLivingEntity(CraftServer server, EntityLiving entity) { -+public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper -+ public CraftComplexLivingEntity(CraftServer server, EntityInsentient entity) { // Paper - super(server, entity); - } - - @Override -- public EntityLiving getHandle() { -- return (EntityLiving) entity; -+ public EntityInsentient getHandle() { // Paper -+ return (EntityInsentient) entity; // Paper - } - - @Override diff --git a/Spigot-Server-Patches/Make-item-validations-configurable.patch b/Spigot-Server-Patches/Make-item-validations-configurable.patch deleted file mode 100644 index a68bcb43d6..0000000000 --- a/Spigot-Server-Patches/Make-item-validations-configurable.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Fri, 4 Jun 2021 12:12:35 -0700 -Subject: [PATCH] Make item validations configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - enableBrigadierConsoleHighlighting = getBoolean("settings.console.enable-brigadier-highlighting", enableBrigadierConsoleHighlighting); - enableBrigadierConsoleCompletions = getBoolean("settings.console.enable-brigadier-completions", enableBrigadierConsoleCompletions); - } -+ -+ public static int itemValidationDisplayNameLength = 8192; -+ public static int itemValidationLocNameLength = 8192; -+ public static int itemValidationLoreLineLength = 8192; -+ public static int itemValidationBookTitleLength = 8192; -+ public static int itemValidationBookAuthorLength = 8192; -+ public static int itemValidationBookPageLength = 16384; -+ private static void itemValidationSettings() { -+ itemValidationDisplayNameLength = getInt("settings.item-validation.display-name", itemValidationDisplayNameLength); -+ itemValidationLocNameLength = getInt("settings.item-validation.loc-name", itemValidationLocNameLength); -+ itemValidationLoreLineLength = getInt("settings.item-validation.lore-line", itemValidationLoreLineLength); -+ itemValidationBookTitleLength = getInt("settings.item-validation.book.title", itemValidationBookTitleLength); -+ itemValidationBookAuthorLength = getInt("settings.item-validation.book.author", itemValidationBookAuthorLength); -+ itemValidationBookPageLength = getInt("settings.item-validation.book.page", itemValidationBookPageLength); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - super(tag); - - if (tag.hasKey(BOOK_TITLE.NBT)) { -- this.title = limit( tag.getString(BOOK_TITLE.NBT), 8192 ); // Spigot -+ this.title = limit( tag.getString(BOOK_TITLE.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookTitleLength); // Spigot // Paper - make configurable - } - - if (tag.hasKey(BOOK_AUTHOR.NBT)) { -- this.author = limit( tag.getString(BOOK_AUTHOR.NBT), 8192 ); // Spigot -+ this.author = limit( tag.getString(BOOK_AUTHOR.NBT), com.destroystokyo.paper.PaperConfig.itemValidationBookAuthorLength ); // Spigot // Paper - make configurable - } - - if (tag.hasKey(RESOLVED.NBT)) { -@@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { - } else { - page = validatePage(page); - } -- this.pages.add( limit( page, 16384 ) ); // Spigot -+ this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable - } - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - NBTTagCompound display = tag.getCompound(DISPLAY.NBT); - - if (display.hasKey(NAME.NBT)) { -- displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot -+ displayName = limit( display.getString(NAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationDisplayNameLength); // Spigot // Paper - make configurable - } - - if (display.hasKey(LOCNAME.NBT)) { -- locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot -+ locName = limit( display.getString(LOCNAME.NBT), com.destroystokyo.paper.PaperConfig.itemValidationLocNameLength ); // Spigot // Paper - make configurable - } - - if (display.hasKey(LORE.NBT)) { - NBTTagList list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); - lore = new ArrayList(list.size()); - for (int index = 0; index < list.size(); index++) { -- String line = limit( list.getString(index), 8192 ); // Spigot -+ String line = limit( list.getString(index), com.destroystokyo.paper.PaperConfig.itemValidationLoreLineLength ); // Spigot // Paper - make configurable - lore.add(line); - } - } diff --git a/Spigot-Server-Patches/Make-legacy-ping-handler-more-reliable.patch b/Spigot-Server-Patches/Make-legacy-ping-handler-more-reliable.patch deleted file mode 100644 index 9d353cfeda..0000000000 --- a/Spigot-Server-Patches/Make-legacy-ping-handler-more-reliable.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Wed, 11 Oct 2017 18:22:50 +0200 -Subject: [PATCH] Make legacy ping handler more reliable - -The Minecraft server often fails to respond to old ("legacy") pings -from old Minecraft versions using the protocol used before the switch -to Netty in Minecraft 1.7. - -Due to packet fragmentation[1], we might not have all needed bytes -available when the LegacyPingHandler is called. In this case, it will -run into an error, remove the handler and continue using the modern -protocol. - -This is unlikely to happen for the first two revisions of the legacy -ping protocol (used in Minecraft 1.5.x and older) since the request -consists of only one or two bytes, but happens frequently for the -last/third revision introduced in Minecraft 1.6. - -It has much larger, variable packet sizes due to the inclusion of -the virtual host (the hostname/port used to connect to the server). - -The solution[2] is simple: If we find more than two matching bytes, -we buffer the remaining bytes until we have enough to fully read and -respond to the request. - -[1]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-11 -[2]: https://netty.io/wiki/user-guide-for-4.x.html#wiki-h4-13 - -diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -+++ b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ServerConnection b; -+ private ByteBuf buf; // Paper - - public LegacyPingHandler(ServerConnection serverconnection) { - this.b = serverconnection; -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) throws Exception { - ByteBuf bytebuf = (ByteBuf) object; - -+ // Paper start - Make legacy ping handler more reliable -+ if (this.buf != null) { -+ try { -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ } finally { -+ bytebuf.release(); -+ } -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); - boolean flag = true; - -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - this.a(channelhandlercontext, this.a(s)); - break; - default: -+ // Paper start - Replace with improved version below -+ if (bytebuf.readUnsignedByte() != 0x01 || bytebuf.readUnsignedByte() != 0xFA) return; -+ readLegacy1_6(channelhandlercontext, bytebuf); -+ /* - boolean flag1 = bytebuf.readUnsignedByte() == 1; - - flag1 &= bytebuf.readUnsignedByte() == 250; -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - } finally { - bytebuf1.release(); - } -+ */ // Paper end - Replace with improved version below - } - - bytebuf.release(); -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - - } - -+ // Paper start -+ private static String readLegacyString(ByteBuf buf) { -+ int size = buf.readShort() * Character.BYTES; -+ if (!buf.isReadable(size)) { -+ return null; -+ } -+ -+ String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); -+ buf.skipBytes(size); // toString doesn't increase readerIndex automatically -+ return result; -+ } -+ -+ private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { -+ ByteBuf buf = this.buf; -+ -+ if (buf == null) { -+ this.buf = buf = ctx.alloc().buffer(); -+ buf.markReaderIndex(); -+ } else { -+ buf.resetReaderIndex(); -+ } -+ -+ buf.writeBytes(part); -+ -+ if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { -+ return; -+ } -+ -+ String s = readLegacyString(buf); -+ if (s == null) { -+ return; -+ } -+ -+ if (!s.equals("MC|PingHost")) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { -+ return; -+ } -+ -+ MinecraftServer server = this.b.d(); -+ int protocolVersion = buf.readByte(); -+ String host = readLegacyString(buf); -+ if (host == null) { -+ removeHandler(ctx); -+ return; -+ } -+ int port = buf.readInt(); -+ -+ if (buf.isReadable()) { -+ removeHandler(ctx); -+ return; -+ } -+ -+ buf.release(); -+ this.buf = null; -+ -+ LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); -+ -+ String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", -+ Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); -+ this.a(ctx, this.a(response)); -+ } -+ -+ private void removeHandler(ChannelHandlerContext ctx) { -+ ByteBuf buf = this.buf; -+ this.buf = null; -+ -+ buf.resetReaderIndex(); -+ ctx.pipeline().remove(this); -+ ctx.fireChannelRead(buf); -+ } -+ -+ @Override -+ public void handlerRemoved(ChannelHandlerContext ctx) { -+ if (this.buf != null) { -+ this.buf.release(); -+ this.buf = null; -+ } -+ } -+ // Paper end -+ - private void a(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { - channelhandlercontext.pipeline().firstContext().writeAndFlush(bytebuf).addListener(ChannelFutureListener.CLOSE); - } diff --git a/Spigot-Server-Patches/Make-max-squid-spawn-height-configurable.patch b/Spigot-Server-Patches/Make-max-squid-spawn-height-configurable.patch deleted file mode 100644 index cf7e17d1b0..0000000000 --- a/Spigot-Server-Patches/Make-max-squid-spawn-height-configurable.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Thu, 11 Jan 2018 16:47:28 -0600 -Subject: [PATCH] Make max squid spawn height configurable - -I don't know why upstream made only the minimum height configurable but -whatever - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - expMergeMaxValue = getInt("experience-merge-max-value", -1); - log("Experience Merge Max Value: " + expMergeMaxValue); - } -+ -+ public double squidMaxSpawnHeight; -+ private void squidMaxSpawnHeight() { -+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntitySquid.java -@@ -0,0 +0,0 @@ public class EntitySquid extends EntityWaterAnimal { - } - - public static boolean b(EntityTypes entitytypes, GeneratorAccess generatoraccess, EnumMobSpawn enummobspawn, BlockPosition blockposition, Random random) { -- return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < generatoraccess.getSeaLevel(); // Spigot -+ final double maxHeight = generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight > 0 ? generatoraccess.getMinecraftWorld().paperConfig.squidMaxSpawnHeight : generatoraccess.getSeaLevel(); // Paper -+ return blockposition.getY() > generatoraccess.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && blockposition.getY() < maxHeight; // Spigot // Paper - } - - public void a(float f, float f1, float f2) { diff --git a/Spigot-Server-Patches/Make-player-data-saving-configurable.patch b/Spigot-Server-Patches/Make-player-data-saving-configurable.patch deleted file mode 100644 index 1235f17e1c..0000000000 --- a/Spigot-Server-Patches/Make-player-data-saving-configurable.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mark Vainomaa -Date: Mon, 26 Mar 2018 18:30:53 +0300 -Subject: [PATCH] Make player data saving configurable - -Upstream has added a patch which negates the need for this patch, -however, we should still migrate our configuration back upstream, -to prevent unexpected situations - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void authenticationServersDownKickMessage() { - authenticationServersDownKickMessage = Strings.emptyToNull(getString("messages.kick.authentication-servers-down", authenticationServersDownKickMessage)); - } -+ -+ private static void savePlayerData() { -+ Object val = config.get("settings.save-player-data"); -+ if (val instanceof Boolean) { -+ SpigotConfig.disablePlayerDataSaving = !(Boolean) val; -+ SpigotConfig.config.set("players.disable-saving", SpigotConfig.disableAdvancementSaving); -+ SpigotConfig.save(); -+ } -+ } - } diff --git a/Spigot-Server-Patches/Make-schedule-command-per-world.patch b/Spigot-Server-Patches/Make-schedule-command-per-world.patch deleted file mode 100644 index d0a2c72a69..0000000000 --- a/Spigot-Server-Patches/Make-schedule-command-per-world.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:52:44 -0800 -Subject: [PATCH] Make schedule command per-world - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandSchedule.java b/src/main/java/net/minecraft/server/commands/CommandSchedule.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandSchedule.java -+++ b/src/main/java/net/minecraft/server/commands/CommandSchedule.java -@@ -0,0 +0,0 @@ public class CommandSchedule { - return new ChatMessage("commands.schedule.cleared.failure", new Object[]{object}); - }); - private static final SuggestionProvider c = (commandcontext, suggestionsbuilder) -> { -- return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getServer().getSaveData().H().u().a(), suggestionsbuilder); -+ return ICompletionProvider.b((Iterable) ((CommandListenerWrapper) commandcontext.getSource()).getWorld().worldDataServer.H().u().a(), suggestionsbuilder); // Paper - }; - - public static void a(CommandDispatcher commanddispatcher) { -@@ -0,0 +0,0 @@ public class CommandSchedule { - } else { - long j = commandlistenerwrapper.getWorld().getTime() + (long) i; - MinecraftKey minecraftkey = (MinecraftKey) pair.getFirst(); -- CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getServer().getSaveData().H().u(); -+ CustomFunctionCallbackTimerQueue customfunctioncallbacktimerqueue = commandlistenerwrapper.getWorld().worldDataServer.H().u(); // Paper - - ((Either) pair.getSecond()).ifLeft((customfunction) -> { - String s = minecraftkey.toString(); -@@ -0,0 +0,0 @@ public class CommandSchedule { - } - - private static int a(CommandListenerWrapper commandlistenerwrapper, String s) throws CommandSyntaxException { -- int i = commandlistenerwrapper.getServer().getSaveData().H().u().a(s); -+ int i = commandlistenerwrapper.getWorld().worldDataServer.H().u().a(s); // Paper - - if (i == 0) { - throw CommandSchedule.b.create(s); diff --git a/Spigot-Server-Patches/Make-shield-blocking-delay-configurable.patch b/Spigot-Server-Patches/Make-shield-blocking-delay-configurable.patch deleted file mode 100644 index 36a371579e..0000000000 --- a/Spigot-Server-Patches/Make-shield-blocking-delay-configurable.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 16 Jun 2018 01:18:16 -0500 -Subject: [PATCH] Make shield blocking delay configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); - log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); - } -+ -+ public int shieldBlockingDelay = 5; -+ private void shieldBlockingDelay() { -+ shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - if (this.isHandRaised() && !this.activeItem.isEmpty()) { - Item item = this.activeItem.getItem(); - -- return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= 5; -+ return item.d_(this.activeItem) != EnumAnimation.BLOCK ? false : item.e_(this.activeItem) - this.bd >= getShieldBlockingDelay(); // Paper - shieldBlockingDelay - } else { - return false; - } -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - public void broadcastItemBreak(EnumHand enumhand) { - this.broadcastItemBreak(enumhand == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND); - } -+ // Paper start -+ public int shieldBlockingDelay = world.paperConfig.shieldBlockingDelay; -+ -+ public int getShieldBlockingDelay() { -+ return shieldBlockingDelay; -+ } -+ -+ public void setShieldBlockingDelay(int shieldBlockingDelay) { -+ this.shieldBlockingDelay = shieldBlockingDelay; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setArrowsStuck(int arrows) { - getHandle().setArrowCount(arrows); - } -+ -+ @Override -+ public int getShieldBlockingDelay() { -+ return getHandle().getShieldBlockingDelay(); -+ } -+ -+ @Override -+ public void setShieldBlockingDelay(int delay) { -+ getHandle().setShieldBlockingDelay(delay); -+ } - // Paper end - } diff --git a/Spigot-Server-Patches/Make-sure-to-remove-correct-TE-during-TE-tick.patch b/Spigot-Server-Patches/Make-sure-to-remove-correct-TE-during-TE-tick.patch deleted file mode 100644 index 3979a358e9..0000000000 --- a/Spigot-Server-Patches/Make-sure-to-remove-correct-TE-during-TE-tick.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 29 Mar 2021 09:07:25 +0200 -Subject: [PATCH] Make sure to remove correct TE during TE tick - -This looks like it can cause premature TE removal. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - //this.tileEntityList.remove(tileentity); // Paper - remove unused list - // Paper - prevent double chunk lookups - Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -- chunk.removeTileEntity(tileentity.getPosition()); -+ chunk.removeTileEntity(tileentity.getPosition(), tileentity); // Paper - remove correct TE - } - // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - @Override - public void removeTileEntity(BlockPosition blockposition) { -+ // Paper start - remove correct TE -+ removeTileEntity(blockposition, null); -+ } -+ public void removeTileEntity(BlockPosition blockposition, TileEntity match) { -+ // Paper end - if (this.loaded || this.world.s_()) { -- TileEntity tileentity = (TileEntity) this.tileEntities.remove(blockposition); -+ // Paper start -+ TileEntity tileentity = (TileEntity) this.tileEntities.get(blockposition); - -- if (tileentity != null) { -+ if (tileentity != null && (match == null || match == tileentity)) { -+ this.tileEntities.remove(blockposition); -+ // Paper end - tileentity.al_(); - } - } diff --git a/Spigot-Server-Patches/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/Spigot-Server-Patches/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch deleted file mode 100644 index 493461d49b..0000000000 --- a/Spigot-Server-Patches/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 7 Feb 2017 16:55:35 -0600 -Subject: [PATCH] Make targetSize more aggressive in the chunk unload queue - - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final PlayerMap playerMap; - public final Int2ObjectMap trackedEntities; - private final Long2ByteMap z; -- private final Queue A; -+ private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER - private int viewDistance; - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerMap = new PlayerMap(); - this.trackedEntities = new Int2ObjectOpenHashMap(); - this.z = new Long2ByteOpenHashMap(); -- this.A = Queues.newConcurrentLinkedQueue(); -+ this.A = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() - this.definedStructureManager = definedstructuremanager; - this.w = convertable_conversionsession.a(worldserver.getDimensionKey()); - this.world = worldserver; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Spigot start - org.spigotmc.SlackActivityAccountant activityAccountant = this.world.getMinecraftServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); -- int targetSize = (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR); -+ int targetSize = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - // Spigot end - while (longiterator.hasNext()) { // Spigot - long j = longiterator.nextLong(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - Runnable runnable; - -- while ((booleansupplier.getAsBoolean() || this.A.size() > 2000) && (runnable = (Runnable) this.A.poll()) != null) { -+ int queueTarget = Math.min(this.getUnloadQueueTasks().size() - 100, (int) (this.getUnloadQueueTasks().size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well -+ while ((booleansupplier.getAsBoolean() || this.getUnloadQueueTasks().size() > queueTarget) && (runnable = (Runnable)this.getUnloadQueueTasks().poll()) != null) { // Paper - Target this queue as well - runnable.run(); - } - diff --git a/Spigot-Server-Patches/Make-the-GUI-graph-fancier.patch b/Spigot-Server-Patches/Make-the-GUI-graph-fancier.patch deleted file mode 100644 index 2d2187f046..0000000000 --- a/Spigot-Server-Patches/Make-the-GUI-graph-fancier.patch +++ /dev/null @@ -1,436 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 2 Feb 2020 04:00:40 -0600 -Subject: [PATCH] Make the GUI graph fancier - - -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphColor.java b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphColor.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphColor { -+ private static final Color[] colorLine = new Color[101]; -+ private static final Color[] colorFill = new Color[101]; -+ -+ static { -+ for (int i = 0; i < 101; i++) { -+ Color color = createColor(i); -+ colorLine[i] = new Color(color.getRed() / 2, color.getGreen() / 2, color.getBlue() / 2, 255); -+ colorFill[i] = new Color(colorLine[i].getRed(), colorLine[i].getGreen(), colorLine[i].getBlue(), 125); -+ } -+ } -+ -+ public static Color getLineColor(int percent) { -+ return colorLine[percent]; -+ } -+ -+ public static Color getFillColor(int percent) { -+ return colorFill[percent]; -+ } -+ -+ private static Color createColor(int percent) { -+ if (percent <= 50) { -+ return new Color(0X00FF00); -+ } -+ -+ int value = 510 - (int) (Math.min(Math.max(0, ((percent - 50) / 50F)), 1) * 510); -+ -+ int red, green; -+ if (value < 255) { -+ red = 255; -+ green = (int) (Math.sqrt(value) * 16); -+ } else { -+ green = 255; -+ value = value - 255; -+ red = 255 - (value * value / 255); -+ } -+ -+ return new Color(red, green, 0); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GraphData.java b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GraphData.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.gui; -+ -+import java.awt.Color; -+ -+public class GraphData { -+ private long total; -+ private long free; -+ private long max; -+ private long usedMem; -+ private int usedPercent; -+ -+ public GraphData(long total, long free, long max) { -+ this.total = total; -+ this.free = free; -+ this.max = max; -+ this.usedMem = total - free; -+ this.usedPercent = usedMem == 0 ? 0 : (int) (usedMem * 100L / max); -+ } -+ -+ public long getTotal() { -+ return total; -+ } -+ -+ public long getFree() { -+ return free; -+ } -+ -+ public long getMax() { -+ return max; -+ } -+ -+ public long getUsedMem() { -+ return usedMem; -+ } -+ -+ public int getUsedPercent() { -+ return usedPercent; -+ } -+ -+ public Color getFillColor() { -+ return GraphColor.getFillColor(usedPercent); -+ } -+ -+ public Color getLineColor() { -+ return GraphColor.getLineColor(usedPercent); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.JPanel; -+import javax.swing.Timer; -+import java.awt.BorderLayout; -+import java.awt.Dimension; -+ -+public class GuiStatsComponent extends JPanel { -+ private final Timer timer; -+ private final RAMGraph ramGraph; -+ -+ public GuiStatsComponent(MinecraftServer server) { -+ super(new BorderLayout()); -+ -+ setOpaque(false); -+ -+ ramGraph = new RAMGraph(); -+ RAMDetails ramDetails = new RAMDetails(server); -+ -+ add(ramGraph, "North"); -+ add(ramDetails, "Center"); -+ -+ timer = new Timer(500, (event) -> { -+ ramGraph.update(); -+ ramDetails.update(); -+ }); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 200); -+ } -+ -+ public void stop() { a(); } public void a() { -+ timer.stop(); -+ ramGraph.stop(); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.gui; -+ -+import net.minecraft.SystemUtils; -+import net.minecraft.server.MinecraftServer; -+ -+import javax.swing.DefaultListCellRenderer; -+import javax.swing.DefaultListSelectionModel; -+import javax.swing.JList; -+import javax.swing.border.EmptyBorder; -+import java.awt.Dimension; -+import java.text.DecimalFormat; -+import java.text.DecimalFormatSymbols; -+import java.util.Locale; -+import java.util.Vector; -+ -+public class RAMDetails extends JList { -+ public static final DecimalFormat DECIMAL_FORMAT = SystemUtils.peek(new DecimalFormat("########0.000"), (format) -+ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); -+ -+ private final MinecraftServer server; -+ -+ public RAMDetails(MinecraftServer server) { -+ this.server = server; -+ -+ setBorder(new EmptyBorder(0, 10, 0, 0)); -+ setFixedCellHeight(20); -+ setOpaque(false); -+ -+ DefaultListCellRenderer renderer = new DefaultListCellRenderer(); -+ renderer.setOpaque(false); -+ setCellRenderer(renderer); -+ -+ setSelectionModel(new DefaultListSelectionModel() { -+ @Override -+ public void setAnchorSelectionIndex(final int anchorIndex) { -+ } -+ -+ @Override -+ public void setLeadAnchorNotificationEnabled(final boolean flag) { -+ } -+ -+ @Override -+ public void setLeadSelectionIndex(final int leadIndex) { -+ } -+ -+ @Override -+ public void setSelectionInterval(final int index0, final int index1) { -+ } -+ }); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 100); -+ } -+ -+ public void update() { -+ GraphData data = RAMGraph.DATA.peekLast(); -+ Vector vector = new Vector<>(); -+ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)"); -+ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb"); -+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms"); -+ setListData(vector); -+ } -+ -+ public double getAverage(long[] tickTimes) { -+ long total = 0L; -+ for (long value : tickTimes) { -+ total += value; -+ } -+ return ((double) total / (double) tickTimes.length) * 1.0E-6D; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/gui/RAMGraph.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.gui; -+ -+import javax.swing.JComponent; -+import javax.swing.SwingUtilities; -+import javax.swing.Timer; -+import javax.swing.ToolTipManager; -+import java.awt.Color; -+import java.awt.Dimension; -+import java.awt.Graphics; -+import java.awt.MouseInfo; -+import java.awt.Point; -+import java.awt.PointerInfo; -+import java.awt.event.MouseAdapter; -+import java.awt.event.MouseEvent; -+import java.text.SimpleDateFormat; -+import java.util.Date; -+import java.util.LinkedList; -+import java.util.concurrent.TimeUnit; -+ -+public class RAMGraph extends JComponent { -+ public static final LinkedList DATA = new LinkedList() { -+ @Override -+ public boolean add(GraphData data) { -+ if (size() >= 348) { -+ remove(); -+ } -+ return super.add(data); -+ } -+ }; -+ -+ static { -+ GraphData empty = new GraphData(0, 0, 0); -+ for (int i = 0; i < 350; i++) { -+ DATA.add(empty); -+ } -+ } -+ -+ private final Timer timer; -+ private final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); -+ -+ private int currentTick; -+ -+ public RAMGraph() { -+ ToolTipManager.sharedInstance().setInitialDelay(0); -+ -+ addMouseListener(new MouseAdapter() { -+ final int defaultDismissTimeout = ToolTipManager.sharedInstance().getDismissDelay(); -+ final int dismissDelayMinutes = (int) TimeUnit.MINUTES.toMillis(10); -+ -+ @Override -+ public void mouseEntered(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(dismissDelayMinutes); -+ } -+ -+ @Override -+ public void mouseExited(MouseEvent me) { -+ ToolTipManager.sharedInstance().setDismissDelay(defaultDismissTimeout); -+ } -+ }); -+ -+ timer = new Timer(50, (event) -> repaint()); -+ timer.start(); -+ } -+ -+ @Override -+ public Dimension getPreferredSize() { -+ return new Dimension(350, 110); -+ } -+ -+ public void update() { -+ Runtime jvm = Runtime.getRuntime(); -+ DATA.add(new GraphData(jvm.totalMemory(), jvm.freeMemory(), jvm.maxMemory())); -+ -+ PointerInfo pointerInfo = MouseInfo.getPointerInfo(); -+ if (pointerInfo != null) { -+ Point point = pointerInfo.getLocation(); -+ if (point != null) { -+ Point loc = new Point(point); -+ SwingUtilities.convertPointFromScreen(loc, this); -+ if (this.contains(loc)) { -+ ToolTipManager.sharedInstance().mouseMoved( -+ new MouseEvent(this, -1, System.currentTimeMillis(), 0, loc.x, loc.y, -+ point.x, point.y, 0, false, 0)); -+ } -+ } -+ } -+ -+ currentTick++; -+ } -+ -+ @Override -+ public void paint(Graphics graphics) { -+ graphics.setColor(new Color(0xFFFFFFFF)); -+ graphics.fillRect(0, 0, 350, 100); -+ -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(1, 25, 348, 25); -+ graphics.drawLine(1, 50, 348, 50); -+ graphics.drawLine(1, 75, 348, 75); -+ -+ int i = 0; -+ for (GraphData data : DATA) { -+ i++; -+ if ((i + currentTick) % 120 == 0) { -+ graphics.setColor(new Color(0x888888)); -+ graphics.drawLine(i, 1, i, 99); -+ } -+ int used = data.getUsedPercent(); -+ if (used > 0) { -+ Color color = data.getLineColor(); -+ graphics.setColor(data.getFillColor()); -+ graphics.fillRect(i, 100 - used, 1, used); -+ graphics.setColor(color); -+ graphics.fillRect(i, 100 - used, 1, 1); -+ } -+ } -+ -+ graphics.setColor(new Color(0xFF000000)); -+ graphics.drawRect(0, 0, 348, 100); -+ -+ Point m = getMousePosition(); -+ if (m != null && m.x > 0 && m.x < 348 && m.y > 0 && m.y < 100) { -+ GraphData data = DATA.get(m.x); -+ int used = data.getUsedPercent(); -+ graphics.setColor(new Color(0x000000)); -+ graphics.drawLine(m.x, 1, m.x, 99); -+ graphics.drawOval(m.x - 2, 100 - used - 2, 5, 5); -+ graphics.setColor(data.getLineColor()); -+ graphics.fillOval(m.x - 2, 100 - used - 2, 5, 5); -+ setToolTipText(String.format("Used: %s mb (%s%%)
    %s", -+ Math.round(data.getUsedMem() / 1024F / 1024F), -+ used, getTime(m.x))); -+ } -+ } -+ -+ public String getTime(int halfSeconds) { -+ int millis = (348 - halfSeconds) / 2 * 1000; -+ return TIME_FORMAT.format(new Date((System.currentTimeMillis() - millis))); -+ } -+ -+ public void stop() { -+ timer.stop(); -+ } -+} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -0,0 +0,0 @@ public class SystemUtils { - return supplier.get(); - } - -+ public static T peek(T t0, Consumer consumer) { return a(t0, consumer); } // Paper - OBFHELPER - public static T a(T t0, Consumer consumer) { - consumer.accept(t0); - return t0; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ private static final DecimalFormat a = (DecimalFormat) SystemUtils.a(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error - decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)); - }); - private final int[] b = new int[256]; -diff --git a/src/main/java/net/minecraft/server/gui/ServerGUI.java b/src/main/java/net/minecraft/server/gui/ServerGUI.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/gui/ServerGUI.java -+++ b/src/main/java/net/minecraft/server/gui/ServerGUI.java -@@ -0,0 +0,0 @@ public class ServerGUI extends JComponent { - - private JComponent c() { - JPanel jpanel = new JPanel(new BorderLayout()); -- GuiStatsComponent guistatscomponent = new GuiStatsComponent(this.c); -+ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.c); // Paper - - this.e.add(guistatscomponent::a); - jpanel.add(guistatscomponent, "North"); diff --git a/Spigot-Server-Patches/Make-the-default-permission-message-configurable.patch b/Spigot-Server-Patches/Make-the-default-permission-message-configurable.patch deleted file mode 100644 index cafa7f443d..0000000000 --- a/Spigot-Server-Patches/Make-the-default-permission-message-configurable.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 18 Nov 2018 19:49:56 +0000 -Subject: [PATCH] Make the default permission message configurable - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ import java.util.regex.Pattern; - import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; -@@ -0,0 +0,0 @@ public class PaperConfig { - connectionThrottleKickMessage = getString("messages.kick.connection-throttle", connectionThrottleKickMessage); - } - -+ public static String noPermissionMessage = "&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error."; -+ private static void noPermissionMessage() { -+ noPermissionMessage = ChatColor.translateAlternateColorCodes('&', getString("messages.no-permission", noPermissionMessage)); -+ } -+ - private static void savePlayerData() { - Object val = config.get("settings.save-player-data"); - if (val instanceof Boolean) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return com.destroystokyo.paper.PaperConfig.suggestPlayersWhenNullTabCompletions; - } - -+ @Override -+ public String getPermissionMessage() { -+ return com.destroystokyo.paper.PaperConfig.noPermissionMessage; -+ } -+ - @Override - public com.destroystokyo.paper.profile.PlayerProfile createProfile(@Nonnull UUID uuid) { - return createProfile(uuid, null); diff --git a/Spigot-Server-Patches/Maps-shouldn-t-load-chunks.patch b/Spigot-Server-Patches/Maps-shouldn-t-load-chunks.patch deleted file mode 100644 index 59332304af..0000000000 --- a/Spigot-Server-Patches/Maps-shouldn-t-load-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sun, 7 Jun 2020 21:43:42 +0100 -Subject: [PATCH] Maps shouldn't load chunks - -Previously maps would load all chunks in a certain radius depending on - their scale when trying to update their content. This would result in - main thread chunk loads when they weren't really necessary, especially - on low view distances or "slow" async chunk loads after teleports or - other prioritisation. - - This changes it to only try to render already loaded chunks based on - the assumption that the chunks around the player will get loaded - eventually anyways and that maps will get checked for update every - five ticks that movement occur in anyways. - -diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java -+++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -@@ -0,0 +0,0 @@ public class ItemWorldMap extends ItemWorldMapBase { - int k2 = (j / i + k1 - 64) * i; - int l2 = (k / i + l1 - 64) * i; - Multiset multiset = LinkedHashMultiset.create(); -- Chunk chunk = world.getChunkAtWorldCoords(new BlockPosition(k2, 0, l2)); -+ Chunk chunk = world.getChunkIfLoaded(new BlockPosition(k2, 0, l2)); // Paper - Maps shouldn't load chunks - -- if (!chunk.isEmpty()) { -+ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - int i3 = k2 & 15; - int j3 = l2 & 15; diff --git a/Spigot-Server-Patches/Mark-chunk-dirty-anytime-entities-change-to-guarante.patch b/Spigot-Server-Patches/Mark-chunk-dirty-anytime-entities-change-to-guarante.patch deleted file mode 100644 index 033ea7cc05..0000000000 --- a/Spigot-Server-Patches/Mark-chunk-dirty-anytime-entities-change-to-guarante.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 23 Jul 2018 22:18:31 -0400 -Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it - saves - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - entity.chunkZ = this.loc.z; - this.entities.add(entity); // Paper - per chunk entity list - this.entitySlices[k].add(entity); -+ this.markDirty(); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - return; - } - entityCounts.decrement(entity.getMinecraftKeyString()); -+ this.markDirty(); // Paper - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Spigot-Server-Patches/Mark-entities-as-being-ticked-when-notifying-navigat.patch b/Spigot-Server-Patches/Mark-entities-as-being-ticked-when-notifying-navigat.patch deleted file mode 100644 index 5405baede5..0000000000 --- a/Spigot-Server-Patches/Mark-entities-as-being-ticked-when-notifying-navigat.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 28 Jul 2019 00:51:11 +0100 -Subject: [PATCH] Mark entities as being ticked when notifying navigation - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); - - if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) { -+ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper - Iterator iterator = this.navigators.iterator(); - - while (iterator.hasNext()) { -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -+ this.tickingEntities = wasTicking; // Paper - } - } - diff --git a/Spigot-Server-Patches/Merchant-getRecipes-should-return-an-immutable-list.patch b/Spigot-Server-Patches/Merchant-getRecipes-should-return-an-immutable-list.patch deleted file mode 100644 index 82b49fd28e..0000000000 --- a/Spigot-Server-Patches/Merchant-getRecipes-should-return-an-immutable-list.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Wed, 10 Feb 2021 14:53:36 -0800 -Subject: [PATCH] Merchant#getRecipes should return an immutable list - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchant.java -@@ -0,0 +0,0 @@ public class CraftMerchant implements Merchant { - - @Override - public List getRecipes() { -- return Collections.unmodifiableList(Lists.transform(merchant.getOffers(), new Function() { -+ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(merchant.getOffers(), new Function() { // Paper - javadoc says 'an immutable list of trades' - not 'an unmodifiable view of a list of trades'. fixes issue with setRecipes(getRecipes()) - @Override - public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantRecipe recipe) { - return recipe.asBukkit(); diff --git a/Spigot-Server-Patches/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/Spigot-Server-Patches/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch deleted file mode 100644 index 05158f57e5..0000000000 --- a/Spigot-Server-Patches/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ /dev/null @@ -1,271 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 9 Apr 2020 00:09:26 -0400 -Subject: [PATCH] Mid Tick Chunk Tasks - Speed up processing of chunk loads and - generation - -Credit to Spotted for the idea - -A lot of the new chunk system requires constant back and forth the main thread -to handle priority scheduling and ensuring conflicting tasks do not run at the -same time. - -The issue is, these queues are only checked at either: - -A) Sync Chunk Loads -B) End of Tick while sleeping - -This results in generating chunks sitting waiting for a full tick to -complete before it will even start the next unit of work to do. - -Additionally, this also delays loading of chunks until this same timing. - -We will now periodically poll the chunk task queues throughout the tick, -looking for work to do. -We do this in a fair method that considers all worlds, not just the one being -ticked, so that each world can get 1 task procesed each before the next pass. - -In a view distance of 15, chunk loading performance was visually faster on the client. - -Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated) - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/MinecraftTimings.java -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +0,0 @@ import java.util.Map; - public final class MinecraftTimings { - - public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); - public static final Timing playerListTimer = Timings.ofSafe("Player List"); - public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); - public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - log("Async Chunks: Enabled - Chunks will be loaded much faster, without lag."); - } - } -+ -+ public static int midTickChunkTasks = 1000; -+ private static void midTickChunkTasks() { -+ midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick - return !this.canOversleep(); - }); - isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper - safe iterator incase chunk loads, also no wrapping -+ final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.world.a(chunk, k); - //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper -+ if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper - } - } - } -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - super.executeTask(runnable); - } - -+ // Paper start -+ private long lastMidTickChunkTask = 0; -+ public boolean pollChunkLoadTasks() { -+ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask()) { -+ try { -+ ChunkProviderServer.this.tickDistanceManager(); -+ } finally { -+ // from below: process pending Chunk loadCallback() and unloadCallback() after each run task -+ playerChunkMap.callbackExecutor.run(); -+ } -+ return true; -+ } -+ return false; -+ } -+ public void midTickLoadChunks() { -+ MinecraftServer server = ChunkProviderServer.this.world.getMinecraftServer(); -+ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count -+ //noinspection StatementWithEmptyBody -+ while (pollChunkLoadTasks()) {} -+ -+ if (System.nanoTime() - lastMidTickChunkTask < 200000) { -+ return; -+ } -+ -+ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.canSleepForTick();) { -+ if (this.executeNext()) { -+ server.midTickChunksTasksRan++; -+ lastMidTickChunkTask = System.nanoTime(); -+ } else { -+ break; -+ } -+ } -+ } -+ // Paper end -+ - @Override - protected boolean executeNext() { - // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - timings.scheduledBlocks.stopTiming(); // Paper - -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - gameprofilerfiller.exitEnter("raid"); - this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.doSounds.startTiming(); // Spigot - this.ak(); - timings.doSounds.stopTiming(); // Spigot -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - this.ticking = false; - gameprofilerfiller.exitEnter("entities"); - boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - timings.entityTick.stopTiming(); // Spigot - - this.tickingEntities = false; -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - - Entity entity2; - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - timings.tickEntities.stopTiming(); // Spigot -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - this.tickBlockEntities(); - } - diff --git a/Spigot-Server-Patches/Mob-Pathfinding-API.patch b/Spigot-Server-Patches/Mob-Pathfinding-API.patch deleted file mode 100644 index 12027d60a5..0000000000 --- a/Spigot-Server-Patches/Mob-Pathfinding-API.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 9 Sep 2018 13:30:00 -0400 -Subject: [PATCH] Mob Pathfinding API - -Implements Pathfinding API for mobs - -diff --git a/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/PaperPathfinder.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity; -+ -+import net.minecraft.world.entity.EntityInsentient; -+import net.minecraft.world.level.pathfinder.PathEntity; -+import net.minecraft.world.level.pathfinder.PathPoint; -+import org.apache.commons.lang.Validate; -+import org.bukkit.Location; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Mob; -+ -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; -+import java.util.ArrayList; -+import java.util.List; -+ -+public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { -+ -+ private final EntityInsentient entity; -+ -+ public PaperPathfinder(EntityInsentient entity) { -+ this.entity = entity; -+ } -+ -+ @Override -+ public Mob getEntity() { -+ return entity.getBukkitMob(); -+ } -+ -+ @Override -+ public void stopPathfinding() { -+ entity.getNavigation().stopPathfinding(); -+ } -+ -+ @Override -+ public boolean hasPath() { -+ return entity.getNavigation().getPathEntity() != null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult getCurrentPath() { -+ PathEntity path = entity.getNavigation().getPathEntity(); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(Location loc) { -+ Validate.notNull(loc, "Location can not be null"); -+ PathEntity path = entity.getNavigation().calculateDestination(loc.getX(), loc.getY(), loc.getZ()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Nullable -+ @Override -+ public PathResult findPath(LivingEntity target) { -+ Validate.notNull(target, "Target can not be null"); -+ PathEntity path = entity.getNavigation().calculateDestination(((CraftLivingEntity) target).getHandle()); -+ return path != null ? new PaperPathResult(path) : null; -+ } -+ -+ @Override -+ public boolean moveTo(@Nonnull PathResult path, double speed) { -+ Validate.notNull(path, "PathResult can not be null"); -+ PathEntity pathEntity = ((PaperPathResult) path).path; -+ return entity.getNavigation().setDestination(pathEntity, speed); -+ } -+ -+ @Override -+ public boolean canOpenDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldOpenDoors(); -+ } -+ -+ @Override -+ public void setCanOpenDoors(boolean canOpenDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldOpenDoors(canOpenDoors); -+ } -+ -+ @Override -+ public boolean canPassDoors() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldPassDoors(); -+ } -+ -+ @Override -+ public void setCanPassDoors(boolean canPassDoors) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldPassDoors(canPassDoors); -+ } -+ -+ @Override -+ public boolean canFloat() { -+ return entity.getNavigation().getPathfinder().getPathfinder().shouldFloat(); -+ } -+ -+ @Override -+ public void setCanFloat(boolean canFloat) { -+ entity.getNavigation().getPathfinder().getPathfinder().setShouldFloat(canFloat); -+ } -+ -+ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { -+ -+ private final PathEntity path; -+ PaperPathResult(PathEntity path) { -+ this.path = path; -+ } -+ -+ @Nullable -+ @Override -+ public Location getFinalPoint() { -+ PathPoint point = path.getFinalPoint(); -+ return point != null ? toLoc(point) : null; -+ } -+ -+ @Override -+ public List getPoints() { -+ List points = new ArrayList<>(); -+ for (PathPoint point : path.getPoints()) { -+ points.add(toLoc(point)); -+ } -+ return points; -+ } -+ -+ @Override -+ public int getNextPointIndex() { -+ return path.getNextIndex(); -+ } -+ -+ @Nullable -+ @Override -+ public Location getNextPoint() { -+ if (!path.hasNext()) { -+ return null; -+ } -+ return toLoc(path.getPoints().get(path.getNextIndex())); -+ } -+ } -+ -+ private Location toLoc(PathPoint point) { -+ return new Location(entity.world.getWorld(), point.getX(), point.getY(), point.getZ()); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - } - - @Nullable -- public final PathEntity a(double d0, double d1, double d2, int i) { -+ public final PathEntity calculateDestination(double d0, double d1, double d2) { return a(d0, d1, d2, 0); } public final PathEntity a(double d0, double d1, double d2, int i) { // Paper - OBFHELPER - return this.a(new BlockPosition(d0, d1, d2), i); - } - -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - } - - @Nullable -- public PathEntity a(Entity entity, int i) { -+ public final PathEntity calculateDestination(Entity entity) { return a(entity, 0); } public PathEntity a(Entity entity, int i) { - return this.a(ImmutableSet.of(entity.getChunkCoordinates()), entity, 16, true, i); // Paper - } - -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - return pathentity != null && this.a(pathentity, d0); - } - -+ public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER - public boolean a(@Nullable PathEntity pathentity, double d0) { - if (pathentity == null) { - this.c = null; -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - } - } - -- @Nullable -+ @Nullable public PathEntity getPathEntity() { return k(); } @Nullable // Paper - OBFHELPER - public PathEntity k() { - return this.c; - } -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - return !this.m(); - } - -+ public void stopPathfinding() { o(); } // Paper - OBFHELPER - public void o() { - this.c = null; - } -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.Vec3D; - - public class PathEntity { - -- private final List a; -+ private final List a; public List getPoints() { return a; } // Paper - OBFHELPER - private PathPoint[] b = new PathPoint[0]; - private PathPoint[] c = new PathPoint[0]; -- private int e; -+ private int e; public int getNextIndex() { return this.e; } // Paper - OBFHELPER - private final BlockPosition f; - private final float g; - private final boolean h; -+ public boolean hasNext() { return getNextIndex() < getPoints().size(); } // Paper - - public PathEntity(List list, BlockPosition blockposition, boolean flag) { - this.a = list; -@@ -0,0 +0,0 @@ public class PathEntity { - } - - @Nullable -- public PathPoint d() { -+ public PathPoint getFinalPoint() { return d(); } @Nullable public PathPoint d() { // Paper - OBFHELPER - return !this.a.isEmpty() ? (PathPoint) this.a.get(this.a.size() - 1) : null; - } - -@@ -0,0 +0,0 @@ public class PathEntity { - return this.a(entity, this.e); - } - -- public BlockPosition g() { -+ public BlockPosition getNext() { return g(); } public BlockPosition g() { // Paper - OBFHELPER - return ((PathPoint) this.a.get(this.e)).a(); - } - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathPoint.java -@@ -0,0 +0,0 @@ import net.minecraft.util.MathHelper; - - public class PathPoint { - -- public final int a; -- public final int b; -- public final int c; -+ public final int a; public final int getX() { return a; } // Paper - OBFHELPER -+ public final int b; public final int getY() { return b; } // Paper - OBFHELPER -+ public final int c; public final int getZ() { return c; } // Paper - OBFHELPER - private final int m; - public int d = -1; - public float e; -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderAbstract.java -@@ -0,0 +0,0 @@ public abstract class PathfinderAbstract { - protected int d; - protected int e; - protected int f; -- protected boolean g; -- protected boolean h; -- protected boolean i; -+ protected boolean g; public boolean shouldPassDoors() { return g; } public void setShouldPassDoors(boolean b) { g = b; } // Paper - obfhelper -+ protected boolean h; public boolean shouldOpenDoors() { return h; } public void setShouldOpenDoors(boolean b) { h = b; } // Paper - obfhelper -+ protected boolean i; public boolean shouldFloat() { return i; } public void setShouldFloat(boolean b) { i = b; } // Paper - obfhelper - - public PathfinderAbstract() {} - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -0,0 +0,0 @@ import org.bukkit.loot.LootTable; - public abstract class CraftMob extends CraftLivingEntity implements Mob { - public CraftMob(CraftServer server, EntityInsentient entity) { - super(server, entity); -+ paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper - } - -+ private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper -+ @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper - @Override - public void setTarget(LivingEntity target) { - EntityInsentient entity = getHandle(); diff --git a/Spigot-Server-Patches/Mob-Spawner-API-Enhancements.patch b/Spigot-Server-Patches/Mob-Spawner-API-Enhancements.patch deleted file mode 100644 index 67ae99f328..0000000000 --- a/Spigot-Server-Patches/Mob-Spawner-API-Enhancements.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Fri, 19 Apr 2019 12:41:13 -0500 -Subject: [PATCH] Mob Spawner API Enhancements - - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - this.mobs.clear(); // CraftBukkit - SPIGOT-3496, MC-92282 - } - -+ public boolean isActivated() { return h(); } // Paper - OBFHELPER - private boolean h() { - BlockPosition blockposition = this.b(); - -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - } - } - -+ public void resetTimer() { i(); } // Paper - OBFHELPER - private void i() { - if (this.maxSpawnDelay <= this.minSpawnDelay) { - this.spawnDelay = this.minSpawnDelay; -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - } - - public void a(NBTTagCompound nbttagcompound) { -+ // Paper start - use larger int if set -+ if (nbttagcompound.hasKey("Paper.Delay")) { -+ this.spawnDelay = nbttagcompound.getInt("Paper.Delay"); -+ } else { - this.spawnDelay = nbttagcompound.getShort("Delay"); -+ } -+ // Paper end - this.mobs.clear(); - if (nbttagcompound.hasKeyOfType("SpawnPotentials", 9)) { - NBTTagList nbttaglist = nbttagcompound.getList("SpawnPotentials", 10); -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - } else if (!this.mobs.isEmpty()) { - this.setSpawnData((MobSpawnerData) WeightedRandom.a(this.a().random, this.mobs)); - } -- -+ // Paper start - use ints if set -+ if (nbttagcompound.hasKeyOfType("Paper.MinSpawnDelay", 99)) { -+ this.minSpawnDelay = nbttagcompound.getInt("Paper.MinSpawnDelay"); -+ this.maxSpawnDelay = nbttagcompound.getInt("Paper.MaxSpawnDelay"); -+ this.spawnCount = nbttagcompound.getShort("SpawnCount"); -+ } else // Paper end - if (nbttagcompound.hasKeyOfType("MinSpawnDelay", 99)) { -- this.minSpawnDelay = nbttagcompound.getShort("MinSpawnDelay"); -- this.maxSpawnDelay = nbttagcompound.getShort("MaxSpawnDelay"); -+ this.minSpawnDelay = nbttagcompound.getInt("MinSpawnDelay"); -+ this.maxSpawnDelay = nbttagcompound.getInt("MaxSpawnDelay"); - this.spawnCount = nbttagcompound.getShort("SpawnCount"); - } - -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - if (minecraftkey == null) { - return nbttagcompound; - } else { -- nbttagcompound.setShort("Delay", (short) this.spawnDelay); -- nbttagcompound.setShort("MinSpawnDelay", (short) this.minSpawnDelay); -- nbttagcompound.setShort("MaxSpawnDelay", (short) this.maxSpawnDelay); -+ // Paper start -+ if (spawnDelay > Short.MAX_VALUE) { -+ nbttagcompound.setInt("Paper.Delay", this.spawnDelay); -+ } -+ nbttagcompound.setShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); -+ -+ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { -+ nbttagcompound.setInt("Paper.MinSpawnDelay", this.minSpawnDelay); -+ nbttagcompound.setInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); -+ } -+ -+ nbttagcompound.setShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); -+ nbttagcompound.setShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); -+ // Paper end - nbttagcompound.setShort("SpawnCount", (short) this.spawnCount); - nbttagcompound.setShort("MaxNearbyEntities", (short) this.maxNearbyEntities); - nbttagcompound.setShort("RequiredPlayerRange", (short) this.requiredPlayerRange); -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.block; - - import com.google.common.base.Preconditions; -+import net.minecraft.core.IRegistry; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.MobSpawnerData; - import net.minecraft.world.level.block.entity.TileEntityMobSpawner; - import org.bukkit.Material; - import org.bukkit.block.Block; - import org.bukkit.block.CreatureSpawner; - import org.bukkit.entity.EntityType; -+// Paper start -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.inventory.ItemStack; -+// Paper end - - public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { - -@@ -0,0 +0,0 @@ public class CraftCreatureSpawner extends CraftBlockEntityState -Date: Thu, 6 May 2021 19:57:58 -0700 -Subject: [PATCH] More Enchantment API - - -diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -+++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java -@@ -0,0 +0,0 @@ import net.minecraft.world.item.ItemStack; - - public abstract class Enchantment { - -- private final EnumItemSlot[] a; -+ private final EnumItemSlot[] a; public final EnumItemSlot[] getSlots() { return this.a; } // Paper - OBFHELPER - private final Enchantment.Rarity d; - public final EnchantmentSlotType itemTarget; - @Nullable -@@ -0,0 +0,0 @@ public abstract class Enchantment { - return map; - } - -+ public Enchantment.Rarity getRarity() { return d(); } // Paper - OBFHELPER - public Enchantment.Rarity d() { - return this.d; - } -@@ -0,0 +0,0 @@ public abstract class Enchantment { - return 0; - } - -+ public float getDamageIncrease(int level, EnumMonsterType enumMonsterType) { return a(level, enumMonsterType); } // Paper - OBFHELPER - public float a(int i, EnumMonsterType enummonstertype) { - return 0.0F; - } -@@ -0,0 +0,0 @@ public abstract class Enchantment { - return false; - } - -+ public boolean isCursed() { return c(); } // Paper - OBFHELPER - public boolean c() { - return false; - } - -+ public boolean isTradeable() { return h(); } // Paper - OBFHELPER - public boolean h() { - return true; - } - -+ public boolean isDiscoverable() { return i(); } // Paper - OBFHELPER - public boolean i() { - return true; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -0,0 +0,0 @@ public class CraftEnchantment extends Enchantment { - - @Override - public boolean isCursed() { -- return target instanceof EnchantmentBinding || target instanceof EnchantmentVanishing; -+ return target.isCursed(); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class CraftEnchantment extends Enchantment { - public net.kyori.adventure.text.Component displayName(int level) { - return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); - } -+ -+ @Override -+ public boolean isTradeable() { -+ return target.isTradeable(); -+ } -+ -+ @Override -+ public boolean isDiscoverable() { -+ return target.isDiscoverable(); -+ } -+ -+ @Override -+ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { -+ return fromNMSRarity(target.getRarity()); -+ } -+ -+ @Override -+ public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { -+ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); -+ } -+ -+ @Override -+ public java.util.Set getActiveSlots() { -+ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); -+ } -+ -+ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { -+ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; -+ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { -+ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; -+ } -+ -+ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); -+ } - // Paper end - - public net.minecraft.world.item.enchantment.Enchantment getHandle() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - public void setHurtDirection(float hurtDirection) { - getHandle().setHurtDirection(hurtDirection); - } -+ -+ public static EnumMonsterType fromBukkitEntityCategory(EntityCategory entityCategory) { -+ switch (entityCategory) { -+ case NONE: -+ return EnumMonsterType.UNDEFINED; -+ case UNDEAD: -+ return EnumMonsterType.UNDEAD; -+ case ARTHROPOD: -+ return EnumMonsterType.ARTHROPOD; -+ case ILLAGER: -+ return EnumMonsterType.ILLAGER; -+ case WATER: -+ return EnumMonsterType.WATER_MOB; -+ } -+ throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); -+ } - // Paper end - } -diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.enchantments; -+ -+import net.minecraft.world.item.enchantment.Enchantment.Rarity; -+import org.bukkit.craftbukkit.enchantments.CraftEnchantment; -+import org.junit.Test; -+ -+import static org.junit.Assert.assertNotNull; -+ -+public class EnchantmentRarityTest { -+ -+ @Test -+ public void test() { -+ for (Rarity nmsRarity : Rarity.values()) { -+ // Will throw exception if a bukkit counterpart is not found -+ CraftEnchantment.fromNMSRarity(nmsRarity); -+ } -+ } -+} -diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.entity; -+ -+import com.google.common.base.Joiner; -+import com.google.common.collect.Maps; -+import com.google.common.collect.Sets; -+import net.minecraft.world.entity.EnumMonsterType; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.EntityCategory; -+import org.junit.Test; -+ -+import java.lang.reflect.Field; -+import java.util.Map; -+import java.util.Set; -+ -+import static org.junit.Assert.assertTrue; -+ -+public class EntityCategoryTest { -+ -+ @Test -+ public void test() throws IllegalAccessException { -+ -+ Map enumMonsterTypeFieldMap = Maps.newHashMap(); -+ for (Field field : EnumMonsterType.class.getDeclaredFields()) { -+ if (field.getType() == EnumMonsterType.class) { -+ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); -+ } -+ } -+ -+ for (EntityCategory entityCategory : EntityCategory.values()) { -+ enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); -+ } -+ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); -+ } -+} diff --git a/Spigot-Server-Patches/More-Lidded-Block-API.patch b/Spigot-Server-Patches/More-Lidded-Block-API.patch deleted file mode 100644 index 19fee18204..0000000000 --- a/Spigot-Server-Patches/More-Lidded-Block-API.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: LemonCaramel -Date: Sun, 23 May 2021 17:49:51 +0900 -Subject: [PATCH] More Lidded Block API - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickab - - public float a; - public float b; -- public int c; -+ public int c; public int getViewerCount() { return c; } // Paper - OBFHELPER - private int g; -+ public boolean opened; // Paper - More Lidded Block API - - public TileEntityEnderChest() { - super(TileEntityTypes.ENDER_CHEST); -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickab - - public void d() { - ++this.c; -+ if (opened) return; // Paper - More Lidded Block API - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); - doOpenLogic(); // Paper - } - - public void f() { - --this.c; -+ if (opened) return; // Paper - More Lidded Block API - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); - doCloseLogic(); // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java -@@ -0,0 +0,0 @@ public class CraftBarrel extends CraftLootable implements Barr - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java -@@ -0,0 +0,0 @@ public class CraftChest extends CraftLootable implements Chest, - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java -@@ -0,0 +0,0 @@ public class CraftEnderChest extends CraftBlockEntityState - public CraftEnderChest(final Material material, final TileEntityEnderChest te) { - super(material, te); - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public void open() { -+ requirePlaced(); -+ if (!getTileEntity().opened) { -+ net.minecraft.world.level.World world = getTileEntity().getWorld(); -+ world.playBlockAction(getTileEntity().getPosition(), getTileEntity().getBlock().getBlock(), 1, getTileEntity().getViewerCount() + 1); -+ world.playSound(null, getPosition(), net.minecraft.sounds.SoundEffects.BLOCK_ENDER_CHEST_OPEN, net.minecraft.sounds.SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ } -+ getTileEntity().opened = true; -+ } -+ -+ @Override -+ public void close() { -+ requirePlaced(); -+ if (getTileEntity().opened) { -+ net.minecraft.world.level.World world = getTileEntity().getWorld(); -+ world.playBlockAction(getTileEntity().getPosition(), getTileEntity().getBlock().getBlock(), 1, 0); -+ world.playSound(null, getPosition(), net.minecraft.sounds.SoundEffects.BLOCK_ENDER_CHEST_CLOSE, net.minecraft.sounds.SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ } -+ getTileEntity().opened = false; -+ } -+ -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java -@@ -0,0 +0,0 @@ public class CraftShulkerBox extends CraftLootable impleme - if (getTileEntity().opened) { - World world = getTileEntity().getWorld(); - world.playBlockAction(getPosition(), getTileEntity().getBlock().getBlock(), 1, 0); -- world.playSound(null, getPosition(), SoundEffects.BLOCK_SHULKER_BOX_OPEN, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); -+ world.playSound(null, getPosition(), SoundEffects.BLOCK_SHULKER_BOX_CLOSE, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); // Paper - More Lidded Block API (Wrong sound) - } - getTileEntity().opened = false; - } -+ -+ // Paper start - More Lidded Block API -+ @Override -+ public boolean isOpen() { -+ return getTileEntity().opened; -+ } -+ // Paper end - More Lidded Block API - } diff --git a/Spigot-Server-Patches/More-World-API.patch b/Spigot-Server-Patches/More-World-API.patch deleted file mode 100644 index b9d3bbd8bb..0000000000 --- a/Spigot-Server-Patches/More-World-API.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Tue, 7 Jul 2020 10:52:34 -0700 -Subject: [PATCH] More World API - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return !this.worldDataServer.getGeneratorSettings().shouldGenerateMapFeatures() ? null : this.getChunkProvider().getChunkGenerator().findNearestMapFeature(this, structuregenerator, blockposition, i, flag); // CraftBukkit - } - -+ public BlockPosition getNearestBiome(BiomeBase biomeBase, BlockPosition blockPosition, int radius, int step) { return this.a(biomeBase, blockPosition, radius, step); } // Paper - OBFHELPER - @Nullable - public BlockPosition a(BiomeBase biomebase, BlockPosition blockposition, int i, int j) { - return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().a(blockposition.getX(), blockposition.getY(), blockposition.getZ(), i, j, (biomebase1) -> { -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return this.savingDisabled; - } - -+ public IRegistryCustom getWorldCustomRegistry() { return r(); } // Paper - OBFHELPER - @Override - public IRegistryCustom r() { - return this.server.getCustomRegistry(); -diff --git a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -+++ b/src/main/java/net/minecraft/world/level/dimension/DimensionManager.java -@@ -0,0 +0,0 @@ public class DimensionManager { - public static IRegistryCustom.Dimension a(IRegistryCustom.Dimension iregistrycustom_dimension) { - IRegistryWritable iregistrywritable = iregistrycustom_dimension.b(IRegistry.K); - -- iregistrywritable.a(DimensionManager.OVERWORLD, (Object) DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.l, (Object) DimensionManager.m, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.THE_NETHER, (Object) DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); -- iregistrywritable.a(DimensionManager.THE_END, (Object) DimensionManager.THE_END_IMPL, Lifecycle.stable()); -+ iregistrywritable.a(DimensionManager.OVERWORLD, DimensionManager.OVERWORLD_IMPL, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.l, DimensionManager.m, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.THE_NETHER, DimensionManager.THE_NETHER_IMPL, Lifecycle.stable()); // Paper - decompile fix -+ iregistrywritable.a(DimensionManager.THE_END, DimensionManager.THE_END_IMPL, Lifecycle.stable()); // Paper - decompile fix - return iregistrycustom_dimension; - } - -@@ -0,0 +0,0 @@ public class DimensionManager { - public static RegistryMaterials a(IRegistry iregistry, IRegistry iregistry1, IRegistry iregistry2, long i) { - RegistryMaterials registrymaterials = new RegistryMaterials<>(IRegistry.M, Lifecycle.experimental()); - -- registrymaterials.a(WorldDimension.THE_NETHER, (Object) (new WorldDimension(() -> { -+ registrymaterials.a(WorldDimension.THE_NETHER, (new WorldDimension(() -> { // Paper - decompile fix - return (DimensionManager) iregistry.d(DimensionManager.THE_NETHER); - }, b(iregistry1, iregistry2, i))), Lifecycle.stable()); -- registrymaterials.a(WorldDimension.THE_END, (Object) (new WorldDimension(() -> { -+ registrymaterials.a(WorldDimension.THE_END, (new WorldDimension(() -> { // Paper - decompile fix - return (DimensionManager) iregistry.d(DimensionManager.THE_END); - }, a(iregistry1, iregistry2, i))), Lifecycle.stable()); - return registrymaterials; -@@ -0,0 +0,0 @@ public class DimensionManager { - return this.E[i]; - } - -+ public Tag getInfiniburnTag() { return o(); } // Paper - OBFHELPER - public Tag o() { - Tag tag = TagsBlock.a().a(this.infiniburn); - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); - } - -+ // Paper start -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius) { -+ return this.locateNearestBiome(origin, biome, radius, 8); -+ } -+ -+ @Override -+ public Location locateNearestBiome(Location origin, Biome biome, int radius, int step) { -+ BlockPosition originPos = new BlockPosition(origin.getX(), origin.getY(), origin.getZ()); -+ BlockPosition nearest = getHandle().getNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().getWorldCustomRegistry().b(IRegistry.ay), biome), originPos, radius, step); -+ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); -+ } -+ -+ @Override -+ public boolean isUltrawarm() { -+ return getHandle().getDimensionManager().isNether(); -+ } -+ -+ @Override -+ public boolean isNatural() { -+ return getHandle().getDimensionManager().isNatural(); -+ } -+ -+ @Override -+ public double getCoordinateScale() { -+ return getHandle().getDimensionManager().getCoordinateScale(); -+ } -+ -+ @Override -+ public boolean hasSkylight() { -+ return getHandle().getDimensionManager().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean hasBedrockCeiling() { -+ return getHandle().getDimensionManager().hasSkyLight(); -+ } -+ -+ @Override -+ public boolean isPiglinSafe() { -+ return getHandle().getDimensionManager().isPiglinSafe(); -+ } -+ -+ @Override -+ public boolean doesBedWork() { -+ return getHandle().getDimensionManager().isBedWorks(); -+ } -+ -+ @Override -+ public boolean doesRespawnAnchorWork() { -+ return getHandle().getDimensionManager().isRespawnAnchorWorks(); -+ } -+ -+ @Override -+ public boolean hasRaids() { -+ return getHandle().getDimensionManager().hasRaids(); -+ } -+ -+ @Override -+ public boolean isFixedTime() { -+ return getHandle().getDimensionManager().isFixedTime(); -+ } -+ -+ @Override -+ public Collection getInfiniburn() { -+ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().getDimensionManager().getInfiniburnTag().getTagged().iterator(), CraftMagicNumbers::getMaterial)); -+ } -+ // Paper end -+ - @Override - public Raid locateNearestRaid(Location location, int radius) { - Validate.notNull(location, "Location cannot be null"); diff --git a/Spigot-Server-Patches/More-lightning-API.patch b/Spigot-Server-Patches/More-lightning-API.patch deleted file mode 100644 index ee3080c341..0000000000 --- a/Spigot-Server-Patches/More-lightning-API.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -Date: Sun, 26 Jul 2020 14:44:09 +0200 -Subject: [PATCH] More lightning API - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLightning.java b/src/main/java/net/minecraft/world/entity/EntityLightning.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLightning.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLightning.java -@@ -0,0 +0,0 @@ public class EntityLightning extends Entity { - - private int lifeTicks; - public long b; -- private int d; -+ private int d; public int getFlashCount() { return d; } public void setFlashCount(int flashes) { this.d = flashes; } // Paper - OBFHELPER - public boolean isEffect; - @Nullable - private EntityPlayer f; -@@ -0,0 +0,0 @@ public class EntityLightning extends Entity { - this.isEffect = flag; - } - -+ // Paper start -+ public int getLifeTicks() { -+ return lifeTicks; -+ } -+ -+ public void setLifeTicks(int lifeTicks) { -+ this.lifeTicks = lifeTicks; -+ } -+ // Paper end -+ - @Override - public SoundCategory getSoundCategory() { - return SoundCategory.WEATHER; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -@@ -0,0 +0,0 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @Override -+ public int getFlashCount() { -+ return getHandle().getFlashCount(); -+ } -+ -+ @Override -+ public void setFlashCount(int flashes) { -+ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); -+ getHandle().setFlashCount(flashes); -+ } -+ -+ @Override -+ public int getLifeTicks() { -+ return getHandle().getLifeTicks(); -+ } -+ -+ @Override -+ public void setLifeTicks(int lifeTicks) { -+ getHandle().setLifeTicks(lifeTicks); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/Spigot-Server-Patches/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch deleted file mode 100644 index d623a5eb77..0000000000 --- a/Spigot-Server-Patches/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: 2277 <38501234+2277@users.noreply.github.com> -Date: Tue, 31 Mar 2020 10:33:55 +0100 -Subject: [PATCH] Move player to spawn point if spawn in unloaded world - -The code following this has better support for null worlds to move -them back to the world spawn. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - bworld = server.getWorld(worldName); - } - -- if (bworld == null) { -- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); -- } -+ // Paper start - Move player to spawn point if spawn in unloaded world -+// if (bworld == null) { -+// bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); -+// } -+ // Paper end - Move player to spawn point if spawn in unloaded world - - spawnIn(bworld == null ? null : ((CraftWorld) bworld).getHandle()); - } diff --git a/Spigot-Server-Patches/Move-range-check-for-block-placing-up.patch b/Spigot-Server-Patches/Move-range-check-for-block-placing-up.patch deleted file mode 100644 index a33391fe6e..0000000000 --- a/Spigot-Server-Patches/Move-range-check-for-block-placing-up.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Jul 2020 19:34:11 -0700 -Subject: [PATCH] Move range check for block placing up - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - BlockPosition blockposition = movingobjectpositionblock.getBlockPosition(); - EnumDirection enumdirection = movingobjectpositionblock.getDirection(); - -+ // Paper start - move check up -+ Location eyeLoc = this.getPlayer().getEyeLocation(); -+ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -+ if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -+ return; -+ } -+ // Paper end - move check up -+ - this.player.resetIdleTimer(); - if (blockposition.getY() < this.minecraftServer.getMaxBuildHeight()) { - if (this.teleportPos == null && this.player.h((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.a((EntityHuman) this.player, blockposition)) { - // CraftBukkit start - Check if we can actually do something over this large a distance -- Location eyeLoc = this.getPlayer().getEyeLocation(); -- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); -- if (reachDistance > (this.getPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { -- return; -- } -+ // Paper - move check up - this.player.clearActiveItem(); // SPIGOT-4706 - // CraftBukkit end - EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/Spigot-Server-Patches/No-Tick-view-distance-implementation.patch b/Spigot-Server-Patches/No-Tick-view-distance-implementation.patch deleted file mode 100644 index cf09d4b0b9..0000000000 --- a/Spigot-Server-Patches/No-Tick-view-distance-implementation.patch +++ /dev/null @@ -1,774 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 21:23:34 -0700 -Subject: [PATCH] No-Tick view distance implementation - -Implements world view distance getters/setters - -Per-Player is absent due to difficulty of maintaining -the diff required to make it happen. - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +0,0 @@ public class TimingsExport extends Thread { - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), -+ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) - )); - })); - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); - phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); - } -+ -+ public int noTickViewDistance; -+ private void viewDistance() { -+ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ public final class MCUtil { - }); - - worldData.addProperty("name", world.getWorld().getName()); -- worldData.addProperty("view-distance", world.spigotConfig.viewDistance); -+ worldData.addProperty("view-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()); -+ worldData.addProperty("no-view-distance", world.getChunkProvider().playerChunkMap.getRawNoTickViewDistance()); - worldData.addProperty("keep-spawn-loaded", world.keepSpawnInMemory); - worldData.addProperty("keep-spawn-loaded-range", world.paperConfig.keepLoadedRange); - worldData.addProperty("visible-chunk-count", visibleChunks.size()); -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - return s; - } - -- protected void a(int i) { -+ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change - this.g.a(i); - } - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - - private void a(long i, int j, boolean flag, boolean flag1) { - if (flag != flag1) { -- Ticket ticket = new Ticket<>(TicketType.PLAYER, ChunkMapDistance.b, new ChunkCoordIntPair(i)); -+ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkCoordIntPair(i)); // Paper - no-tick view distance - - if (flag1) { - ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks - -+ boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - // Paper end - optimise isOutsideOfRange - -+ // Paper start - no-tick view distance -+ public final Chunk getSendingChunk() { -+ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used -+ // in Chunk's neighbour callback -+ Chunk ret = this.chunkMap.world.getChunkProvider().getChunkAtIfLoadedImmediately(this.location.x, this.location.z); -+ if (ret != null && ret.areNeighboursLoaded(1)) { -+ return ret; -+ } -+ return null; -+ } -+ // Paper end - no-tick view distance -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - - public void a(BlockPosition blockposition) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - byte b0 = (byte) SectionPosition.a(blockposition.getY()); -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - - public void a(EnumSkyBlock enumskyblock, int i) { -- Chunk chunk = this.getChunk(); -+ Chunk chunk = this.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - chunk.setNeedsSaving(true); -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - - private void a(Packet packet, boolean flag) { -- this.players.a(this.location, flag).forEach((entityplayer) -> { -- entityplayer.playerConnection.sendPacket(packet); -- }); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PlayerAreaMap viewDistanceMap = this.chunkMap.playerViewDistanceBroadcastMap; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = viewDistanceMap.getObjectsInRange(this.location); -+ if (players == null) { -+ return; -+ } -+ -+ if (flag) { // flag -> border only -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ -+ int viewDistance = viewDistanceMap.getLastViewDistance(player); -+ long lastPosition = viewDistanceMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.location.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.location.z); -+ -+ if (Math.max(distX, distZ) == viewDistance) { -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ } else { -+ Object[] backingSet = players.getBackingSet(); -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ player.playerConnection.sendPacket(packet); -+ } -+ } -+ -+ return; -+ // Paper end - per player view distance - } - - public CompletableFuture> a(ChunkStatus chunkstatus, PlayerChunkMap playerchunkmap) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; -+import net.minecraft.network.protocol.game.PacketPlayOutViewDistance; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.WorldLoadListener; -+import net.minecraft.server.network.PlayerConnection; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private boolean updatingChunksModified; - private final ChunkTaskQueueSorter p; - private final Mailbox> mailboxWorldGen; -- private final Mailbox> mailboxMain; -+ public final Mailbox> mailboxMain; // Paper - private -> public -+ // Paper start -+ final Mailbox> mailboxLight; -+ public void addLightTask(PlayerChunk playerchunk, Runnable run) { -+ this.mailboxLight.a(ChunkTaskQueueSorter.a(playerchunk, run)); -+ } -+ // Paper end - public final WorldLoadListener worldLoadListener; - public final PlayerChunkMap.a chunkDistanceManager; public final ChunkMapDistance getChunkDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER - private final AtomicInteger u; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int noTickViewDistance; -+ public final int getRawNoTickViewDistance() { -+ return this.noTickViewDistance; -+ } -+ public final int getEffectiveNoTickViewDistance() { -+ return this.noTickViewDistance == -1 ? this.getEffectiveViewDistance() : this.noTickViewDistance; -+ } -+ public final int getLoadViewDistance() { -+ return Math.max(this.getEffectiveViewDistance(), this.getEffectiveNoTickViewDistance()); -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceBroadcastMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; -+ // Paper end - no-tick view distance - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerMobSpawnMap.remove(player); - this.playerChunkTickRangeMap.remove(player); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.playerViewDistanceBroadcastMap.remove(player); -+ this.playerViewDistanceTickMap.remove(player); -+ this.playerViewDistanceNoTickMap.remove(player); -+ // Paper end - no-tick view distance - } - - void updateMaps(EntityPlayer player) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ int effectiveTickViewDistance = this.getEffectiveViewDistance(); -+ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); -+ -+ if (!this.cannotLoadChunks(player)) { -+ this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); -+ this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) -+ } -+ -+ player.needsChunkCenterUpdate = true; -+ this.playerViewDistanceBroadcastMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 1); // clients need an extra neighbour to render the full view distance configured -+ player.needsChunkCenterUpdate = false; -+ // Paper end - no-tick view distance - } - // Paper end - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - }); - // Paper end - optimise PlayerChunkMap#isOutsideRange -+ // Paper start - no-tick view distance -+ this.setNoTickViewDistance(this.world.paperConfig.noTickViewDistance); -+ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState.size() != 1) { -+ return; -+ } -+ Chunk chunk = PlayerChunkMap.this.world.getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); -+ if (chunk == null || !chunk.areNeighboursLoaded(2)) { -+ return; -+ } -+ -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); -+ PlayerChunkMap.this.world.getChunkProvider().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (newState != null) { -+ return; -+ } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(rangeX, rangeZ); -+ PlayerChunkMap.this.world.getChunkProvider().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update -+ }); -+ this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ if (player.needsChunkCenterUpdate) { -+ player.needsChunkCenterUpdate = false; -+ player.playerConnection.sendPacket(new PacketPlayOutViewCentre(currPosX, currPosZ)); -+ } -+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), null, true, false); // unloaded, loaded -+ }); -+ // Paper end - no-tick view distance - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - completablefuture1.thenAcceptAsync((either) -> { - either.mapLeft((chunk) -> { - this.u.getAndIncrement(); -- Packet[] apacket = new Packet[2]; -- -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- this.a(entityplayer, apacket, chunk); -- }); -+ // Paper - no-tick view distance - moved to Chunk neighbour update - return Either.left(chunk); - }); - }, (runnable) -> { -- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); -+ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // Paper - diff on change, this is the scheduling method copied in Chunk used to schedule chunk broadcasts (on change it needs to be copied again) - }); - return completablefuture1; - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - } - -- protected void setViewDistance(int i) { -- int j = MathHelper.clamp(i + 1, 3, 33); -+ public void setViewDistance(int i) { // Paper - public -+ int j = MathHelper.clamp(i + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32 - - if (j != this.viewDistance) { - int k = this.viewDistance; - - this.viewDistance = j; -- this.chunkDistanceManager.a(this.viewDistance); -- ObjectIterator objectiterator = this.updatingChunks.values().iterator(); -+ this.setNoTickViewDistance(this.getRawNoTickViewDistance()); //Paper - no-tick view distance - propagate changes to no-tick, which does the actual chunk loading/sending -+ } - -- while (objectiterator.hasNext()) { -- PlayerChunk playerchunk = (PlayerChunk) objectiterator.next(); -- ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); -- Packet[] apacket = new Packet[2]; -+ } - -- this.a(chunkcoordintpair, false).forEach((entityplayer) -> { -- int l = b(chunkcoordintpair, entityplayer, true); -- boolean flag = l <= k; -- boolean flag1 = l <= this.viewDistance; -+ // Paper start - no-tick view distance -+ public final void setNoTickViewDistance(int viewDistance) { -+ viewDistance = viewDistance == -1 ? -1 : MathHelper.clamp(viewDistance, 2, 32); - -- this.sendChunk(entityplayer, chunkcoordintpair, apacket, flag, flag1); -- }); -+ this.noTickViewDistance = viewDistance; -+ int loadViewDistance = this.getLoadViewDistance(); -+ this.chunkDistanceManager.setNoTickViewDistance(loadViewDistance + 2 + 2); // add 2 to account for the change to 31 -> 33 tickets // see notes in the distance map updating for the other + 2 -+ -+ if (this.world != null && this.world.players != null) { // this can be called from constructor, where these aren't set -+ for (EntityPlayer player : this.world.players) { -+ PlayerConnection connection = player.playerConnection; -+ if (connection != null) { -+ // moved in from PlayerList -+ connection.sendPacket(new PacketPlayOutViewDistance(loadViewDistance)); -+ } -+ this.updateMaps(player); - } - } -- - } -+ // Paper end - no-tick view distance - - protected void sendChunk(EntityPlayer entityplayer, ChunkCoordIntPair chunkcoordintpair, Packet[] apacket, boolean flag, boolean flag1) { - if (entityplayer.world == this.world) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PlayerChunk playerchunk = this.getVisibleChunk(chunkcoordintpair.pair()); - - if (playerchunk != null) { -- Chunk chunk = playerchunk.getChunk(); -+ Chunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance - - if (chunk != null) { - this.a(entityplayer, apacket, chunk); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - optimise isOutsideOfRange - -+ private boolean cannotLoadChunks(EntityPlayer entityplayer) { return this.b(entityplayer); } // Paper - OBFHELPER - private boolean b(EntityPlayer entityplayer) { - return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.removePlayerFromDistanceMaps(entityplayer); // Paper - distance maps - } - -- for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { -- for (int l = j - this.viewDistance; l <= j + this.viewDistance; ++l) { -- ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k, l); -- -- this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], !flag, flag); -- } -- } -+ // Paper - broadcast view distance map handles this (see remove/add calls above) - - } - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - SectionPosition sectionposition = SectionPosition.a((Entity) entityplayer); - - entityplayer.a(sectionposition); -- entityplayer.playerConnection.sendPacket(new PacketPlayOutViewCentre(sectionposition.a(), sectionposition.c())); -+ // Paper - distance map handles this now - return sectionposition; - } - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int k1; - int l1; - -+ /* // Paper start - replaced by distance map - if (Math.abs(i1 - i) <= this.viewDistance * 2 && Math.abs(j1 - j) <= this.viewDistance * 2) { - k1 = Math.min(i, i1) - this.viewDistance; - l1 = Math.min(j, j1) - this.viewDistance; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); - } - } -- } -+ }*/ // Paper end - replaced by distance map - - this.updateMaps(entityplayer); // Paper - distance maps - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - @Override - public Stream a(ChunkCoordIntPair chunkcoordintpair, boolean flag) { -- return this.playerMap.a(chunkcoordintpair.pair()).filter((entityplayer) -> { -- int i = b(chunkcoordintpair, entityplayer, true); -+ // Paper start - per player view distance -+ // there can be potential desync with player's last mapped section and the view distance map, so use the -+ // view distance map here. -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkcoordintpair); - -- return i > this.viewDistance ? false : !flag || i == this.viewDistance; -- }); -+ if (inRange == null) { -+ return Stream.empty(); -+ } -+ // all current cases are inlined so we wont hit this code, it's just in case plugins or future updates use it -+ List players = new java.util.ArrayList<>(); -+ Object[] backingSet = inRange.getBackingSet(); -+ -+ if (flag) { // flag -> border only -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); -+ -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkcoordintpair.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkcoordintpair.z); -+ if (Math.max(distX, distZ) == viewDistance) { -+ players.add(player); -+ } -+ } -+ } else { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object temp = backingSet[i]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ players.add(player); -+ } -+ } -+ return players.stream(); -+ // Paper end - per player view distance - } - - public void addEntity(Entity entity) { // Paper - protected -> public -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -- private final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER -+ // Paper start -+ private static int getLightMask(final Chunk chunk) { -+ final ChunkSection[] chunkSections = chunk.getSections(); -+ int mask = 0; -+ -+ for (int i = 0; i < chunkSections.length; ++i) { -+ /* -+ -+ -+Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section. -+Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. -+ -+ */ -+ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; -+ } -+ -+ return mask; -+ } -+ -+ private static int getCeilingLightMask(final Chunk chunk) { -+ int mask = getLightMask(chunk); -+ -+ /* -+ It is similar to get highest bit, it would turn an 001010 into an 001111 so basically the highest bit and all below. -+ We then invert this, so we'd have 110000 and compare that to the "main" chunk. -+ This is because the bug only appears when the current chunks lightmaps are higher than those of the neighbors, thus we can omit sending neighbors which are lower than the current chunks lights. -+ -+ so TLDR is that getCeilingLightMask returns a light mask with all bits set below the highest affected section. We could also count the number of leading zeros and invert them, somehow. -+ @TODO: Implement Leafs suggestion -+ either use Integer#numberOfLeadingZeros or document what this bithack is supposed to be doing then -+ */ -+ mask |= mask >> 1; -+ mask |= mask >> 2; -+ mask |= mask >> 4; -+ mask |= mask >> 8; -+ mask |= mask >> 16; -+ -+ return mask; -+ } -+ // Paper end -+ -+ public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { - apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ); - PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair()); - -- if (playerchunk != null && playerchunk.getChunk() != null) { -+ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance - flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance; - } - } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - boolean flag1 = gamerules.getBoolean(GameRules.REDUCED_DEBUG_INFO); - - // Spigot - view distance -- playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); -+ playerconnection.sendPacket(new PacketPlayOutLogin(entityplayer.getId(), entityplayer.playerInteractManager.getGameMode(), entityplayer.playerInteractManager.c(), BiomeManager.a(worldserver1.getSeed()), worlddata.isHardcore(), this.server.F(), this.s, worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), this.getMaxPlayers(), worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebugWorld(), worldserver1.isFlatWorld())); // Paper - no-tick view distance - entityplayer.getBukkitEntity().sendSupportedChannels(); // CraftBukkit - playerconnection.sendPacket(new PacketPlayOutCustomPayload(PacketPlayOutCustomPayload.a, (new PacketDataSerializer(Unpooled.buffer())).a(this.getServer().getServerModName()))); - playerconnection.sendPacket(new PacketPlayOutServerDifficulty(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - // CraftBukkit start - WorldData worlddata = worldserver1.getWorldData(); - entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(worldserver1.getDimensionManager(), worldserver1.getDimensionKey(), BiomeManager.a(worldserver1.getSeed()), entityplayer1.playerInteractManager.getGameMode(), entityplayer1.playerInteractManager.c(), worldserver1.isDebugWorld(), worldserver1.isFlatWorld(), flag)); -- entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.spigotConfig.viewDistance)); // Spigot -+ entityplayer1.playerConnection.sendPacket(new PacketPlayOutViewDistance(worldserver1.getChunkProvider().playerChunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance - entityplayer1.spawnIn(worldserver1); - entityplayer1.dead = false; - entityplayer1.playerConnection.teleport(new Location(worldserver1.getWorld(), entityplayer1.locX(), entityplayer1.locY(), entityplayer1.locZ(), entityplayer1.yaw, entityplayer1.pitch)); -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - public void a(int i) { - this.viewDistance = i; -- this.sendAll(new PacketPlayOutViewDistance(i)); -+ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance - Iterator iterator = this.server.getWorlds().iterator(); - - while (iterator.hasNext()) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.b(blockposition, iblockdata1, iblockdata2); - } - -- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement -+ if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getState() != null && chunk.getState().isAtLeast(PlayerChunk.State.TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement // Paper - diff on change, see below - this.notify(blockposition, iblockdata1, iblockdata, i); -+ // Paper start - per player view distance - allow block updates for non-ticking chunks in player view distance -+ // if copied from above -+ } else if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || ((WorldServer)this).getChunkProvider().playerChunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { -+ ((WorldServer)this).getChunkProvider().flagDirty(blockposition); -+ // Paper end - per player view distance - } - - if ((i & 1) != 0) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.level.ChunkTaskQueueSorter; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.EntitySlice; - import net.minecraft.util.MathHelper; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - - protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { -+ // Paper start - no-tick view distance -+ ChunkProviderServer chunkProviderServer = ((WorldServer)this.world).getChunkProvider(); -+ PlayerChunkMap chunkMap = chunkProviderServer.playerChunkMap; -+ // this code handles the addition of ticking tickets - the distance map handles the removal -+ if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { -+ if (chunkMap.playerViewDistanceTickMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready for entity ticking -+ chunkProviderServer.serverThreadQueue.execute(() -> { -+ // double check that this condition still holds. -+ if (Chunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(Chunk.this.coordinateKey) != null) { -+ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, Chunk.this.loc, 31, Chunk.this.loc); // 31 -> entity ticking, TODO check on update -+ } -+ }); -+ } -+ } - -+ // this code handles the chunk sending -+ if (!areNeighboursLoaded(bitsetBefore, 1) && areNeighboursLoaded(bitsetAfter, 1)) { -+ if (chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(this.coordinateKey) != null) { -+ // now we're ready to send -+ chunkMap.mailboxMain.a(ChunkTaskQueueSorter.a(chunkMap.getUpdatingChunk(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap -+ // double check that this condition still holds. -+ if (!Chunk.this.areNeighboursLoaded(1)) { -+ return; -+ } -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(Chunk.this.coordinateKey); -+ if (inRange == null) { -+ return; -+ } -+ -+ // broadcast -+ Object[] backingSet = inRange.getBackingSet(); -+ Packet[] chunkPackets = new Packet[2]; -+ for (int index = 0, len = backingSet.length; index < len; ++index) { -+ Object temp = backingSet[index]; -+ if (!(temp instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)temp; -+ chunkMap.sendChunk(player, chunkPackets, Chunk.this); -+ } -+ }))); -+ } -+ } -+ // Paper end - no-tick view distance - } - - public final boolean isAnyNeighborsLoaded() { -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - IBlockData iblockdata = this.getType(blockposition); - IBlockData iblockdata1 = Block.b(iblockdata, (GeneratorAccess) this.world, blockposition); - -- this.world.setTypeAndData(blockposition, iblockdata1, 20); -+ this.world.setTypeAndData(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here - } - - this.n[i].clear(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutWorldEvent; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.server.level.ChunkMapDistance; - import net.minecraft.server.level.PlayerChunk; -+import net.minecraft.server.level.PlayerChunkMap; - import net.minecraft.server.level.Ticket; - import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - // Spigot start - @Override - public int getViewDistance() { -- return world.spigotConfig.viewDistance; -+ return getHandle().getChunkProvider().playerChunkMap.getEffectiveViewDistance(); // Paper - no-tick view distance - } - // Spigot end - -+ // Paper start - per player view distance -+ @Override -+ public void setViewDistance(int viewDistance) { -+ if (viewDistance < 2 || viewDistance > 32) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getEffectiveViewDistance()) { -+ chunkMap.setViewDistance(viewDistance); -+ } -+ } -+ -+ @Override -+ public int getNoTickViewDistance() { -+ return getHandle().getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance(); -+ } -+ -+ @Override -+ public void setNoTickViewDistance(int viewDistance) { -+ if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { -+ throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); -+ } -+ PlayerChunkMap chunkMap = getHandle().getChunkProvider().playerChunkMap; -+ if (viewDistance != chunkMap.getRawNoTickViewDistance()) { -+ chunkMap.setNoTickViewDistance(viewDistance); -+ } -+ } -+ // Paper end - per player view distance -+ - // Spigot start - private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() - { -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ package org.spigotmc; - - import java.util.Collection; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityCreature; -@@ -0,0 +0,0 @@ public class ActivationRange - maxRange = Math.max( maxRange, waterActivationRange ); - maxRange = Math.max( maxRange, villagerActivationRange ); - // Paper end -- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); -+ maxRange = Math.min( ( ((WorldServer)world).getChunkProvider().playerChunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance - - for ( EntityHuman player : world.getPlayers() ) - { diff --git a/Spigot-Server-Patches/Ocelot-despawns-should-honor-nametags-and-leash.patch b/Spigot-Server-Patches/Ocelot-despawns-should-honor-nametags-and-leash.patch deleted file mode 100644 index d6c6fdbd13..0000000000 --- a/Spigot-Server-Patches/Ocelot-despawns-should-honor-nametags-and-leash.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:54:40 -0500 -Subject: [PATCH] Ocelot despawns should honor nametags and leash - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityOcelot.java -@@ -0,0 +0,0 @@ public class EntityOcelot extends EntityAnimal { - - @Override - public boolean isTypeNotPersistent(double d0) { -- return !this.isTrusting() /*&& this.ticksLived > 2400*/; // CraftBukkit -+ return !this.isTrusting() && !this.hasCustomName() && !this.isLeashed() /*&& this.ticksLived > 2400*/; // CraftBukkit // Paper - honor name and leash - } - - public static AttributeProvider.Builder eK() { diff --git a/Spigot-Server-Patches/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/Spigot-Server-Patches/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch deleted file mode 100644 index b8bc848766..0000000000 --- a/Spigot-Server-Patches/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 01:01:32 -0400 -Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob - limit - -This resolves the super common complaint about mobs not spawning. - -This was ultimately a flaw in the vanilla count algorithim that allows -spawners and other misc mobs to count against the mob limit, which are -not bounded, and can prevent the entire world from spawning new. - -I believe Bukkits changes around persistence may of actually made it -worse than vanilla. - -This should fully solve all of the issues around it so that only natural -influences natural spawns. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); - } - -+ public boolean countAllMobsForSpawning = false; -+ private void countAllMobsForSpawning() { -+ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); -+ if (countAllMobsForSpawning) { -+ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); -+ } else { -+ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); -+ } -+ } -+ - public boolean antiXray; - public EngineMode engineMode; - public int maxChunkSectionIndex; -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - EnumCreatureType enumcreaturetype = entity.getEntityType().e(); - - if (enumcreaturetype != EnumCreatureType.MISC) { -+ // Paper start - Only count natural spawns -+ if (!entity.world.paperConfig.countAllMobsForSpawning && -+ !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL || -+ entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { -+ continue; -+ } -+ // Paper end - BlockPosition blockposition = entity.getChunkCoordinates(); - long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); - diff --git a/Spigot-Server-Patches/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/Spigot-Server-Patches/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch deleted file mode 100644 index 09abcba5df..0000000000 --- a/Spigot-Server-Patches/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 28 Mar 2016 19:55:45 -0400 -Subject: [PATCH] Only process BlockPhysicsEvent if a plugin has a listener - -Saves on some object allocation and processing when no plugin listens to this - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper - - this.methodProfiler.a(() -> { - return worldserver + " " + worldserver.getDimensionKey().a(); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - private int tickPosition; - public final Convertable.ConversionSession convertable; - public final UUID uuid; -+ public boolean hasPhysicsEvent = true; // Paper - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI - return this.chunkProvider.getChunkAt(x, z, false); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit start - iblockdata1.b(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam - CraftWorld world = ((WorldServer) this).getWorld(); -- if (world != null) { -+ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); - this.getServer().getPluginManager().callEvent(event); - -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - try { - // CraftBukkit start - CraftWorld world = ((WorldServer) this).getWorld(); -- if (world != null) { -+ if (world != null && ((WorldServer)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ())); - this.getServer().getPluginManager().callEvent(event); - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPlant.java b/src/main/java/net/minecraft/world/level/block/BlockPlant.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPlant.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPlant.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.block; - - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.IWorldReader; -@@ -0,0 +0,0 @@ public class BlockPlant extends Block { - public IBlockData updateState(IBlockData iblockdata, EnumDirection enumdirection, IBlockData iblockdata1, GeneratorAccess generatoraccess, BlockPosition blockposition, BlockPosition blockposition1) { - // CraftBukkit start - if (!iblockdata.canPlace(generatoraccess, blockposition)) { -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { -+ if (!(generatoraccess instanceof WorldServer && ((WorldServer) generatoraccess).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(generatoraccess, blockposition).isCancelled()) { // Paper - return Blocks.AIR.getBlockData(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTallPlant.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.block; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; -@@ -0,0 +0,0 @@ public class BlockTallPlant extends BlockPlant { - - protected static void b(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) { - // CraftBukkit start -- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { -+ if (((WorldServer)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, blockposition).isCancelled()) { // Paper - return; - } - // CraftBukkit end diff --git a/Spigot-Server-Patches/Only-refresh-abilities-if-needed.patch b/Spigot-Server-Patches/Only-refresh-abilities-if-needed.patch deleted file mode 100644 index 7a8b95aef3..0000000000 --- a/Spigot-Server-Patches/Only-refresh-abilities-if-needed.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 1 Mar 2016 23:12:03 -0600 -Subject: [PATCH] Only refresh abilities if needed - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - @Override - public void setFlying(boolean value) { -+ boolean needsUpdate = getHandle().abilities.isFlying != value; // Paper - Only refresh abilities if needed - if (!getAllowFlight() && value) { - throw new IllegalArgumentException("Cannot make player fly if getAllowFlight() is false"); - } - - getHandle().abilities.isFlying = value; -- getHandle().updateAbilities(); -+ if (needsUpdate) getHandle().updateAbilities(); // Paper - Only refresh abilities if needed - } - - @Override diff --git a/Spigot-Server-Patches/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/Spigot-Server-Patches/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch deleted file mode 100644 index e414bb728e..0000000000 --- a/Spigot-Server-Patches/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 May 2016 22:53:50 -0400 -Subject: [PATCH] Only send Dragon/Wither Death sounds to same world - -Also fix view distance lookup - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (this.deathAnimationTicks == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (net.minecraft.server.level.EntityPlayer player : this.world.getMinecraftServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; -- for (EntityPlayer player : (List) MinecraftServer.getServer().getPlayerList().players) { -+ //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ for (EntityPlayer player : (List)this.world.getPlayers()) { -+ final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/Spigot-Server-Patches/Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/Spigot-Server-Patches/Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch deleted file mode 100644 index b1d81d8664..0000000000 --- a/Spigot-Server-Patches/Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Fri, 19 Mar 2021 16:07:21 -0700 -Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by - MobSpawnerTrader - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ public class EntityTypes { - - @Nullable - public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - add consumer to modify entity before spawn -+ return this.spawnCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1, spawnReason, null); -+ } -+ @Nullable -+ public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason, @Nullable java.util.function.Consumer op) { -+ // Paper end - // Paper start - Call PreCreatureSpawnEvent - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); - if (type != null) { -@@ -0,0 +0,0 @@ public class EntityTypes { - } - // Paper end - T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); -+ if (t0 != null && op != null) op.accept(t0); // Paper - - if (t0 != null) { - worldserver.addAllEntities(t0, spawnReason); -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerTrader.java -@@ -0,0 +0,0 @@ public class EntityVillagerTrader extends EntityVillagerAbstract { - public EntityVillagerTrader(EntityTypes entitytypes, World world) { - super(entitytypes, world); - this.attachedToPlayer = true; -- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader -+ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set. - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -+++ b/src/main/java/net/minecraft/world/entity/npc/MobSpawnerTrader.java -@@ -0,0 +0,0 @@ public class MobSpawnerTrader implements MobSpawner { - return false; - } - -- EntityVillagerTrader entityvillagertrader = (EntityVillagerTrader) EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit -+ EntityVillagerTrader entityvillagertrader = EntityTypes.WANDERING_TRADER.spawnCreature(worldserver, null, null, null, blockposition2, EnumMobSpawn.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, trader -> trader.setDespawnDelay(48000)); // CraftBukkit // Paper - set despawnTimer before spawn events called - - if (entityvillagertrader != null) { - for (int i = 0; i < 2; ++i) { diff --git a/Spigot-Server-Patches/Optimise-ArraySetSorted-removeIf.patch b/Spigot-Server-Patches/Optimise-ArraySetSorted-removeIf.patch deleted file mode 100644 index 127972a778..0000000000 --- a/Spigot-Server-Patches/Optimise-ArraySetSorted-removeIf.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Apr 2020 18:23:28 -0700 -Subject: [PATCH] Optimise ArraySetSorted#removeIf - -Remove iterator allocation and ensure the call is always O(n) - -diff --git a/src/main/java/net/minecraft/util/ArraySetSorted.java b/src/main/java/net/minecraft/util/ArraySetSorted.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/ArraySetSorted.java -+++ b/src/main/java/net/minecraft/util/ArraySetSorted.java -@@ -0,0 +0,0 @@ import java.util.NoSuchElementException; - public class ArraySetSorted extends AbstractSet { - - private final Comparator a; -- private T[] b; -- private int c; -+ private T[] b; private final T[] getBackingArray() { return this.b; } // Paper - OBFHELPER -+ private int c; private final int getSize() { return this.c; } private final void setSize(int value) { this.c = value; } // Paper - OBFHELPER - - private ArraySetSorted(int i, Comparator comparator) { - this.a = comparator; -@@ -0,0 +0,0 @@ public class ArraySetSorted extends AbstractSet { - } - } - -+ // Paper start - optimise removeIf -+ @Override -+ public boolean removeIf(java.util.function.Predicate filter) { -+ // prev. impl used an iterator, which could be n^2 and creates garbage -+ int i = 0, len = this.getSize(); -+ T[] backingArray = this.getBackingArray(); -+ -+ for (;;) { -+ if (i >= len) { -+ return false; -+ } -+ if (!filter.test(backingArray[i])) { -+ ++i; -+ continue; -+ } -+ break; -+ } -+ -+ // we only want to write back to backingArray if we really need to -+ -+ int lastIndex = i; // this is where new elements are shifted to -+ -+ for (; i < len; ++i) { -+ T curr = backingArray[i]; -+ if (!filter.test(curr)) { // if test throws we're screwed -+ backingArray[lastIndex++] = curr; -+ } -+ } -+ -+ // cleanup end -+ Arrays.fill(backingArray, lastIndex, len, null); -+ this.setSize(lastIndex); -+ return true; -+ } -+ // Paper end - optimise removeIf -+ - public static > ArraySetSorted a(int i) { - return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } diff --git a/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch b/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch deleted file mode 100644 index cc23459ed0..0000000000 --- a/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 19 Aug 2016 01:52:56 +0100 -Subject: [PATCH] Optimise BlockState's hashCode/equals - -These are singleton "single instance" objects. We can rely on -object identity checks safely. - -Use a simpler optimized hashcode - -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateBoolean.java -@@ -0,0 +0,0 @@ public class BlockStateBoolean extends IBlockState { - return obool.toString(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateBoolean && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateEnum.java -@@ -0,0 +0,0 @@ public class BlockStateEnum & INamable> extends IBlockState - return ((INamable) t0).getName(); - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateEnum && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/BlockStateInteger.java -@@ -0,0 +0,0 @@ public class BlockStateInteger extends IBlockState { - return this.a; - } - -- @Override -- public boolean equals(Object object) { -+ public boolean equals_unused(Object object) { // Paper - if (this == object) { - return true; - } else if (object instanceof BlockStateInteger && super.equals(object)) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -+++ b/src/main/java/net/minecraft/world/level/block/state/properties/IBlockState.java -@@ -0,0 +0,0 @@ public abstract class IBlockState> { - } - - public boolean equals(Object object) { -- if (this == object) { -- return true; -- } else if (!(object instanceof IBlockState)) { -- return false; -- } else { -- IBlockState iblockstate = (IBlockState) object; -- -- return this.a.equals(iblockstate.a) && this.b.equals(iblockstate.b); -- } -+ return this == object; // Paper - only one instance per configuration - } - -+ private static final java.util.concurrent.atomic.AtomicInteger hashId = new java.util.concurrent.atomic.AtomicInteger(1); // Paper - only one instance per configuration -+ private final int hashCode = 92821 * hashId.getAndIncrement(); // Paper - only one instance per configuration - public final int hashCode() { - if (this.c == null) { - this.c = this.b(); - } - -- return this.c; -+ return this.hashCode; // Paper - only one instance per configuration - } - - public int b() { diff --git a/Spigot-Server-Patches/Optimise-Chunk-getFluid.patch b/Spigot-Server-Patches/Optimise-Chunk-getFluid.patch deleted file mode 100644 index 4b00052462..0000000000 --- a/Spigot-Server-Patches/Optimise-Chunk-getFluid.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 14 Jan 2020 14:59:08 -0800 -Subject: [PATCH] Optimise Chunk#getFluid - -Removing the try catch and generally reducing ops should make it -faster on its own, however removing the try catch makes it -easier to inline due to code size - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - - public Fluid a(int i, int j, int k) { -- try { -- if (j >= 0 && j >> 4 < this.sections.length) { -- ChunkSection chunksection = this.sections[j >> 4]; -- -- if (!ChunkSection.a(chunksection)) { -- return chunksection.b(i & 15, j & 15, k & 15); -+ //try { // Paper - remove try catch -+ // Paper start - reduce the number of ops in this call -+ int index = j >> 4; -+ if (index >= 0 && index < this.sections.length) { -+ ChunkSection chunksection = this.sections[index]; -+ -+ if (chunksection != null) { -+ return chunksection.blockIds.a((j & 15) << 8 | (k & 15) << 4 | i & 15).getFluid(); - } -+ // Paper end - } - - return FluidTypes.EMPTY.h(); -- } catch (Throwable throwable) { -+ /*} catch (Throwable throwable) { // Paper - remove try catch - CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got"); - -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - }); - throw new ReportedException(crashreport); - } -+ */ // Paper - remove try catch - } - - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -0,0 +0,0 @@ public class ChunkSection { - } - - public Fluid b(int i, int j, int k) { -- return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); -+ return ((IBlockData) this.blockIds.a(i, j, k)).getFluid(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid. - } - - public void a() { diff --git a/Spigot-Server-Patches/Optimise-IEntityAccess-getPlayerByUUID.patch b/Spigot-Server-Patches/Optimise-IEntityAccess-getPlayerByUUID.patch deleted file mode 100644 index f29518aeaa..0000000000 --- a/Spigot-Server-Patches/Optimise-IEntityAccess-getPlayerByUUID.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 11 Jan 2020 21:50:56 -0800 -Subject: [PATCH] Optimise IEntityAccess#getPlayerByUUID - -Use the world entity map instead of iterating over all players - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ // Paper start - optimise getPlayerByUUID -+ @Nullable -+ @Override -+ public EntityHuman getPlayerByUUID(UUID uuid) { -+ Entity player = this.entitiesByUUID.get(uuid); -+ return (player instanceof EntityHuman) ? (EntityHuman)player : null; -+ } -+ // Paper end -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -0,0 +0,0 @@ public interface IEntityAccess { - - @Nullable - default EntityHuman b(UUID uuid) { -+ // Paper start - allow WorldServer to override -+ return this.getPlayerByUUID(uuid); -+ } -+ @Nullable -+ default EntityHuman getPlayerByUUID(UUID uuid) { -+ // Paper end - for (int i = 0; i < this.getPlayers().size(); ++i) { - EntityHuman entityhuman = (EntityHuman) this.getPlayers().get(i); - diff --git a/Spigot-Server-Patches/Optimise-TickListServer-by-rewriting-it.patch b/Spigot-Server-Patches/Optimise-TickListServer-by-rewriting-it.patch deleted file mode 100644 index 490d3eac81..0000000000 --- a/Spigot-Server-Patches/Optimise-TickListServer-by-rewriting-it.patch +++ /dev/null @@ -1,1267 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 14 Feb 2020 01:24:39 -0800 -Subject: [PATCH] Optimise TickListServer by rewriting it - -In my profiling TickListServer showed up as -~10% for saving chunks and ~5% for the scheduling -of items on a server with ~90 players at -view distance = 5. Most of the performance -loss is unneccessary. - -TickListServer has numerous performance issues: - 1. Handling scheduled items is O(nlogn) - 2. Getting scheduled items for a chunk is O(n), - with n being the the number of scheduled items - for all chunks (hits saving very hard) - 3. Checking if an item is scheduled for the current tick is O(n), - with n being the number of items scheduled for current tick - 4. Items not in ticking chunks are churned in the scheduler - -The biggest issues are 4 & 2. - -We solve 1 by splitting up scheduled items into short and long scheduled, -where we expect the vast majority of our entries to be in the short scheduled -set. Handling short scheduled items is O(n) due to how the comparison -process is reduced to mapping. See TickListServerInterval. However, -this isn't memory-efficient - which is why long scheduled exists. -Long scheduled is handled the same as TickListServer. - -2 is solved by mapping what entries are in what chunks. - -3 is solved by mapping what blocks have what scheduled for them. - -4 is solved by moving the items that are not in ticking chunks -into a map of entries for that chunk. Once the chunk is moved -to ticking, the items are re-scheduled. - -This patch has also added two flags to debug excessive tick delays: --Dpaper.ticklist-warn-on-excessive-delay=true (false by default) -and -Dpaper.ticklist-excessive-delay-threshold=ticks which -sets the excessive tick delay to the specified ticks (defaults to -60 * 20 ticks, aka 60 seconds) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier); - } - -+ public static boolean useOptimizedTickList = true; -+ private static void useOptimizedTickList() { -+ if (config.contains("settings.use-optimized-ticklist")) { // don't add default, hopefully temporary config -+ useOptimizedTickList = config.getBoolean("settings.use-optimized-ticklist"); -+ } -+ } -+ - public static boolean asyncChunks = false; - private static void asyncChunks() { - ConfigurationSection section; -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import java.util.function.Function; -+import net.minecraft.CrashReport; -+import net.minecraft.CrashReportSystemDetails; -+import net.minecraft.ReportedException; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; -+import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; -+import java.util.ArrayDeque; -+import java.util.ArrayList; -+import java.util.Collections; -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.List; -+import java.util.function.Consumer; -+import java.util.function.Predicate; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import net.minecraft.world.level.NextTickListEntry; -+import net.minecraft.world.level.TickListPriority; -+import net.minecraft.world.level.TickListServer; -+import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; -+ -+public final class PaperTickList extends TickListServer { // extend to avoid breaking ABI -+ -+ // in the order the state is expected to change (mostly) -+ public static final int STATE_UNSCHEDULED = 1 << 0; -+ public static final int STATE_SCHEDULED = 1 << 1; // scheduled for some tick -+ public static final int STATE_PENDING_TICK = 1 << 2; // for this tick -+ public static final int STATE_TICKING = 1 << 3; -+ public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled -+ public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick -+ -+ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds -+ -+ private final WorldServer world; -+ private final Predicate excludeFromScheduling; -+ private final Function getMinecraftKeyFrom; -+ //private final Function getObjectFronMinecraftKey; -+ private final Consumer> tickFunction; -+ -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ private final co.aikar.timings.Timing timingFinished; -+ -+ // note: remove ops / add ops suck on fastutil, a chained hashtable implementation would work better, but Long... -+ // try to alleviate with a very small load factor -+ private final Long2ObjectOpenHashMap>> entriesByBlock = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> entriesByChunk = new Long2ObjectOpenHashMap<>(1024, 0.25f); -+ private final Long2ObjectOpenHashMap>> pendingChunkTickLoad = new Long2ObjectOpenHashMap<>(1024, 0.5f); -+ -+ // fastutil has O(1) first/last while TreeMap/TreeSet are log(n) -+ private final ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ -+ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); -+ -+ private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; -+ { -+ for (int i = 0, len = this.shortScheduled.length; i < len; ++i) { -+ this.shortScheduled[i] = new TickListServerInterval<>(); -+ } -+ } -+ private int shortScheduledIndex; -+ -+ private long currentTick; -+ -+ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); -+ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl -+ -+ // assume index < length -+ private static int getWrappedIndex(final int start, final int length, final int index) { -+ final int next = start + index; -+ return next < length ? next : next - length; -+ } -+ -+ private static int getNextIndex(final int curr, final int length) { -+ final int next = curr + 1; -+ return next < length ? next : 0; -+ } -+ -+ public PaperTickList(final WorldServer world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, -+ final Consumer> tickFunction, final String timingsType) { -+ super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType); -+ this.world = world; -+ this.excludeFromScheduling = excludeFromScheduling; -+ this.getMinecraftKeyFrom = getMinecraftKeyFrom; -+ this.tickFunction = tickFunction; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper -+ this.timingFinished = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Finish"); -+ this.currentTick = this.world.getTime(); -+ } -+ -+ private void queueEntryForTick(final NextTickListEntry entry, final ChunkProviderServer chunkProvider) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { -+ this.toTickThisTick.add(entry); -+ entry.tickState = STATE_PENDING_TICK; -+ } else { -+ // we dump them to a map to avoid constantly re-scheduling them -+ this.addToNotTickingReady(entry); -+ } -+ } -+ } -+ -+ private void addToNotTickingReady(final NextTickListEntry entry) { -+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { -+ return new ArrayList<>(); -+ }).add(entry); -+ } -+ -+ private void addToSchedule(final NextTickListEntry entry) { -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { -+ if (delay < 0) { -+ // longScheduled orders by tick time, short scheduled does not -+ this.longScheduled.add(entry); -+ } else { -+ this.shortScheduled[getWrappedIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD, (int)delay)].addEntryLast(entry); -+ } -+ } else { -+ this.longScheduled.add(entry); -+ } -+ } -+ -+ private void removeEntry(final NextTickListEntry entry) { -+ entry.tickState = STATE_CANCELLED_TICK; -+ // short/long scheduled will skip the entry -+ -+ final BlockPosition pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); -+ -+ if (pendingTickingLoad != null) { -+ for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { -+ if (pendingTickingLoad.get(i) == entry) { -+ pendingTickingLoad.remove(i); -+ break; -+ } -+ } -+ -+ if (pendingTickingLoad.isEmpty()) { -+ this.pendingChunkTickLoad.remove(chunkKey); -+ } -+ } -+ -+ long delay = entry.getTargetTick() - (this.currentTick + 1); -+ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { -+ this.longScheduled.remove(entry); -+ } -+ } -+ -+ public void onChunkSetTicking(final int chunkX, final int chunkZ) { -+ final ArrayList> pending = this.pendingChunkTickLoad.remove(MCUtil.getCoordinateKey(chunkX, chunkZ)); -+ if (pending == null) { -+ return; -+ } -+ -+ for (int i = 0, size = pending.size(); i < size; ++i) { -+ final NextTickListEntry entry = pending.get(i); -+ // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled -+ this.addToSchedule(entry); -+ } -+ } -+ -+ private void prepare() { -+ final long currentTick = this.currentTick; -+ -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); -+ -+ // here we setup what's going to tick -+ -+ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of -+ // this tick -+ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) { -+ // nothing in longScheduled to worry about -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ this.queueEntryForTick(iterator.next(), chunkProvider); -+ } -+ } -+ } else { -+ final TickListServerInterval interval = this.shortScheduled[this.shortScheduledIndex]; -+ -+ // combine interval and longScheduled, keeping order -+ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; -+ final Iterator> longScheduledIterator = this.longScheduled.iterator(); -+ NextTickListEntry longCurrent = longScheduledIterator.next(); -+ -+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) { -+ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { -+ final NextTickListEntry shortCurrent = iterator.next(); -+ if (longCurrent != null) { -+ // drain longCurrent until we can add shortCurrent -+ while (comparator.compare(longCurrent, shortCurrent) <= 0) { -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ longScheduledIterator.remove(); -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ if (longCurrent.getTargetTick() > currentTick) { -+ longCurrent = null; -+ break; -+ } -+ } else { -+ longCurrent = null; -+ break; -+ } -+ } -+ } -+ this.queueEntryForTick(shortCurrent, chunkProvider); -+ } -+ } -+ -+ // add remaining from long scheduled -+ for (;;) { -+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { -+ break; -+ } -+ longScheduledIterator.remove(); -+ this.queueEntryForTick(longCurrent, chunkProvider); -+ -+ if (longScheduledIterator.hasNext()) { -+ longCurrent = longScheduledIterator.next(); -+ } else { -+ break; -+ } -+ } -+ } -+ } -+ -+ private boolean warnedAboutDesync; -+ -+ @Override -+ public void nextTick() { -+ ++this.currentTick; -+ if (this.currentTick != this.world.getTime()) { -+ if (!this.warnedAboutDesync) { -+ this.warnedAboutDesync = true; -+ MinecraftServer.LOGGER.error("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); -+ MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); -+ } -+ } -+ } -+ -+ @Override -+ public void tick() { -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); -+ -+ this.world.getMethodProfiler().enter("cleaning"); -+ this.timingCleanup.startTiming(); -+ -+ this.prepare(); -+ -+ // this must be done here in case something schedules in the tick code -+ this.shortScheduled[this.shortScheduledIndex].clear(); -+ this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); -+ -+ this.timingCleanup.stopTiming(); -+ this.world.getMethodProfiler().exitEnter("ticking"); -+ this.timingTicking.startTiming(); -+ -+ for (final NextTickListEntry toTick : this.toTickThisTick) { -+ if (toTick.tickState != STATE_PENDING_TICK) { -+ // onTickEnd gets called at end of tick -+ continue; -+ } -+ try { -+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { -+ toTick.tickState = STATE_TICKING; -+ this.tickFunction.accept(toTick); -+ if (toTick.tickState == STATE_TICKING) { -+ toTick.tickState = STATE_TICKED; -+ } // else it's STATE_CANCELLED_TICK -+ } else { -+ // re-schedule eventually -+ toTick.tickState = STATE_SCHEDULED; -+ this.addToNotTickingReady(toTick); -+ } -+ } catch (final Throwable thr) { -+ // start copy from TickListServer // TODO check on update -+ CrashReport crashreport = CrashReport.a(thr, "Exception while ticking"); -+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being ticked"); -+ -+ CrashReportSystemDetails.a(crashreportsystemdetails, toTick.getPosition(), (IBlockData) null); -+ throw new ReportedException(crashreport); -+ // end copy from TickListServer -+ } -+ } -+ -+ this.timingTicking.stopTiming(); -+ this.world.getMethodProfiler().exit(); -+ this.timingFinished.startTiming(); -+ -+ // finished ticking, actual cleanup time -+ for (int i = 0, len = this.toTickThisTick.size(); i < len; ++i) { -+ final NextTickListEntry entry = this.toTickThisTick.poll(); -+ if (entry.tickState != STATE_SCHEDULED) { -+ // some entries get re-scheduled due to their chunk not being loaded/at correct status, so do not -+ // call onTickEnd for them -+ this.onTickEnd(entry); -+ } -+ } -+ -+ this.timingFinished.stopTiming(); -+ } -+ -+ private void onTickEnd(final NextTickListEntry entry) { -+ if (entry.tickState == STATE_CANCELLED_TICK) { -+ return; -+ } -+ entry.tickState = STATE_UNSCHEDULED; -+ -+ final BlockPosition pos = entry.getPosition(); -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); -+ -+ if (currentEntries.size() == 1) { -+ // it should contain our entry -+ this.entriesByBlock.remove(blockKey); -+ } else { -+ // it's more likely that this entry is at the start of the list than the end -+ for (int i = 0, len = currentEntries.size(); i < len; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ if (currentEntry == entry) { -+ currentEntries.remove(i); -+ break; -+ } -+ } -+ } -+ -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); -+ -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); -+ -+ set.remove(entry); -+ -+ if (set.isEmpty()) { -+ this.entriesByChunk.remove(chunkKey); -+ } -+ -+ // already removed from longScheduled or shortScheduled -+ } -+ -+ @Override -+ public boolean isPendingTickThisTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final NextTickListEntry entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public boolean isScheduledForTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); -+ -+ if (entries == null) { -+ return false; -+ } -+ -+ for (int i = 0, size = entries.size(); i < size; ++i) { -+ final NextTickListEntry entry = entries.get(i); -+ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ @Override -+ public void schedule(BlockPosition blockPosition, T t, int i, TickListPriority tickListPriority) { -+ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority); -+ } -+ -+ public void schedule(final NextTickListEntry entry) { -+ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority()); -+ } -+ -+ public void schedule(final BlockPosition pos, final T data, final long targetTick, final TickListPriority priority) { -+ final NextTickListEntry entry = new NextTickListEntry<>(pos, data, targetTick, priority); -+ if (this.excludeFromScheduling.test(entry.getData())) { -+ return; -+ } -+ -+ if (WARN_ON_EXCESSIVE_DELAY) { -+ final long delay = entry.getTargetTick() - this.currentTick; -+ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { -+ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); -+ } -+ } -+ -+ final long blockKey = MCUtil.getBlockKey(pos); -+ -+ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); -+ -+ if (currentEntries.isEmpty()) { -+ currentEntries.add(entry); -+ } else { -+ for (int i = 0, size = currentEntries.size(); i < size; ++i) { -+ final NextTickListEntry currentEntry = currentEntries.get(i); -+ -+ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending) -+ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) { -+ // can't add -+ return; -+ } -+ } -+ currentEntries.add(entry); -+ } -+ -+ entry.tickState = STATE_SCHEDULED; -+ -+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { -+ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); -+ }).add(entry); -+ -+ this.addToSchedule(entry); -+ } -+ -+ public void scheduleAll(final Iterator> iterator) { -+ while (iterator.hasNext()) { -+ this.schedule(iterator.next()); -+ } -+ } -+ -+ // this is not the standard interception calculation, but it's the one vanilla uses -+ // i.e the y value is ignored? the x, z calc isn't correct? -+ // however for the copy op they use the correct intersection, after using this one of course... -+ private static boolean isBlockInSortof(final StructureBoundingBox boundingBox, final BlockPosition pos) { -+ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ(); -+ } -+ -+ @Override -+ public List> getEntriesInBoundingBox(final StructureBoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { -+ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above -+ } -+ -+ final int lowerChunkX = structureboundingbox.getMinX() >> 4; -+ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive -+ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4; -+ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive -+ -+ final int xChunksLength = (upperChunkX - lowerChunkX + 1); -+ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1); -+ -+ final ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; -+ -+ final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); -+ int totalEntries = 0; -+ for (int currChunkX = lowerChunkX; currChunkX <= upperChunkX; ++currChunkX) { -+ for (int currChunkZ = lowerChunkZ; currChunkZ <= upperChunkZ; ++currChunkZ) { -+ // todo optimize -+ //final int index = (currChunkX - lowerChunkX) + xChunksLength * (currChunkZ - lowerChunkZ); -+ final int index = offset + currChunkX + xChunksLength * currChunkZ; -+ final ObjectRBTreeSet> set = containingChunks[index] = this.entriesByChunk.get(MCUtil.getCoordinateKey(currChunkX, currChunkZ)); -+ if (set != null) { -+ totalEntries += set.size(); -+ } -+ } -+ } -+ -+ final List> ret = new ArrayList<>(totalEntries); -+ -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ MCUtil.mergeSortedSets((NextTickListEntry entry) -> { -+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { -+ return; -+ } -+ final int tickState = entry.tickState; -+ if ((tickState & matchOne) == 0) { -+ return; -+ } -+ -+ ret.add(entry); -+ return; -+ }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); -+ -+ if (removeReturned) { -+ for (NextTickListEntry entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); -+ Iterator> iterator = list.iterator(); -+ -+ while (iterator.hasNext()) { -+ NextTickListEntry nextticklistentry = iterator.next(); -+ -+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { -+ BlockPosition blockposition1 = nextticklistentry.getPosition().add(blockposition); -+ T t0 = nextticklistentry.getData(); -+ -+ this.schedule(new NextTickListEntry<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); -+ } -+ } -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public List> getEntriesInChunk(ChunkCoordIntPair chunkPos, boolean removeReturned, boolean excludeTicked) { -+ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks -+ // not at ticking status, and ticking status requires neighbours loaded -+ // so with this method we will reduce scheduler churning -+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); -+ -+ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); -+ -+ if (entries == null) { -+ return Collections.emptyList(); -+ } -+ -+ final List> ret = new ArrayList<>(entries.size()); -+ -+ for (NextTickListEntry entry : entries) { -+ if ((entry.tickState & matchOne) == 0) { -+ continue; -+ } -+ ret.add(entry); -+ } -+ -+ if (removeReturned) { -+ for (NextTickListEntry entry : ret) { -+ this.removeEntry(entry); -+ } -+ } -+ -+ return ret; -+ } -+ -+ @Override -+ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { -+ // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); -+ -+ return TickListServer.serialize(this.getMinecraftKeyFrom, list, this.currentTick); -+ // end copy from TickListServer -+ } -+ -+ @Override -+ public int getTotalScheduledEntries() { -+ // good thing this is only used in debug reports // TODO check on update -+ int ret = 0; -+ -+ for (NextTickListEntry entry : this.longScheduled) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ -+ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { -+ ArrayList> list = iterator.next().getValue(); -+ -+ for (NextTickListEntry entry : list) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ -+ for (TickListServerInterval interval : this.shortScheduled) { -+ for (Iterable> set : interval.byPriority) { -+ for (NextTickListEntry entry : set) { -+ if (entry.tickState == STATE_SCHEDULED) { -+ ++ret; -+ } -+ } -+ } -+ } -+ -+ return ret; -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.server.ticklist; -+ -+import com.destroystokyo.paper.util.set.LinkedSortedSet; -+import java.util.Comparator; -+import net.minecraft.world.level.NextTickListEntry; -+import net.minecraft.world.level.TickListPriority; -+ -+// represents a set of entries to tick at a specified time -+public final class TickListServerInterval { -+ -+ public static final int TOTAL_PRIORITIES = TickListPriority.values().length; -+ public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { -+ return Long.compare(entry1.getId(), entry2.getId()); -+ }; -+ public static final Comparator> ENTRY_COMPARATOR = (Comparator)NextTickListEntry.comparator(); -+ -+ // we do not record the interval, this class is meant to be used on a ring buffer -+ -+ // inlined enum map for TickListPriority -+ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; -+ -+ { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i] = new LinkedSortedSet<>(ENTRY_COMPARATOR_BY_ID); -+ } -+ } -+ -+ public void addEntryLast(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); -+ } -+ -+ public void addEntryFirst(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); -+ } -+ -+ public void clear() { -+ for (int i = 0, len = this.byPriority.length; i < len; ++i) { -+ this.byPriority[i].clear(); // O(1) clear -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.set; -+ -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+public final class LinkedSortedSet implements Iterable { -+ -+ public final Comparator comparator; -+ -+ protected Link head; -+ protected Link tail; -+ -+ public LinkedSortedSet() { -+ this((Comparator)Comparator.naturalOrder()); -+ } -+ -+ public LinkedSortedSet(final Comparator comparator) { -+ this.comparator = comparator; -+ } -+ -+ public void clear() { -+ this.head = this.tail = null; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator() { -+ -+ Link next = LinkedSortedSet.this.head; -+ -+ @Override -+ public boolean hasNext() { -+ return this.next != null; -+ } -+ -+ @Override -+ public E next() { -+ final Link next = this.next; -+ if (next == null) { -+ throw new NoSuchElementException(); -+ } -+ this.next = next.next; -+ return next.element; -+ } -+ }; -+ } -+ -+ public boolean addLast(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.tail; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) < 0) { -+ Link prev = curr; -+ curr = curr.prev; -+ if (curr != null) { -+ continue; -+ } -+ this.head = prev.prev = new Link<>(element, null, prev); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert after curr -+ final Link next = curr.next; -+ final Link insert = new Link<>(element, curr, next); -+ curr.next = insert; -+ -+ if (next == null) { -+ this.tail = insert; -+ } else { -+ next.prev = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ public boolean addFirst(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.head; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) > 0) { -+ Link prev = curr; -+ curr = curr.next; -+ if (curr != null) { -+ continue; -+ } -+ this.tail = prev.next = new Link<>(element, prev, null); -+ return true; -+ } -+ -+ if (compare != 0) { -+ // insert before curr -+ final Link prev = curr.prev; -+ final Link insert = new Link<>(element, prev, curr); -+ curr.prev = insert; -+ -+ if (prev == null) { -+ this.head = insert; -+ } else { -+ prev.next = insert; -+ } -+ return true; -+ } -+ -+ return false; -+ } else { -+ this.head = this.tail = new Link<>(element); -+ return true; -+ } -+ } -+ -+ protected static final class Link { -+ public E element; -+ public Link prev; -+ public Link next; -+ -+ public Link() {} -+ -+ public Link(final E element) { -+ this.element = element; -+ } -+ -+ public Link(final E element, final Link prev, final Link next) { -+ this.element = element; -+ this.prev = prev; -+ this.next = next; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); - } - -+ public final BlockPosition add(BaseBlockPosition baseblockposition) { return this.a(baseblockposition); } // Paper - OBFHELPER - public BlockPosition a(BaseBlockPosition baseblockposition) { - return this.b(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ import net.minecraft.SystemUtils; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.SectionPosition; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.MathHelper; - import net.minecraft.util.profiling.GameProfilerFiller; -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ public final boolean isTickingReadyMainThread(BlockPosition pos) { -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(pos)); -+ return chunk != null && chunk.isTickingReady(); -+ } -+ // Paper end - rewrite ticklistserver -+ - public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier supplier) { - this.world = worldserver; - this.serverThreadQueue = new ChunkProviderServer.a(worldserver); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - PlayerChunk.this.isTickingReady = true; - - -- -+ // Paper start - rewrite ticklistserver -+ PlayerChunk.this.chunkMap.world.onChunkSetTicking(PlayerChunk.this.location.x, PlayerChunk.this.location.z); -+ // Paper end - rewrite ticklistserver - - } - }); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - // Paper end - -+ // Paper start - rewrite ticklistserver -+ void onChunkSetTicking(int chunkX, int chunkZ) { -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListBlock).onChunkSetTicking(chunkX, chunkZ); -+ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.nextTickListFluid).onChunkSetTicking(chunkX, chunkZ); -+ } -+ } -+ // Paper end - rewrite ticklistserver -+ - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - convertable = convertable_conversionsession; - uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile()); - // CraftBukkit end -- this.nextTickListBlock = new TickListServer<>(this, (block) -> { -- return block == null || block.getBlockData().isAir(); -- }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -- this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { -- return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { -+ this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { -+ return block == null || block.getBlockData().isAir(); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -+ this.nextTickListFluid = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ } else { -+ this.nextTickListBlock = new TickListServer<>(this, (block) -> { -+ return block == null || block.getBlockData().isAir(); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings -+ this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { -+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings -+ } - this.navigators = Sets.newHashSet(); - this.L = new ObjectLinkedOpenHashSet(); - this.Q = flag1; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (this.Q) { - long i = this.worldData.getTime() + 1L; - -- this.worldDataServer.setTime(i); -+ this.worldDataServer.setTime(i); // Paper - diff on change, we want the below to be ran right after this -+ this.nextTickListBlock.nextTick(); // Paper -+ this.nextTickListFluid.nextTick(); // Paper - this.worldDataServer.u().a(this.server, i); - if (this.worldData.q().getBoolean(GameRules.DO_DAYLIGHT_CYCLE)) { - this.setDayTime(this.worldData.getDayTime() + 1L); -diff --git a/src/main/java/net/minecraft/world/level/NextTickListEntry.java b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/NextTickListEntry.java -+++ b/src/main/java/net/minecraft/world/level/NextTickListEntry.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - public class NextTickListEntry { - - private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading -- private final T e; -- public final BlockPosition a; -- public final long b; -- public final TickListPriority c; -- private final long f; -+ private final T e; public final T getData() { return this.e; } // Paper - OBFHELPER -+ public final BlockPosition a; public final BlockPosition getPosition() { return this.a; } // Paper - OBFHELPER -+ public final long b; public final long getTargetTick() { return this.b; } // Paper - OBFHELPER -+ public final TickListPriority c; public final TickListPriority getPriority() { return this.c; } // Paper - OBFHELPER -+ private final long f; public final long getId() { return this.f; } // Paper - OBFHELPER -+ private final int hash; // Paper -+ public int tickState; // Paper - - public NextTickListEntry(BlockPosition blockposition, T t0) { - this(blockposition, t0, 0L, TickListPriority.NORMAL); -@@ -0,0 +0,0 @@ public class NextTickListEntry { - this.e = t0; - this.b = i; - this.c = ticklistpriority; -+ this.hash = this.computeHash(); // Paper - } - - public boolean equals(Object object) { -@@ -0,0 +0,0 @@ public class NextTickListEntry { - } - } - -+ // Paper start - optimize hashcode -+ @Override - public int hashCode() { -+ return this.hash; -+ } -+ public final int computeHash() { -+ // Paper end - optimize hashcode - return this.a.hashCode(); - } - -- public static Comparator a() { // Paper - decompile fix -- return Comparator.comparingLong((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).b; // Paper - decompile fix -- }).thenComparing((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).c; // Paper - decompile fix -- }).thenComparingLong((nextticklistentry) -> { -- return ((NextTickListEntry) nextticklistentry).f; // Paper - decompile fix -- }); -+ // Paper start - let's not use more functional code for no reason. -+ public static Comparator comparator() { return NextTickListEntry.a(); } // Paper - OBFHELPER -+ public static Comparator a() { -+ return (Comparator)(Comparator)(NextTickListEntry nextticklistentry, NextTickListEntry nextticklistentry1) -> { -+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); -+ -+ if (i != 0) { -+ return i; -+ } else { -+ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority()); -+ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); -+ } -+ }; - } -+ // Paper end - let's not use more functional code for no reason. - - public String toString() { - return this.e + ": " + this.a + ", " + this.b + ", " + this.c + ", " + this.f; -diff --git a/src/main/java/net/minecraft/world/level/TickListChunk.java b/src/main/java/net/minecraft/world/level/TickListChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/TickListChunk.java -+++ b/src/main/java/net/minecraft/world/level/TickListChunk.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; - - public class TickListChunk implements TickList { - -@@ -0,0 +0,0 @@ public class TickListChunk implements TickList { - return nbttaglist; - } - -+ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries -+ - public static TickListChunk a(NBTTagList nbttaglist, Function function, Function function1) { - List> list = Lists.newArrayList(); - -@@ -0,0 +0,0 @@ public class TickListChunk implements TickList { - if (t0 != null) { - BlockPosition blockposition = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z")); - -- list.add(new TickListChunk.a<>(t0, blockposition, nbttagcompound.getInt("t"), TickListPriority.a(nbttagcompound.getInt("p")))); -+ // Paper start - clean up broken entries -+ int delay = nbttagcompound.getInt("t"); -+ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { -+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); -+ continue; -+ } -+ list.add(new TickListChunk.a<>(t0, blockposition, delay, TickListPriority.a(nbttagcompound.getInt("p")))); -+ // Paper end - clean up broken entries - } - } - -diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/TickListServer.java -+++ b/src/main/java/net/minecraft/world/level/TickListServer.java -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - private final co.aikar.timings.Timing timingTicking; // Paper - // Paper end - -+ // Paper start -+ public void nextTick() {} -+ // Paper end -+ - public void b() { -+ // Paper start - allow overriding -+ this.tick(); -+ } -+ public void tick() { -+ // Paper end - int i = this.nextTickList.size(); - - if (false) { // CraftBukkit -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - - @Override - public boolean b(BlockPosition blockposition, T t0) { -+ // Paper start - allow overriding -+ return this.isPendingTickThisTick(blockposition, t0); -+ } -+ public boolean isPendingTickThisTick(BlockPosition blockposition, T t0) { -+ // Paper end - return this.f.contains(new NextTickListEntry<>(blockposition, t0)); - } - - public List> a(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper start - allow overriding -+ return this.getEntriesInChunk(chunkcoordintpair, flag, flag1); -+ } -+ public List> getEntriesInChunk(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { -+ // Paper end - int i = (chunkcoordintpair.x << 4) - 2; - int j = i + 16 + 2; - int k = (chunkcoordintpair.z << 4) - 2; -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - } - - public List> a(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper start - allow overriding -+ return this.getEntriesInBoundingBox(structureboundingbox, flag, flag1); -+ } -+ public List> getEntriesInBoundingBox(StructureBoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper end - List> list = this.a((List) null, this.nextTickList, structureboundingbox, flag); - - if (flag && list != null) { -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - } - - public void a(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // Paper start - allow overriding -+ this.copy(structureboundingbox, blockposition); -+ } -+ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { -+ // Paper end - List> list = this.a(structureboundingbox, false, false); - Iterator iterator = list.iterator(); - -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - } - - public NBTTagList a(ChunkCoordIntPair chunkcoordintpair) { -+ // Paper start - allow overriding -+ return this.serialize(chunkcoordintpair); -+ } -+ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { -+ // Paper end - List> list = this.a(chunkcoordintpair, false, true); - - return a(this.b, list, this.e.getTime()); - } - -+ public static NBTTagList serialize(Function function, Iterable> iterable, long i) { return TickListServer.a(function, iterable, i); } // Paper - OBFHELPER - private static NBTTagList a(Function function, Iterable> iterable, long i) { - NBTTagList nbttaglist = new NBTTagList(); - Iterator iterator = iterable.iterator(); -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - - @Override - public boolean a(BlockPosition blockposition, T t0) { -+ // Paper start - allow overriding -+ return this.isScheduledForTick(blockposition, t0); -+ } -+ public boolean isScheduledForTick(BlockPosition blockposition, T t0) { -+ // Paper end - return this.nextTickListHash.contains(new NextTickListEntry<>(blockposition, t0)); - } - - @Override - public void a(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { -+ // Paper start - allow overriding -+ this.schedule(blockposition, t0, i, ticklistpriority); -+ } -+ public void schedule(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { -+ // Paper end - if (!this.a.test(t0)) { - this.a(new NextTickListEntry<>(blockposition, t0, (long) i + this.e.getTime(), ticklistpriority)); - } -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - } - - public int a() { -+ // Paper start - allow overriding -+ return this.getTotalScheduledEntries(); -+ } -+ public int getTotalScheduledEntries() { -+ // Paper end - return this.nextTickListHash.size(); - } - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureBoundingBox.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagIntArray; - - public class StructureBoundingBox { - -- public int a; -- public int b; -- public int c; -- public int d; -- public int e; -- public int f; -+ public int a; public final int getMinX() { return this.a; } // Paper - OBFHELPER -+ public int b; public final int getMinY() { return this.b; } // Paper - OBFHELPER -+ public int c; public final int getMinZ() { return this.c; } // Paper - OBFHELPER -+ public int d; public final int getMaxX() { return this.d; } // Paper - OBFHELPER -+ public int e; public final int getMaxY() { return this.e; } // Paper - OBFHELPER -+ public int f; public final int getMaxZ() { return this.f; } // Paper - OBFHELPER - - public StructureBoundingBox() {} - -@@ -0,0 +0,0 @@ public class StructureBoundingBox { - this.e = 512; - } - -+ public final boolean intersects(StructureBoundingBox boundingBox) { return this.b(boundingBox); } // Paper - OBFHELPER - public boolean b(StructureBoundingBox structureboundingbox) { - return this.d >= structureboundingbox.a && this.a <= structureboundingbox.d && this.f >= structureboundingbox.c && this.c <= structureboundingbox.f && this.e >= structureboundingbox.b && this.b <= structureboundingbox.e; - } -@@ -0,0 +0,0 @@ public class StructureBoundingBox { - this.a(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public final boolean hasPoint(BaseBlockPosition baseblockposition) { return this.b(baseblockposition); } // Paper - OBFHELPER - public boolean b(BaseBlockPosition baseblockposition) { - return baseblockposition.getX() >= this.a && baseblockposition.getX() <= this.d && baseblockposition.getZ() >= this.c && baseblockposition.getZ() <= this.f && baseblockposition.getY() >= this.b && baseblockposition.getY() <= this.e; - } diff --git a/Spigot-Server-Patches/Optimise-getChunkAt-calls-for-loaded-chunks.patch b/Spigot-Server-Patches/Optimise-getChunkAt-calls-for-loaded-chunks.patch deleted file mode 100644 index fbfd592126..0000000000 --- a/Spigot-Server-Patches/Optimise-getChunkAt-calls-for-loaded-chunks.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Jan 2020 17:04:35 -0800 -Subject: [PATCH] Optimise getChunkAt calls for loaded chunks - -bypass the need to get a player chunk, then get the either, -then unwrap it... - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - return this.getChunkAt(i, j, chunkstatus, flag); - }, this.serverThreadQueue).join(); - } else { -+ // Paper start - optimise for loaded chunks -+ Chunk ifLoaded = this.getChunkAtIfLoadedMainThread(i, j); -+ if (ifLoaded != null) { -+ return ifLoaded; -+ } -+ // Paper end - GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler(); - - gameprofilerfiller.c("getChunk"); -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - if (Thread.currentThread() != this.serverThread) { - return null; - } else { -- this.world.getMethodProfiler().c("getChunkNow"); -- long k = ChunkCoordIntPair.pair(i, j); -- -- for (int l = 0; l < 4; ++l) { -- if (k == this.cachePos[l] && this.cacheStatus[l] == ChunkStatus.FULL) { -- IChunkAccess ichunkaccess = this.cacheChunk[l]; -- -- return ichunkaccess instanceof Chunk ? (Chunk) ichunkaccess : null; -- } -- } -- -- PlayerChunk playerchunk = this.getChunk(k); -- -- if (playerchunk == null) { -- return null; -- } else { -- Either either = (Either) playerchunk.b(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error -- -- if (either == null) { -- return null; -- } else { -- IChunkAccess ichunkaccess1 = (IChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error -- -- if (ichunkaccess1 != null) { -- this.a(k, ichunkaccess1, ChunkStatus.FULL); -- if (ichunkaccess1 instanceof Chunk) { -- return (Chunk) ichunkaccess1; -- } -- } -- -- return null; -- } -- } -+ return this.getChunkAtIfLoadedMainThread(i, j); // Paper - optimise for loaded chunks - } - } - diff --git a/Spigot-Server-Patches/Optimise-getType-calls.patch b/Spigot-Server-Patches/Optimise-getType-calls.patch deleted file mode 100644 index d9da966e5b..0000000000 --- a/Spigot-Server-Patches/Optimise-getType-calls.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 3 Jun 2020 11:37:13 -0700 -Subject: [PATCH] Optimise getType calls - -Remove the map lookup for converting from Block->Bukkit Material - -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockData.java -@@ -0,0 +0,0 @@ public class IBlockData extends BlockBase.BlockData { - - public static final Codec b = a((Codec) IRegistry.BLOCK, Block::getBlockData).stable(); - -+ -+ // Paper start - optimise getType calls -+ org.bukkit.Material cachedMaterial; -+ -+ public final org.bukkit.Material getBukkitMaterial() { -+ if (this.cachedMaterial == null) { -+ this.cachedMaterial = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(this.getBlock()); -+ } -+ -+ return this.cachedMaterial; -+ } -+ // Paper end - optimise getType calls -+ - public IBlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(block, immutablemap, mapcodec); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java -@@ -0,0 +0,0 @@ public class CraftChunkSnapshot implements ChunkSnapshot { - public Material getBlockType(int x, int y, int z) { - CraftChunk.validateChunkCoordinates(x, y, z); - -- return CraftMagicNumbers.getMaterial(blockids[y >> 4].a(x, y & 0xF, z).getBlock()); -+ return blockids[y >> 4].a(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -@@ -0,0 +0,0 @@ public class CraftBlock implements Block { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(world.getType(position).getBlock()); -+ return world.getType(position).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -@@ -0,0 +0,0 @@ public class CraftBlockState implements BlockState { - - @Override - public Material getType() { -- return CraftMagicNumbers.getMaterial(data.getBlock()); -+ return data.getBukkitMaterial(); // Paper - optimise getType calls - } - - public void setFlag(int flag) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -0,0 +0,0 @@ public class CraftBlockData implements BlockData { - - @Override - public Material getMaterial() { -- return CraftMagicNumbers.getMaterial(state.getBlock()); -+ return state.getBukkitMaterial(); // Paper - optimise getType calls - } - - public IBlockData getState() { -diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java -@@ -0,0 +0,0 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { - - @Override - public Material getType(int x, int y, int z) { -- return CraftMagicNumbers.getMaterial(getTypeId(x, y, z).getBlock()); -+ return getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls - } - - @Override diff --git a/Spigot-Server-Patches/Optimise-random-block-ticking.patch b/Spigot-Server-Patches/Optimise-random-block-ticking.patch deleted file mode 100644 index d6ca4bae21..0000000000 --- a/Spigot-Server-Patches/Optimise-random-block-ticking.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Jan 2020 21:28:00 -0800 -Subject: [PATCH] Optimise random block ticking - -Massive performance improvement for random block ticking. -The performance increase comes from the fact that the vast -majority of attempted block ticks (~95% in my testing) fail -because the randomly selected block is not tickable. - -Now only tickable blocks are targeted, however this means that -the maximum number of block ticks occurs per chunk. However, -not all chunks are going to be targeted. The percent chance -of a chunk being targeted is based on how many tickable blocks -are in the chunk. -This means that while block ticks are spread out less, the -total number of blocks ticked per world tick remains the same. -Therefore, the chance of a random tickable block being ticked -remains the same. - -diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.math; -+ -+import java.util.Random; -+ -+public final class ThreadUnsafeRandom extends Random { -+ -+ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them. -+ private static final long multiplier = 0x5DEECE66DL; -+ private static final long addend = 0xBL; -+ private static final long mask = (1L << 48) - 1; -+ -+ private static long initialScramble(long seed) { -+ return (seed ^ multiplier) & mask; -+ } -+ -+ private long seed; -+ -+ @Override -+ public void setSeed(long seed) { -+ // note: called by Random constructor -+ this.seed = initialScramble(seed); -+ } -+ -+ @Override -+ protected int next(int bits) { -+ // avoid the expensive CAS logic used by superclass -+ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits)); -+ } -+ -+ // Taken from -+ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ -+ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c -+ // Original license is public domain -+ public static int fastRandomBounded(final long randomInteger, final long limit) { -+ // randomInteger must be [0, pow(2, 32)) -+ // limit must be [0, pow(2, 32)) -+ return (int)((randomInteger * limit) >>> 32); -+ } -+ -+ @Override -+ public int nextInt(int bound) { -+ // yes this breaks random's spec -+ // however there's nothing that uses this class that relies on it -+ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); -+ } -+} -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); - } - -+ public final BlockPosition.MutableBlockPosition setValues(final BaseBlockPosition baseblockposition) { return this.g(baseblockposition); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition g(BaseBlockPosition baseblockposition) { - return this.d(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }); - } - -- public void a(Chunk chunk, int i) { -+ // Paper start - optimise random block ticking -+ private final BlockPosition.MutableBlockPosition chunkTickMutablePosition = new BlockPosition.MutableBlockPosition(); -+ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom(); -+ // Paper end -+ -+ public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper - ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); - boolean flag = this.isRaining(); - int j = chunkcoordintpair.d(); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); - - gameprofilerfiller.enter("thunder"); -- BlockPosition blockposition; -+ final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change - - if (!this.paperConfig.disableThunder && flag && this.W() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder -- blockposition = this.a(this.a(j, 0, k, 15)); -+ blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper - if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); - boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("iceandsnow"); -- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow -- blockposition = this.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, this.a(j, 0, k, 15)); -- BlockPosition blockposition1 = blockposition.down(); -+ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking -+ // Paper start - optimise chunk ticking -+ this.getRandomBlockPosition(j, 0, k, 15, blockposition); -+ int normalY = chunk.getHighestBlockY(HeightMap.Type.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15); -+ int downY = normalY - 1; -+ blockposition.setY(normalY); -+ // Paper end - BiomeBase biomebase = this.getBiome(blockposition); - -- if (biomebase.a(this, blockposition1)) { -- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.getBlockData(), null); // CraftBukkit -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (biomebase.a(this, blockposition)) { -+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.getBlockData(), null); // CraftBukkit -+ // Paper end - } - -+ blockposition.setY(normalY); // Paper - if (flag && biomebase.b(this, blockposition)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.getBlockData(), null); // CraftBukkit - } - -- if (flag && this.getBiome(blockposition1).c() == BiomeBase.Precipitation.RAIN) { -- this.getType(blockposition1).getBlock().c((World) this, blockposition1); -+ // Paper start - optimise chunk ticking -+ blockposition.setY(downY); -+ if (flag && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { -+ chunk.getType(blockposition).getBlock().c((World) this, blockposition); -+ // Paper end - } - } - -- gameprofilerfiller.exitEnter("tickBlocks"); -- timings.chunkTicksBlocks.startTiming(); // Paper -+ // Paper start - optimise random block ticking -+ gameprofilerfiller.exit(); - if (i > 0) { -- ChunkSection[] achunksection = chunk.getSections(); -- int l = achunksection.length; -+ gameprofilerfiller.enter("randomTick"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - -- for (int i1 = 0; i1 < l; ++i1) { -- ChunkSection chunksection = achunksection[i1]; -+ ChunkSection[] sections = chunk.getSections(); - -- if (chunksection != Chunk.a && chunksection.d()) { -- int j1 = chunksection.getYPosition(); -+ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) { -+ ChunkSection section = sections[sectionIndex]; -+ if (section == null || section.tickingList.size() == 0) { -+ continue; -+ } - -- for (int k1 = 0; k1 < i; ++k1) { -- BlockPosition blockposition2 = this.a(j, j1, k, 15); -+ int yPos = sectionIndex << 4; - -- gameprofilerfiller.enter("randomTick"); -- IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k); -+ for (int a = 0; a < randomTickSpeed; ++a) { -+ int tickingBlocks = section.tickingList.size(); -+ int index = this.randomTickRandom.nextInt(16 * 16 * 16); -+ if (index >= tickingBlocks) { -+ continue; -+ } - -- if (iblockdata.isTicking()) { -- iblockdata.b(this, blockposition2, this.random); -- } -+ long raw = section.tickingList.getRaw(index); -+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); -+ int randomX = location & 15; -+ int randomY = ((location >>> (4 + 4)) & 255) | yPos; -+ int randomZ = (location >>> 4) & 15; - -- Fluid fluid = iblockdata.getFluid(); -+ BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); -+ IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); - -- if (fluid.f()) { -- fluid.b(this, blockposition2, this.random); -- } -+ iblockdata.b(this, blockposition2, this.randomTickRandom); - -- gameprofilerfiller.exit(); -- } -+ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method. -+ // TODO CHECK ON UPDATE - } - } -+ gameprofilerfiller.exit(); -+ timings.chunkTicksBlocks.stopTiming(); // Paper -+ // Paper end - } -- timings.chunkTicksBlocks.stopTiming(); // Paper -- gameprofilerfiller.exit(); - } - - protected BlockPosition a(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -0,0 +0,0 @@ public class DataBits { - } - - } -+ -+ // Paper start -+ public final void forEach(DataBitConsumer consumer) { -+ int i = 0; -+ long[] along = this.b; -+ int j = along.length; -+ -+ for (int k = 0; k < j; ++k) { -+ long l = along[k]; -+ -+ for (int i1 = 0; i1 < this.f; ++i1) { -+ consumer.accept(i, (int) (l & this.d)); -+ l >>= this.c; -+ ++i; -+ if (i >= this.e) { -+ return; -+ } -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface DataBitConsumer { -+ -+ void accept(int location, int data); -+ -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { - } - - public void setHomePos(BlockPosition blockposition) { -- this.datawatcher.set(EntityTurtle.bp, blockposition); -+ this.datawatcher.set(EntityTurtle.bp, blockposition.immutableCopy()); // Paper - called with mutablepos... - } - - public BlockPosition getHomePos() { // Paper - public -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public abstract ITagRegistry p(); - - public BlockPosition a(int i, int j, int k, int l) { -+ // Paper start - allow use of mutable pos -+ BlockPosition.MutableBlockPosition ret = new BlockPosition.MutableBlockPosition(); -+ this.getRandomBlockPosition(i, j, k, l, ret); -+ return ret.immutableCopy(); -+ } -+ public final BlockPosition.MutableBlockPosition getRandomBlockPosition(int i, int j, int k, int l, BlockPosition.MutableBlockPosition out) { -+ // Paper end - this.n = this.n * 3 + 1013904223; - int i1 = this.n >> 2; - -- return new BlockPosition(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); -+ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call -+ return out; // Paper - } - - public boolean isSavingDisabled() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - this.entities.remove(entity); // Paper - } - -- @Override -- public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { -+ public final int getHighestBlockY(HeightMap.Type heightmap_type, int i, int j) { return this.getHighestBlock(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 -+ @Override public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { // Paper - return ((HeightMap) this.heightMap.get(heightmap_type)).a(i & 15, j & 15) - 1; - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.material.Fluid; - public class ChunkSection { - - public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); -- private final int yPos; -+ final int yPos; // Paper - private -> package-private - short nonEmptyBlockCount; // Paper - package-private -- private short tickingBlockCount; -+ short tickingBlockCount; // Paper - private -> package-private - private short e; - final DataPaletteBlock blockIds; // Paper - package-private - -+ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper -+ - // Paper start - Anti-Xray - Add parameters - @Deprecated public ChunkSection(int i) { this(i, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere - public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { -@@ -0,0 +0,0 @@ public class ChunkSection { - --this.nonEmptyBlockCount; - if (iblockdata1.isTicking()) { - --this.tickingBlockCount; -+ // Paper start -+ this.tickingList.remove(i, j, k); -+ // Paper end - } - } - -@@ -0,0 +0,0 @@ public class ChunkSection { - ++this.nonEmptyBlockCount; - if (iblockdata.isTicking()) { - ++this.tickingBlockCount; -+ // Paper start -+ this.tickingList.add(i, j, k, iblockdata); -+ // Paper end - } - } - -@@ -0,0 +0,0 @@ public class ChunkSection { - } - - public void recalcBlockCounts() { -+ // Paper start -+ this.tickingList.clear(); -+ // Paper end - this.nonEmptyBlockCount = 0; - this.tickingBlockCount = 0; - this.e = 0; -- this.blockIds.a((iblockdata, i) -> { -+ this.blockIds.forEachLocation((iblockdata, location) -> { // Paper - Fluid fluid = iblockdata.getFluid(); - - if (!iblockdata.isAir()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (iblockdata.isTicking()) { -- this.tickingBlockCount = (short) (this.tickingBlockCount + i); -+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); -+ // Paper start -+ this.tickingList.add(location, iblockdata); -+ // Paper end - } - } - - if (!fluid.isEmpty()) { -- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); - if (fluid.f()) { -- this.e = (short) (this.e + i); -+ this.e = (short) (this.e + 1); - } - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - }); - } - -+ // Paper start -+ public void forEachLocation(DataPaletteBlock.a datapaletteblock_a) { -+ this.getDataBits().forEach((int location, int data) -> { -+ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location); -+ }); -+ } -+ // Paper end -+ - @FunctionalInterface - public interface a { - diff --git a/Spigot-Server-Patches/Optimise-removeQueue.patch b/Spigot-Server-Patches/Optimise-removeQueue.patch deleted file mode 100644 index 9f7be558e9..0000000000 --- a/Spigot-Server-Patches/Optimise-removeQueue.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Fri, 25 Nov 2016 13:22:40 +0000 -Subject: [PATCH] Optimise removeQueue - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - - } - -+ // Paper start - Cache authenticator threads -+ private static final AtomicInteger threadId = new AtomicInteger(0); -+ private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( -+ r -> new Thread(r, "User Authenticator #" + threadId.incrementAndGet()) -+ ); -+ // Paper end - // Spigot start - public void initUUID() - { -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic().getEncoded(), this.e)); - } else { - // Spigot start -- new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { -- -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - @Override - public void run() { - try { -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + i.getName(), ex); - } - } -- }.start(); -+ }); -+ // Paper end - // Spigot end - } - -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - throw new IllegalStateException("Protocol error", cryptographyexception); - } - -- Thread thread = new Thread("User Authenticator #" + LoginListener.b.incrementAndGet()) { -+ // Paper start - Cache authenticator threads -+ authenticatorPool.execute(new Runnable() { - public void run() { - GameProfile gameprofile = LoginListener.this.i; - -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - - return LoginListener.this.server.W() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; - } -- }; -- -- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LoginListener.LOGGER)); -- thread.start(); -+ }); -+ // Paper end - } - - // Spigot start diff --git a/Spigot-Server-Patches/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/Spigot-Server-Patches/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch deleted file mode 100644 index 5a4e56f189..0000000000 --- a/Spigot-Server-Patches/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:47:01 -0400 -Subject: [PATCH] Optimize Biome Mob Lookups for Mob Spawning - -Uses an EnumMap as well as a Set paired List for O(1) contains calls. - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeSettingsMobs.java -@@ -0,0 +0,0 @@ public class BiomeSettingsMobs { - }, (enumcreaturetype) -> { - return ImmutableList.of(); - })), ImmutableMap.of(), false); -+ // Paper start- decompile error workaround -+ private static class bProxy extends BiomeSettingsMobs.b { -+ private bProxy(double d0, double d1) { -+ super(d0, d1); -+ } -+ } -+ private static class cProxy extends BiomeSettingsMobs.c { -+ public cProxy(EntityTypes entitytypes, int i, int j, int k) { -+ super(entitytypes, i, j, k); -+ } -+ }; -+ // Paper end - public static final MapCodec c = RecordCodecBuilder.mapCodec((instance) -> { -- RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { -+ RecordCodecBuilder recordcodecbuilder = Codec.FLOAT.optionalFieldOf("creature_spawn_probability", 0.1F).forGetter((biomesettingsmobs) -> { // Paper - add type to builder - return biomesettingsmobs.d; - }); -- Codec codec = EnumCreatureType.g; -- Codec codec1 = BiomeSettingsMobs.c.b.listOf(); -- Logger logger = BiomeSettingsMobs.LOGGER; -+ // Paper - remove unused vars - -- logger.getClass(); -- return instance.group(recordcodecbuilder, Codec.simpleMap(codec, codec1.promotePartial(SystemUtils.a("Spawn data: ", logger::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { -+ return instance.group(recordcodecbuilder, Codec.simpleMap(EnumCreatureType.g, cProxy.b.listOf().promotePartial(SystemUtils.a("Spawn data: ", BiomeSettingsMobs.LOGGER::error)), INamable.a(EnumCreatureType.values())).fieldOf("spawners").forGetter((biomesettingsmobs) -> { // Paper - inline codec, cProxy, LOGGER - return biomesettingsmobs.e; -- }), Codec.simpleMap(IRegistry.ENTITY_TYPE, BiomeSettingsMobs.b.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { -+ }), Codec.simpleMap(IRegistry.ENTITY_TYPE, bProxy.a, IRegistry.ENTITY_TYPE).fieldOf("spawn_costs").forGetter((biomesettingsmobs) -> { // Paper - decompile error - bProxy - return biomesettingsmobs.f; - }), Codec.BOOL.fieldOf("player_spawn_friendly").orElse(false).forGetter(BiomeSettingsMobs::b)).apply(instance, BiomeSettingsMobs::new); - }); -@@ -0,0 +0,0 @@ public class BiomeSettingsMobs { - - public static class a { - -- private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(ImmutableMap.toImmutableMap((enumcreaturetype) -> { -+ // Paper start - keep track of data in a pair set to give O(1) contains calls - we have to hook removals incase plugins mess with it -+ public static class MobList extends java.util.ArrayList { -+ java.util.Set biomes = new java.util.HashSet<>(); -+ -+ @Override -+ public boolean contains(Object o) { -+ return biomes.contains(o); -+ } -+ -+ @Override -+ public boolean add(BiomeSettingsMobs.c BiomeSettingsMobs) { -+ biomes.add(BiomeSettingsMobs); -+ return super.add(BiomeSettingsMobs); -+ } -+ -+ @Override -+ public BiomeSettingsMobs.c remove(int index) { -+ BiomeSettingsMobs.c removed = super.remove(index); -+ if (removed != null) { -+ biomes.remove(removed); -+ } -+ return removed; -+ } -+ -+ @Override -+ public void clear() { -+ biomes.clear(); -+ super.clear(); -+ } -+ } -+ // use toImmutableEnumMap collector -+ private final Map> a = (Map) Stream.of(EnumCreatureType.values()).collect(Maps.toImmutableEnumMap((enumcreaturetype) -> { - return enumcreaturetype; - }, (enumcreaturetype) -> { -- return Lists.newArrayList(); -+ return new MobList(); // Use MobList instead of ArrayList - })); -+ // Paper end - private final Map, BiomeSettingsMobs.b> b = Maps.newLinkedHashMap(); - private float c = 0.1F; - private boolean d; diff --git a/Spigot-Server-Patches/Optimize-Bit-Operations-by-inlining.patch b/Spigot-Server-Patches/Optimize-Bit-Operations-by-inlining.patch deleted file mode 100644 index 4dcff244df..0000000000 --- a/Spigot-Server-Patches/Optimize-Bit-Operations-by-inlining.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 02:24:49 -0400 -Subject: [PATCH] Optimize Bit Operations by inlining - -Inline bit operations and reduce instruction count to make these hot -operations faster - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - }).stable(); - private static final Logger LOGGER = LogManager.getLogger(); - public static final BlockPosition ZERO = new BlockPosition(0, 0, 0); -- private static final int f = 1 + MathHelper.f(MathHelper.c(30000000)); -- private static final int g = BlockPosition.f; -- private static final int h = 64 - BlockPosition.f - BlockPosition.g; -- private static final long i = (1L << BlockPosition.f) - 1L; -- private static final long j = (1L << BlockPosition.h) - 1L; -- private static final long k = (1L << BlockPosition.g) - 1L; -- private static final int l = BlockPosition.h; -- private static final int m = BlockPosition.h + BlockPosition.g; -+ // Paper start - static constants -+ private static final int f = 26; -+ private static final int g = 26; -+ private static final int h = 12; -+ private static final long i = 67108863; -+ private static final long j = 4095; -+ private static final long k = 67108863; -+ private static final int l = 12; -+ private static final int m = 38; -+ // Paper end - - public BlockPosition(int i, int j, int k) { - super(i, j, k); -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - this(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); - } - -+ public static long getAdjacent(int baseX, int baseY, int baseZ, EnumDirection enumdirection) { return asLong(baseX + enumdirection.getAdjacentX(), baseY + enumdirection.getAdjacentY(), baseZ + enumdirection.getAdjacentZ()); } // Paper - public static long a(long i, EnumDirection enumdirection) { - return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); - } - - public static long a(long i, int j, int k, int l) { -- return a(b(i) + j, c(i) + k, d(i) + l); -+ return a((int) (i >> 38) + j, (int) ((i << 52) >> 52) + k, (int) ((i << 26) >> 38) + l); // Paper - simplify/inline - } - - public static int b(long i) { -- return (int) (i << 64 - BlockPosition.m - BlockPosition.f >> 64 - BlockPosition.f); -+ return (int) (i >> 38); // Paper - simplify/inline - } - - public static int c(long i) { -- return (int) (i << 64 - BlockPosition.h >> 64 - BlockPosition.h); -+ return (int) ((i << 52) >> 52); // Paper - simplify/inline - } - - public static int d(long i) { -- return (int) (i << 64 - BlockPosition.l - BlockPosition.g >> 64 - BlockPosition.g); -+ return (int) ((i << 26) >> 38); // Paper - simplify/inline - } - - public static BlockPosition fromLong(long i) { -- return new BlockPosition(b(i), c(i), d(i)); -+ return new BlockPosition((int) (i >> 38), (int) ((i << 52) >> 52), (int) ((i << 26) >> 38)); // Paper - simplify/inline - } - - public long asLong() { -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - - public static long asLong(int x, int y, int z) { return a(x, y, z); } // Paper - OBFHELPER - public static long a(int i, int j, int k) { -- long l = 0L; -- -- l |= ((long) i & BlockPosition.i) << BlockPosition.m; -- l |= ((long) j & BlockPosition.j) << 0; -- l |= ((long) k & BlockPosition.k) << BlockPosition.l; -- return l; -+ return (((long) i & (long) 67108863) << 38) | (((long) j & (long) 4095)) | (((long) k & (long) 67108863) << 12); // Paper - inline constants and simplify - } - - public static long f(long i) { -diff --git a/src/main/java/net/minecraft/core/SectionPosition.java b/src/main/java/net/minecraft/core/SectionPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/SectionPosition.java -+++ b/src/main/java/net/minecraft/core/SectionPosition.java -@@ -0,0 +0,0 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static SectionPosition a(BlockPosition blockposition) { -- return new SectionPosition(a(blockposition.getX()), a(blockposition.getY()), a(blockposition.getZ())); -+ return new SectionPosition(blockposition.getX() >> 4, blockposition.getY() >> 4, blockposition.getZ() >> 4); // Paper - } - - public static SectionPosition a(ChunkCoordIntPair chunkcoordintpair, int i) { -@@ -0,0 +0,0 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static SectionPosition a(long i) { -- return new SectionPosition(b(i), c(i), d(i)); -+ return new SectionPosition((int) (i >> 42), (int) (i << 44 >> 44), (int) (i << 22 >> 42)); // Paper - } - - public static long a(long i, EnumDirection enumdirection) { - return a(i, enumdirection.getAdjacentX(), enumdirection.getAdjacentY(), enumdirection.getAdjacentZ()); - } - -+ // Paper start -+ public static long getAdjacentFromBlockPos(int x, int y, int z, EnumDirection enumdirection) { -+ return (((long) ((x >> 4) + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getAdjacentZ()) & 4194303L) << 20); -+ } -+ public static long getAdjacentFromSectionPos(int x, int y, int z, EnumDirection enumdirection) { -+ return (((long) (x + enumdirection.getAdjacentX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getAdjacentY()) & 1048575L)) | (((long) (z + enumdirection.getAdjacentZ()) & 4194303L) << 20); -+ } -+ // Paper end - public static long a(long i, int j, int k, int l) { -- return b(b(i) + j, c(i) + k, d(i) + l); -+ return (((long) ((int) (i >> 42) + j) & 4194303L) << 42) | (((long) ((int) (i << 44 >> 44) + k) & 1048575L)) | (((long) ((int) (i << 22 >> 42) + l) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static int a(int i) { -@@ -0,0 +0,0 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static short b(BlockPosition blockposition) { -- int i = b(blockposition.getX()); -- int j = b(blockposition.getY()); -- int k = b(blockposition.getZ()); -- -- return (short) (i << 8 | k << 4 | j << 0); -+ return (short) ((blockposition.getX() & 15) << 8 | (blockposition.getZ() & 15) << 4 | blockposition.getY() & 15); // Paper - simplify/inline - } - - public static int a(short short0) { -@@ -0,0 +0,0 @@ public class SectionPosition extends BaseBlockPosition { - return this.getZ(); - } - -- public int d() { -- return this.a() << 4; -+ public final int d() { // Paper -+ return this.getX() << 4; // Paper - } - -- public int e() { -- return this.b() << 4; -+ public final int e() { // Paper -+ return this.getY() << 4; // Paper - } - -- public int f() { -- return this.c() << 4; -+ public final int f() { // Paper -+ return this.getZ() << 4; // Paper - } - - public int g() { -@@ -0,0 +0,0 @@ public class SectionPosition extends BaseBlockPosition { - return (this.c() << 4) + 15; - } - -+ public static long blockToSection(long i) { return e(i); } // Paper - OBFHELPER - public static long e(long i) { -- return b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); -+ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); -+ return (((long) (int) (i >> 42) & 4194303L) << 42) | (((long) (int) ((i << 52) >> 56) & 1048575L)) | (((long) (int) ((i << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count - } - - public static long f(long i) { -@@ -0,0 +0,0 @@ public class SectionPosition extends BaseBlockPosition { - return new ChunkCoordIntPair(this.a(), this.c()); - } - -+ // Paper start -+ public static long blockPosAsSectionLong(int i, int j, int k) { -+ return (((long) (i >> 4) & 4194303L) << 42) | (((long) (j >> 4) & 1048575L)) | (((long) (k >> 4) & 4194303L) << 20); -+ } -+ // Paper end -+ public static long asLong(int i, int j, int k) { return b(i, j, k); } // Paper - OBFHELPER - public static long b(int i, int j, int k) { -- long l = 0L; -- -- l |= ((long) i & 4194303L) << 42; -- l |= ((long) j & 1048575L) << 0; -- l |= ((long) k & 4194303L) << 20; -- return l; -+ return (((long) i & 4194303L) << 42) | (((long) j & 1048575L)) | (((long) k & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public long s() { -- return b(this.a(), this.b(), this.c()); -+ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count - } - - public Stream t() { -@@ -0,0 +0,0 @@ public class SectionPosition extends BaseBlockPosition { - } - - public static Stream a(SectionPosition sectionposition, int i) { -- int j = sectionposition.a(); -- int k = sectionposition.b(); -- int l = sectionposition.c(); -- -- return a(j - i, k - i, l - i, j + i, k + i, l + i); -+ return a(sectionposition.getX() - i, sectionposition.getY() - i, sectionposition.getZ() - i, sectionposition.getX() + i, sectionposition.getY() + i, sectionposition.getZ() + i); // Paper - simplify/inline - } - - public static Stream b(ChunkCoordIntPair chunkcoordintpair, int i) { -- int j = chunkcoordintpair.x; -- int k = chunkcoordintpair.z; -- -- return a(j - i, 0, k - i, j + i, 15, k + i); -+ return a(chunkcoordintpair.x - i, 0, chunkcoordintpair.z - i, chunkcoordintpair.x + i, 15, chunkcoordintpair.z + i); // Paper - simplify/inline - } - - public static Stream a(final int i, final int j, final int k, final int l, final int i1, final int j1) { diff --git a/Spigot-Server-Patches/Optimize-BlockPosition-helper-methods.patch b/Spigot-Server-Patches/Optimize-BlockPosition-helper-methods.patch deleted file mode 100644 index 06a96740b1..0000000000 --- a/Spigot-Server-Patches/Optimize-BlockPosition-helper-methods.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Wed, 15 Aug 2018 12:05:12 -0700 -Subject: [PATCH] Optimize BlockPosition helper methods - -Resolves #1338 - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - - @Override - public BlockPosition up() { -- return this.shift(EnumDirection.UP); -+ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition up(int i) { -- return this.shift(EnumDirection.UP, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() + i, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition down() { -- return this.shift(EnumDirection.DOWN); -+ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition - } - - @Override - public BlockPosition down(int i) { -- return this.shift(EnumDirection.DOWN, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY() - i, this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition north() { -- return this.shift(EnumDirection.NORTH); -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition - } - - public BlockPosition north(int i) { -- return this.shift(EnumDirection.NORTH, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() - i); // Paper - Optimize BlockPosition - } - - public BlockPosition south() { -- return this.shift(EnumDirection.SOUTH); -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition - } - - public BlockPosition south(int i) { -- return this.shift(EnumDirection.SOUTH, i); -+ return i == 0 ? this : new BlockPosition(this.getX(), this.getY(), this.getZ() + i); // Paper - Optimize BlockPosition - } - - public BlockPosition west() { -- return this.shift(EnumDirection.WEST); -+ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition west(int i) { -- return this.shift(EnumDirection.WEST, i); -+ return i == 0 ? this : new BlockPosition(this.getX() - i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition east() { -- return this.shift(EnumDirection.EAST); -+ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition east(int i) { -- return this.shift(EnumDirection.EAST, i); -+ return i == 0 ? this : new BlockPosition(this.getX() + i, this.getY(), this.getZ()); // Paper - Optimize BlockPosition - } - - public BlockPosition shift(EnumDirection enumdirection) { -- return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); -+ // Paper Start - Optimize BlockPosition -+ switch(enumdirection) { -+ case UP: -+ return new BlockPosition(this.getX(), this.getY() + 1, this.getZ()); -+ case DOWN: -+ return new BlockPosition(this.getX(), this.getY() - 1, this.getZ()); -+ case NORTH: -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() - 1); -+ case SOUTH: -+ return new BlockPosition(this.getX(), this.getY(), this.getZ() + 1); -+ case WEST: -+ return new BlockPosition(this.getX() - 1, this.getY(), this.getZ()); -+ case EAST: -+ return new BlockPosition(this.getX() + 1, this.getY(), this.getZ()); -+ default: -+ return new BlockPosition(this.getX() + enumdirection.getAdjacentX(), this.getY() + enumdirection.getAdjacentY(), this.getZ() + enumdirection.getAdjacentZ()); -+ } -+ // Paper End - } - - @Override diff --git a/Spigot-Server-Patches/Optimize-Captured-TileEntity-Lookup.patch b/Spigot-Server-Patches/Optimize-Captured-TileEntity-Lookup.patch deleted file mode 100644 index 9168f175d0..0000000000 --- a/Spigot-Server-Patches/Optimize-Captured-TileEntity-Lookup.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 6 Apr 2019 10:16:48 -0400 -Subject: [PATCH] Optimize Captured TileEntity Lookup - -upstream was doing a containsKey/get pattern, and always doing it at that. -that scenario is only even valid if were in the middle of a block place. - -Optimize to check if the captured list even has values in it, and also to -just do a get call since the value can never be null. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return null; - } else { - // CraftBukkit start -- if (capturedTileEntities.containsKey(blockposition)) { -- return capturedTileEntities.get(blockposition); -+ TileEntity tileentity = null; // Paper -+ if (!capturedTileEntities.isEmpty() && (tileentity = capturedTileEntities.get(blockposition)) != null) { // Paper -+ return tileentity; // Paper - } - // CraftBukkit end - -- TileEntity tileentity = null; -+ //TileEntity tileentity = null; // Paper - move up - - if (this.tickingTileEntities) { - tileentity = this.E(blockposition); diff --git a/Spigot-Server-Patches/Optimize-ChunkProviderServer-s-chunk-level-checking-.patch b/Spigot-Server-Patches/Optimize-ChunkProviderServer-s-chunk-level-checking-.patch deleted file mode 100644 index 57a3e94cdf..0000000000 --- a/Spigot-Server-Patches/Optimize-ChunkProviderServer-s-chunk-level-checking-.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 16 Apr 2020 16:13:59 -0700 -Subject: [PATCH] Optimize ChunkProviderServer's chunk level checking helper - methods - -These can be hot functions (i.e entity ticking and block ticking), -so inline where possible, and avoid the abstraction of the -Either class. - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - - public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER - @Override public boolean a(Entity entity) { -- long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); -- -- return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // entity ticking -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(entity)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER - @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { -- return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is entity ticking ready -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(chunkcoordintpair)); -+ return playerChunk != null && playerChunk.isEntityTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - @Override - public boolean a(BlockPosition blockposition) { -- long i = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4); -- -- return this.a(i, (Function>>) PlayerChunk::a); // CraftBukkit - decompile error -+ // Paper start - optimize is ticking ready type functions -+ // is ticking ready -+ PlayerChunk playerChunk = this.getChunk(MCUtil.getCoordinateKey(blockposition)); -+ return playerChunk != null && playerChunk.isTickingReady(); -+ // Paper end - optimize is ticking ready type functions - } - - private boolean a(long i, Function>> function) { diff --git a/Spigot-Server-Patches/Optimize-Collision-to-not-load-chunks.patch b/Spigot-Server-Patches/Optimize-Collision-to-not-load-chunks.patch deleted file mode 100644 index 8f50c1b412..0000000000 --- a/Spigot-Server-Patches/Optimize-Collision-to-not-load-chunks.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 02:37:57 -0400 -Subject: [PATCH] Optimize Collision to not load chunks - -The collision code takes an AABB and generates a cuboid of checks rather -than a cylinder, so at high velocity this can generate a lot of chunk checks. - -Treat an unloaded chunk as a collision for entities, and also for players if -the "prevent moving into unloaded chunks" setting is enabled. - -If that serting is not enabled, collisions will be ignored for players, since -movement will load only the chunk the player enters anyways and avoids loading -massive amounts of surrounding chunks due to large AABB lookups. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ import net.minecraft.server.ScoreboardServer; - import net.minecraft.server.level.DemoPlayerInteractManager; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerInteractManager; -+import net.minecraft.server.level.TicketType; - import net.minecraft.server.level.WorldServer; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.sounds.SoundCategory; -@@ -0,0 +0,0 @@ import net.minecraft.world.effect.MobEffect; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.World; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - // CraftBukkit end - -+ worldserver1.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper - while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) { - entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ()); - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private CraftEntity bukkitEntity; - - PlayerChunkMap.EntityTracker tracker; // Paper -+ public boolean collisionLoadChunks = false; // Paper - public Throwable addedToWorldStack; // Paper - entity debug - public CraftEntity getBukkitEntity() { - if (bukkitEntity == null) { -diff --git a/src/main/java/net/minecraft/world/level/ICollisionAccess.java b/src/main/java/net/minecraft/world/level/ICollisionAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/ICollisionAccess.java -+++ b/src/main/java/net/minecraft/world/level/ICollisionAccess.java -@@ -0,0 +0,0 @@ public interface ICollisionAccess extends IBlockAccess { - } - - default boolean b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate) { -+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.d(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); -+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper - } - - Stream c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate predicate); -diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -@@ -0,0 +0,0 @@ import java.util.function.Consumer; - import javax.annotation.Nullable; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.CursorPosition; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.RegionLimitedWorldAccess; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.block.Blocks; -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.shapes.VoxelShapes; - public class VoxelShapeSpliterator extends AbstractSpliterator { - - @Nullable -- private final Entity a; -+ private final Entity a; final Entity getEntity() { return this.a; } // Paper - OBFHELPER - private final AxisAlignedBB b; - private final VoxelShapeCollision c; - private final CursorPosition d; -- private final BlockPosition.MutableBlockPosition e; -+ private final BlockPosition.MutableBlockPosition e; final BlockPosition.MutableBlockPosition getMutablePos() { return this.e; } // Paper - OBFHELPER - private final VoxelShape f; -- private final ICollisionAccess g; -+ private final ICollisionAccess g; final ICollisionAccess getCollisionAccess() { return this.g; } // Paper - OBFHELPER - private boolean h; - private final BiPredicate i; - -@@ -0,0 +0,0 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { - boolean a(Consumer consumer) { - while (true) { - if (this.d.a()) { -- int i = this.d.b(); -- int j = this.d.c(); -- int k = this.d.d(); -+ int i = this.d.b(); final int x = i; -+ int j = this.d.c(); final int y = j; -+ int k = this.d.d(); final int z = k; - int l = this.d.e(); - - if (l == 3) { - continue; - } - -- IBlockAccess iblockaccess = this.a(i, k); -- -- if (iblockaccess == null) { -+ // Paper start - ensure we don't load chunks -+ Entity entity = this.getEntity(); -+ BlockPosition.MutableBlockPosition blockposition_mutableblockposition = this.getMutablePos(); -+ boolean far = entity != null && MCUtil.distanceSq(entity.locX(), y, entity.locZ(), x, y, z) > 14; -+ blockposition_mutableblockposition.setValues(x, y, z); -+ -+ boolean isRegionLimited = this.getCollisionAccess() instanceof RegionLimitedWorldAccess; -+ IBlockData iblockdata = isRegionLimited ? Blocks.VOID_AIR.getBlockData() : ((!far && entity instanceof EntityPlayer) || (entity != null && entity.collisionLoadChunks) -+ ? this.getCollisionAccess().getType(blockposition_mutableblockposition) -+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition) -+ ); -+ -+ if (iblockdata == null) { -+ if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) { -+ VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z))); -+ consumer.accept(voxelshape3); -+ return true; -+ } - continue; - } -- -- this.e.d(i, j, k); -- IBlockData iblockdata = iblockaccess.getType(this.e); -+ // Paper - moved up -+ // Paper end - - if (!this.i.test(iblockdata, this.e) || l == 1 && !iblockdata.d() || l == 2 && !iblockdata.a(Blocks.MOVING_PISTON)) { - continue; -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -0,0 +0,0 @@ public final class VoxelShapes { - - if (k2 < 3) { - blockposition_mutableblockposition.a(enumaxiscycle1, i2, j2, l1); -- IBlockData iblockdata = iworldreader.getType(blockposition_mutableblockposition); -+ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata == null) return 0.0D; // Paper - - if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { - d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); diff --git a/Spigot-Server-Patches/Optimize-CraftBlockData-Creation.patch b/Spigot-Server-Patches/Optimize-CraftBlockData-Creation.patch deleted file mode 100644 index 7c430a4990..0000000000 --- a/Spigot-Server-Patches/Optimize-CraftBlockData-Creation.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Thu, 23 Aug 2018 11:45:32 -0400 -Subject: [PATCH] Optimize CraftBlockData Creation - -Avoids a hashmap lookup by cacheing a reference to the CraftBlockData -and cloning it when one is needed. - -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -0,0 +0,0 @@ public abstract class BlockBase { - this.o = blockbase_info.t; - this.p = blockbase_info.u; - } -+ // Paper start - impl cached craft block data, lazy load to fix issue with loading at the wrong time -+ private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData; -+ -+ public org.bukkit.craftbukkit.block.data.CraftBlockData createCraftBlockData() { -+ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(getBlockData()); -+ return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); -+ } -+ // Paper end - - public void a() { - if (!this.getBlock().o()) { -diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java -@@ -0,0 +0,0 @@ public class CraftBlockData implements BlockData { - return craft; - } - -+ // Paper start - optimize creating BlockData to not need a map lookup -+ static { -+ // Initialize cached data for all IBlockData instances after registration -+ Block.REGISTRY_ID.iterator().forEachRemaining(IBlockData::createCraftBlockData); -+ } - public static CraftBlockData fromData(IBlockData data) { -+ return data.createCraftBlockData(); -+ } -+ -+ public static CraftBlockData createData(IBlockData data) { -+ // Paper end - return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); - } - diff --git a/Spigot-Server-Patches/Optimize-DataBits.patch b/Spigot-Server-Patches/Optimize-DataBits.patch deleted file mode 100644 index 4fa643e8e0..0000000000 --- a/Spigot-Server-Patches/Optimize-DataBits.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Apr 2016 21:38:58 -0400 -Subject: [PATCH] Optimize DataBits - -Remove Debug checks as these are super hot and causing noticeable hits - -Before: http://i.imgur.com/nQsMzAE.png -After: http://i.imgur.com/nJ46crB.png - -Optimize redundant converting of static fields into an unsigned long each call by precomputing it in ctor - -diff --git a/src/main/java/net/minecraft/util/DataBits.java b/src/main/java/net/minecraft/util/DataBits.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/DataBits.java -+++ b/src/main/java/net/minecraft/util/DataBits.java -@@ -0,0 +0,0 @@ public class DataBits { - private final long d; - private final int e; - private final int f; -- private final int g; -- private final int h; -+ private final int g;private final long g_unsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls -+ private final int h;private final long h_unsigned; // Paper - private final int i; - - public DataBits(int i, int j) { -@@ -0,0 +0,0 @@ public class DataBits { - this.f = (char) (64 / i); - int k = 3 * (this.f - 1); - -- this.g = DataBits.a[k + 0]; -- this.h = DataBits.a[k + 1]; -+ this.g = DataBits.a[k + 0]; this.g_unsigned = Integer.toUnsignedLong(this.g); // Paper -+ this.h = DataBits.a[k + 1]; this.h_unsigned = Integer.toUnsignedLong(this.h); // Paper - this.i = DataBits.a[k + 2]; - int l = (j + this.f - 1) / this.f; - -@@ -0,0 +0,0 @@ public class DataBits { - } - - private int b(int i) { -- long j = Integer.toUnsignedLong(this.g); -- long k = Integer.toUnsignedLong(this.h); -+ //long j = Integer.toUnsignedLong(this.g); // Paper -+ //long k = Integer.toUnsignedLong(this.h); // Paper - -- return (int) ((long) i * j + k >> 32 >> this.i); -+ return (int) ((long) i * this.g_unsigned + this.h_unsigned >> 32 >> this.i); // Paper - } - -- public int a(int i, int j) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -- Validate.inclusiveBetween(0L, this.d, (long) j); -+ public final int a(int i, int j) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.b(i); - long l = this.b[k]; - int i1 = (i - k * this.f) * this.c; -@@ -0,0 +0,0 @@ public class DataBits { - return j1; - } - -- public void b(int i, int j) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -- Validate.inclusiveBetween(0L, this.d, (long) j); -+ public final void b(int i, int j) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper -+ //Validate.inclusiveBetween(0L, this.d, (long) j); // Paper - int k = this.b(i); - long l = this.b[k]; - int i1 = (i - k * this.f) * this.c; -@@ -0,0 +0,0 @@ public class DataBits { - this.b[k] = l & ~(this.d << i1) | ((long) j & this.d) << i1; - } - -- public int a(int i) { -- Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); -+ public final int a(int i) { // Paper - make final for inline -+ //Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper - int j = this.b(i); - long k = this.b[j]; - int l = (i - j * this.f) * this.c; diff --git a/Spigot-Server-Patches/Optimize-Dynamic-get-Missing-Keys.patch b/Spigot-Server-Patches/Optimize-Dynamic-get-Missing-Keys.patch deleted file mode 100644 index 36cdf340c3..0000000000 --- a/Spigot-Server-Patches/Optimize-Dynamic-get-Missing-Keys.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 21 Dec 2020 11:01:42 -0500 -Subject: [PATCH] Optimize Dynamic#get Missing Keys - -get was calling toString() on every NBT object that was ever asked for an optional -key from the object to build a string for the error text. - -When done on large NBT objects, this was using a ton of computation time building the -JSON representation of the NBT object. - -Now we will just skip the value when 99.9999% of the time the text is never even printed. - -diff --git a/src/main/java/com/mojang/serialization/Dynamic.java b/src/main/java/com/mojang/serialization/Dynamic.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/mojang/serialization/Dynamic.java -+++ b/src/main/java/com/mojang/serialization/Dynamic.java -@@ -0,0 +0,0 @@ import java.util.stream.Stream; - - @SuppressWarnings("unused") - public class Dynamic extends DynamicLike { -+ private static final boolean DEBUG_MISSING_KEYS = Boolean.getBoolean("Paper.debugDynamicMissingKeys"); // Paper - private final T value; - - public Dynamic(final DynamicOps ops) { -@@ -0,0 +0,0 @@ public class Dynamic extends DynamicLike { - return new OptionalDynamic<>(ops, ops.getMap(value).flatMap(m -> { - final T value = m.get(key); - if (value == null) { -- return DataResult.error("key missing: " + key + " in " + this.value); -+ return DataResult.error(DEBUG_MISSING_KEYS ? "key missing: " + key + " in " + this.value : "key missing: " + key); // Paper - } - return DataResult.success(new Dynamic<>(ops, value)); - })); diff --git a/Spigot-Server-Patches/Optimize-Hoppers.patch b/Spigot-Server-Patches/Optimize-Hoppers.patch deleted file mode 100644 index cb232f1e13..0000000000 --- a/Spigot-Server-Patches/Optimize-Hoppers.patch +++ /dev/null @@ -1,517 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Apr 2016 22:09:52 -0400 -Subject: [PATCH] Optimize Hoppers - -* Removes unnecessary extra calls to .update() that are very expensive -* Lots of itemstack cloning removed. Only clone if the item is actually moved -* Return true when a plugin cancels inventory move item event instead of false, as false causes pulls to cycle through all items. - However, pushes do not exhibit the same behavior, so this is not something plugins could of been relying on. -* Add option (Default on) to cooldown hoppers when they fail to move an item due to full inventory -* Skip subsequent InventoryMoveItemEvents if a plugin does not use the item after first event fire for an iteration -* Don't check for Entities with Inventories if the block above us is also occluding (not just Inventoried) -* Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); - } -+ -+ public boolean cooldownHopperWhenFull = true; -+ public boolean disableHopperMoveEvents = false; -+ private void hopperOptimizations() { -+ cooldownHopperWhenFull = getBoolean("hopper.cooldown-when-full", cooldownHopperWhenFull); -+ log("Cooldown Hoppers when Full: " + (cooldownHopperWhenFull ? "enabled" : "disabled")); -+ disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); -+ log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.WorldSettings; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.biome.WorldChunkManager; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.TileEntityHopper; - import net.minecraft.world.level.border.IWorldBorderListener; - import net.minecraft.world.level.border.WorldBorder; - import net.minecraft.world.level.chunk.ChunkGenerator; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0; // Paper -+ TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - - this.methodProfiler.a(() -> { - return worldserver + " " + worldserver.getDimensionKey().a(); -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - return this.getItem().a(this, entityhuman, entityliving, enumhand); - } - -- public ItemStack cloneItemStack() { -- if (this.isEmpty()) { -+ public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper -+ public ItemStack cloneItemStack(boolean origItem) { // Paper -+ if (!origItem && this.isEmpty()) { // Paper - return ItemStack.b; - } else { -- ItemStack itemstack = new ItemStack(this.getItem(), this.count); -+ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper - - itemstack.d(this.D()); - if (this.tag != null) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return list; - } - -- @Override -- public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { -+ public List getEntities(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { return a(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER -+ @Override public List a(Class oclass, AxisAlignedBB axisalignedbb, @Nullable Predicate predicate) { - this.getMethodProfiler().c("getEntities"); - int i = MathHelper.floor((axisalignedbb.minX - 2.0D) / 16.0D); - int j = MathHelper.f((axisalignedbb.maxX + 2.0D) / 16.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/IHopper.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPosition; - import net.minecraft.world.IInventory; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; -@@ -0,0 +0,0 @@ public interface IHopper extends IInventory { - return IHopper.c; - } - -- @Nullable -+ //@Nullable // Paper - it's annoying - World getWorld(); -+ default BlockPosition getBlockPosition() { return new BlockPosition(getX(), getY(), getZ()); } // Paper - -- double x(); -+ double x(); default double getX() { return this.x(); } // Paper - OBFHELPER - -- double z(); -+ double z(); default double getY() { return this.z(); } // Paper - OBFHELPER - -- double A(); -+ double A(); default double getZ() { return this.A(); } // Paper - OBFHELPER - } -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public void setCurrentChunk(Chunk chunk) { - this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; - } -+ static boolean IGNORE_TILE_UPDATES = false; - // Paper end - - @Nullable -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - - public void update() { - if (this.world != null) { -+ if (IGNORE_TILE_UPDATES) return; // Paper - this.c = this.world.getType(this.position); - this.world.b(this.position, this); - if (!this.c.isAir()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityHopper.java -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return false; - } - -+ // Paper start - Optimize Hoppers -+ private static boolean skipPullModeEventFire = false; -+ private static boolean skipPushModeEventFire = false; -+ public static boolean skipHopperEvents = false; -+ -+ private boolean hopperPush(IInventory iinventory, EnumDirection enumdirection) { -+ skipPushModeEventFire = skipHopperEvents; -+ boolean foundItem = false; -+ for (int i = 0; i < this.getSize(); ++i) { -+ ItemStack item = this.getItem(i); -+ if (!item.isEmpty()) { -+ foundItem = true; -+ ItemStack origItemStack = item; -+ ItemStack itemstack = origItemStack; -+ -+ final int origCount = origItemStack.getCount(); -+ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); -+ origItemStack.setCount(moved); -+ -+ // We only need to fire the event once to give protection plugins a chance to cancel this event -+ // Because nothing uses getItem, every event call should end up the same result. -+ if (!skipPushModeEventFire) { -+ itemstack = callPushMoveEvent(iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ return false; -+ } -+ } -+ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ this.setItem(i, origItemStack); -+ iinventory.update(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ } -+ } -+ if (foundItem && world.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown -+ this.setCooldown(world.spigotConfig.hopperTransfer); -+ } -+ return false; -+ } -+ -+ private static boolean hopperPull(IHopper ihopper, IInventory iinventory, ItemStack origItemStack, int i) { -+ ItemStack itemstack = origItemStack; -+ final int origCount = origItemStack.getCount(); -+ final World world = ihopper.getWorld(); -+ final int moved = Math.min(world.spigotConfig.hopperAmount, origCount); -+ itemstack.setCount(moved); -+ -+ if (!skipPullModeEventFire) { -+ itemstack = callPullMoveEvent(ihopper, iinventory, itemstack); -+ if (itemstack == null) { // cancelled -+ origItemStack.setCount(origCount); -+ // Drastically improve performance by returning true. -+ // No plugin could of relied on the behavior of false as the other call -+ // site for IMIE did not exhibit the same behavior -+ return true; -+ } -+ } -+ -+ final ItemStack itemstack2 = addItem(iinventory, ihopper, itemstack, null); -+ final int remaining = itemstack2.getCount(); -+ if (remaining != moved) { -+ origItemStack = origItemStack.cloneItemStack(true); -+ origItemStack.setCount(origCount); -+ if (!origItemStack.isEmpty()) { -+ origItemStack.setCount(origCount - moved + remaining); -+ } -+ IGNORE_TILE_UPDATES = true; -+ iinventory.setItem(i, origItemStack); -+ IGNORE_TILE_UPDATES = false; -+ iinventory.update(); -+ return true; -+ } -+ origItemStack.setCount(origCount); -+ -+ if (world.paperConfig.cooldownHopperWhenFull) { -+ cooldownHopper(ihopper); -+ } -+ -+ return false; -+ } -+ -+ private ItemStack callPushMoveEvent(IInventory iinventory, ItemStack itemstack) { -+ Inventory destinationInventory = getInventory(iinventory); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), -+ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPushModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(this); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static ItemStack callPullMoveEvent(IHopper hopper, IInventory iinventory, ItemStack itemstack) { -+ Inventory sourceInventory = getInventory(iinventory); -+ Inventory destination = getInventory(hopper); -+ -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, -+ // Mirror is safe as we no plugins ever use this item -+ CraftItemStack.asCraftMirror(itemstack), destination, false); -+ boolean result = event.callEvent(); -+ if (!event.calledGetItem && !event.calledSetItem) { -+ skipPullModeEventFire = true; -+ } -+ if (!result) { -+ cooldownHopper(hopper); -+ return null; -+ } -+ -+ if (event.calledSetItem) { -+ return CraftItemStack.asNMSCopy(event.getItem()); -+ } else { -+ return itemstack; -+ } -+ } -+ -+ private static Inventory getInventory(IInventory iinventory) { -+ Inventory sourceInventory;// Have to special case large chests as they work oddly -+ if (iinventory instanceof InventoryLargeChest) { -+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); -+ } else if (iinventory instanceof TileEntity) { -+ sourceInventory = ((TileEntity) iinventory).getOwner(false).getInventory(); -+ } else { -+ sourceInventory = iinventory.getOwner().getInventory(); -+ } -+ return sourceInventory; -+ } -+ -+ private static void cooldownHopper(IHopper hopper) { -+ if (hopper instanceof TileEntityHopper) { -+ ((TileEntityHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer); -+ } else if (hopper instanceof EntityMinecartHopper) { -+ ((EntityMinecartHopper) hopper).setCooldown(hopper.getWorld().spigotConfig.hopperTransfer / 2); -+ } -+ } -+ // Paper end -+ - private boolean k() { - IInventory iinventory = this.l(); - -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - if (this.b(iinventory, enumdirection)) { - return false; - } else { -+ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest - for (int i = 0; i < this.getSize(); ++i) { - if (!this.getItem(i).isEmpty()) { - ItemStack itemstack = this.getItem(i).cloneItemStack(); -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- return false; -+ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - } - } -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return iinventory instanceof IWorldInventory ? IntStream.of(((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) : IntStream.range(0, iinventory.getSize()); - } - -- private boolean b(IInventory iinventory, EnumDirection enumdirection) { -- return a(iinventory, enumdirection).allMatch((i) -> { -- ItemStack itemstack = iinventory.getItem(i); -+ private static boolean allMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof IWorldInventory) { -+ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } else { -+ int size = iinventory.getSize(); -+ for (int i = 0; i < size; i++) { -+ if (!test.test(iinventory.getItem(i), i)) { -+ return false; -+ } -+ } -+ } -+ return true; -+ } - -- return itemstack.getCount() >= itemstack.getMaxStackSize(); -- }); -+ private static boolean anyMatch(IInventory iinventory, EnumDirection enumdirection, java.util.function.BiPredicate test) { -+ if (iinventory instanceof IWorldInventory) { -+ for (int i : ((IWorldInventory) iinventory).getSlotsForFace(enumdirection)) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } else { -+ int size = iinventory.getSize(); -+ for (int i = 0; i < size; i++) { -+ if (test.test(iinventory.getItem(i), i)) { -+ return true; -+ } -+ } -+ } -+ return true; -+ } -+ private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); -+ private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); -+ -+ // Paper end -+ -+ private boolean b(IInventory iinventory, EnumDirection enumdirection) { -+ // Paper start - no streams -+ return allMatch(iinventory, enumdirection, STACK_SIZE_TEST); -+ // Paper end - } - - private static boolean c(IInventory iinventory, EnumDirection enumdirection) { -- return a(iinventory, enumdirection).allMatch((i) -> { -- return iinventory.getItem(i).isEmpty(); -- }); -+ return allMatch(iinventory, enumdirection, IS_EMPTY_TEST); - } - - public static boolean a(IHopper ihopper) { -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - if (iinventory != null) { - EnumDirection enumdirection = EnumDirection.DOWN; - -- return c(iinventory, enumdirection) ? false : a(iinventory, enumdirection).anyMatch((i) -> { -- return a(ihopper, iinventory, i, enumdirection); -+ // Paper start - optimize hoppers and remove streams -+ skipPullModeEventFire = skipHopperEvents; -+ return !c(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { -+ // Logic copied from below to avoid extra getItem calls -+ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { -+ return hopperPull(ihopper, iinventory, item, i); -+ } else { -+ return false; -+ } - }); -+ // Paper end - } else { - Iterator iterator = c(ihopper).iterator(); - -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) { -+ private static boolean a(IHopper ihopper, IInventory iinventory, int i, EnumDirection enumdirection) {// Paper - method unused as logic is inlined above - ItemStack itemstack = iinventory.getItem(i); - -- if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { -+ if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins -+ return hopperPull(ihopper, iinventory, itemstack, i); /* // Paper - disable rest - ItemStack itemstack1 = itemstack.cloneItemStack(); - // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); - // CraftBukkit start - Call event on collection of items from inventories into the hopper -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot -- iinventory.setItem(i, itemstack1); -+ iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations - } - - return false; -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - public static boolean a(IInventory iinventory, EntityItem entityitem) { - boolean flag = false; - // CraftBukkit start -- InventoryPickupItemEvent event = new InventoryPickupItemEvent(iinventory.getOwner().getInventory(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); -+ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(iinventory), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation - entityitem.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return false; -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - return !iinventory.b(i, itemstack) ? false : !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canPlaceItemThroughFace(i, itemstack, enumdirection); - } - -+ private static boolean canTakeItem(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { return b(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER - private static boolean b(IInventory iinventory, ItemStack itemstack, int i, EnumDirection enumdirection) { - return !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canTakeItemThroughFace(i, itemstack, enumdirection); - } -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - boolean flag1 = iinventory1.isEmpty(); - - if (itemstack1.isEmpty()) { -+ IGNORE_TILE_UPDATES = true; // Paper - iinventory1.setItem(i, itemstack); -+ IGNORE_TILE_UPDATES = false; // Paper - itemstack = ItemStack.b; - flag = true; - } else if (a(itemstack1, itemstack)) { -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - - public static List c(IHopper ihopper) { -- return (List) ihopper.aa_().d().stream().flatMap((axisalignedbb) -> { -- return ihopper.getWorld().a(EntityItem.class, axisalignedbb.d(ihopper.x() - 0.5D, ihopper.z() - 0.5D, ihopper.A() - 0.5D), IEntitySelector.a).stream(); -- }).collect(Collectors.toList()); -+ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! -+ World world = ihopper.getWorld(); -+ double d0 = ihopper.getX(); -+ double d1 = ihopper.getY(); -+ double d2 = ihopper.getZ(); -+ AxisAlignedBB bb = new AxisAlignedBB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); -+ return world.getEntities(EntityItem.class, bb, Entity::isAlive); -+ // Paper end - } - - @Nullable - public static IInventory b(World world, BlockPosition blockposition) { -- return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper - } - - @Nullable -- public static IInventory a(World world, double d0, double d1, double d2) { -+ public static IInventory a(World world, double d0, double d1, double d2) { return a(world, d0, d1, d2, false); } // Paper - overload to default false -+ public static IInventory a(World world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper - Object object = null; - BlockPosition blockposition = new BlockPosition(d0, d1, d2); - if ( !world.isLoaded( blockposition ) ) return null; // Spigot -@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi - } - } - -- if (object == null) { -+ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper - List list = world.getEntities((Entity) null, new AxisAlignedBB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), IEntitySelector.d); - - if (!list.isEmpty()) { -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java -@@ -0,0 +0,0 @@ public abstract class TileEntityLootable extends TileEntityContainer { - @Override - public boolean isEmpty() { - this.d((EntityHuman) null); -- return this.f().stream().allMatch(ItemStack::isEmpty); -+ // Paper start -+ for (ItemStack itemStack : this.f()) { -+ if (!itemStack.isEmpty()) { -+ return false; -+ } -+ } -+ // Paper end -+ return true; - } - - @Override - public ItemStack getItem(int i) { -- this.d((EntityHuman) null); -+ if (i == 0) this.d((EntityHuman) null); // Paper - return (ItemStack) this.f().get(i); - } - diff --git a/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch b/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch deleted file mode 100644 index 68a8013e17..0000000000 --- a/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 21 Dec 2016 03:48:29 -0500 -Subject: [PATCH] Optimize ItemStack.isEmpty() - -Remove hashMap lookup every check, simplify code to remove ternary - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - } - - public boolean isEmpty() { -- return this == ItemStack.b ? true : (this.getItem() != null && this.getItem() != Items.AIR ? this.count <= 0 : true); -+ return this == ItemStack.NULL_ITEM || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper - } - - public ItemStack cloneAndSubtract(int i) { diff --git a/Spigot-Server-Patches/Optimize-Light-Engine.patch b/Spigot-Server-Patches/Optimize-Light-Engine.patch deleted file mode 100644 index ae6a62bc9a..0000000000 --- a/Spigot-Server-Patches/Optimize-Light-Engine.patch +++ /dev/null @@ -1,1433 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 4 Jun 2020 22:43:29 -0400 -Subject: [PATCH] Optimize Light Engine - -Massive update to light to improve performance and chunk loading/generation. - -1) Massive bit packing/unpacking optimizations and inlining. - A lot of performance has to do with constant packing and unpacking of bits. - We now inline a most bit operations, and re-use base x/y/z bits in many places. - This helps with cpu level processing to just do all the math at once instead - of having to jump in and out of function calls. - - This much logic also is likely over the JVM Inline limit for JIT too. -2) Applied a few of JellySquid's Phosphor mod optimizations such as - - ensuring we don't notify neighbor chunks when neighbor chunk doesn't need to be notified - - reduce hasLight checks in initializing light, and prob some more, they are tagged JellySquid where phosphor influence was used. -3) Optimize hot path accesses to getting updating chunk to have less branching -4) Optimize getBlock accesses to have less branching, and less unpacking -5) Have a separate urgent bucket for chunk light tasks. These tasks will always cut in line over non blocking light tasks. -6) Retain chunk priority while light tasks are enqueued. So if a task comes in at high priority but the queue is full - of tasks already at a lower priority, before the task was simply added to the end. Now it can cut in line to the front. - this applies for both urgent and non urgent tasks. -7) Buffer non urgent tasks even if queueUpdate is called multiple times to improve efficiency. -8) Fix NPE risk that crashes server in getting nibble data - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - if (ChunkProviderServer.this.tickDistanceManager()) { - return true; - } else { -- ChunkProviderServer.this.lightEngine.queueUpdate(); -+ ChunkProviderServer.this.lightEngine.queueUpdate(); // Paper - not needed - return super.executeNext() || execChunkTask; // Paper - } - } finally { -diff --git a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineGraphSection.java -@@ -0,0 +0,0 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { - - @Override - protected void a(long i, int j, boolean flag) { -+ // Paper start -+ int x = (int) (i >> 42); -+ int y = (int) (i << 44 >> 44); -+ int z = (int) (i << 22 >> 42); -+ // Paper end - for (int k = -1; k <= 1; ++k) { - for (int l = -1; l <= 1; ++l) { - for (int i1 = -1; i1 <= 1; ++i1) { -- long j1 = SectionPosition.a(i, k, l, i1); -+ if (k == 0 && l == 0 && i1 == 0) continue; // Paper -+ long j1 = (((long) (x + k) & 4194303L) << 42) | (((long) (y + l) & 1048575L)) | (((long) (z + i1) & 4194303L) << 20); // Paper - -- if (j1 != i) { -+ //if (j1 != i) { // Paper - checked above - this.b(i, j1, j, flag); -- } -+ //} // Paper - } - } - } -@@ -0,0 +0,0 @@ public abstract class LightEngineGraphSection extends LightEngineGraph { - protected int a(long i, long j, int k) { - int l = k; - -+ // Paper start -+ int x = (int) (i >> 42); -+ int y = (int) (i << 44 >> 44); -+ int z = (int) (i << 22 >> 42); -+ // Paper end - for (int i1 = -1; i1 <= 1; ++i1) { - for (int j1 = -1; j1 <= 1; ++j1) { - for (int k1 = -1; k1 <= 1; ++k1) { -- long l1 = SectionPosition.a(i, i1, j1, k1); -+ long l1 = (((long) (x + i1) & 4194303L) << 42) | (((long) (y + j1) & 1048575L)) | (((long) (z + k1) & 4194303L) << 20); // Paper - - if (l1 == i) { - l1 = Long.MAX_VALUE; -diff --git a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -+++ b/src/main/java/net/minecraft/server/level/LightEngineThreaded.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.level; - - import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; // Paper - import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import it.unimi.dsi.fastutil.objects.ObjectList; - import it.unimi.dsi.fastutil.objects.ObjectListIterator; -@@ -0,0 +0,0 @@ import net.minecraft.util.thread.ThreadedMailbox; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.chunk.ChunkSection; -+import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -0,0 +0,0 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ThreadedMailbox b; -- private final ObjectList> c = new ObjectArrayList(); -- private final PlayerChunkMap d; -+ // Paper start -+ private static final int MAX_PRIORITIES = PlayerChunkMap.GOLDEN_TICKET + 2; -+ -+ private boolean isChunkLightStatus(long pair) { -+ PlayerChunk playerChunk = playerChunkMap.getVisibleChunk(pair); -+ if (playerChunk == null) { -+ return false; -+ } -+ ChunkStatus status = PlayerChunk.getChunkStatus(playerChunk.getTicketLevel()); -+ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT); -+ } -+ -+ static class ChunkLightQueue { -+ public boolean shouldFastUpdate; -+ java.util.ArrayDeque pre = new java.util.ArrayDeque(); -+ java.util.ArrayDeque post = new java.util.ArrayDeque(); -+ -+ ChunkLightQueue(long chunk) {} -+ } -+ -+ static class PendingLightTask { -+ long chunkId; -+ IntSupplier priority; -+ Runnable pre; -+ Runnable post; -+ boolean fastUpdate; -+ -+ public PendingLightTask(long chunkId, IntSupplier priority, Runnable pre, Runnable post, boolean fastUpdate) { -+ this.chunkId = chunkId; -+ this.priority = priority; -+ this.pre = pre; -+ this.post = post; -+ this.fastUpdate = fastUpdate; -+ } -+ } -+ -+ -+ // Retain the chunks priority level for queued light tasks -+ class LightQueue { -+ private int size = 0; -+ private final Long2ObjectLinkedOpenHashMap[] buckets = new Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES]; -+ private final java.util.concurrent.ConcurrentLinkedQueue pendingTasks = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private final java.util.concurrent.ConcurrentLinkedQueue priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ -+ private LightQueue() { -+ for (int i = 0; i < buckets.length; i++) { -+ buckets[i] = new Long2ObjectLinkedOpenHashMap<>(); -+ } -+ } -+ -+ public void changePriority(long pair, int currentPriority, int priority) { -+ this.priorityChanges.add(() -> { -+ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair); -+ if (remove != null) { -+ ChunkLightQueue existing = this.buckets[Math.max(1, priority)].put(pair, remove); -+ if (existing != null) { -+ remove.pre.addAll(existing.pre); -+ remove.post.addAll(existing.post); -+ } -+ } -+ }); -+ } -+ -+ public final void addChunk(long chunkId, IntSupplier priority, Runnable pre, Runnable post) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, pre, post, true)); -+ queueUpdate(); -+ } -+ -+ public final void add(long chunkId, IntSupplier priority, LightEngineThreaded.Update type, Runnable run) { -+ pendingTasks.add(new PendingLightTask(chunkId, priority, type == Update.PRE_UPDATE ? run : null, type == Update.POST_UPDATE ? run : null, false)); -+ } -+ public final void add(PendingLightTask update) { -+ int priority = update.priority.getAsInt(); -+ ChunkLightQueue lightQueue = this.buckets[priority].computeIfAbsent(update.chunkId, ChunkLightQueue::new); -+ -+ if (update.pre != null) { -+ this.size++; -+ lightQueue.pre.add(update.pre); -+ } -+ if (update.post != null) { -+ this.size++; -+ lightQueue.post.add(update.post); -+ } -+ if (update.fastUpdate) { -+ lightQueue.shouldFastUpdate = true; -+ } -+ } -+ -+ public final boolean isEmpty() { -+ return this.size == 0 && this.pendingTasks.isEmpty(); -+ } -+ -+ public final int size() { -+ return this.size; -+ } -+ -+ public boolean poll(java.util.List pre, java.util.List post) { -+ PendingLightTask pending; -+ while ((pending = pendingTasks.poll()) != null) { -+ add(pending); -+ } -+ Runnable run; -+ while ((run = priorityChanges.poll()) != null) { -+ run.run(); -+ } -+ boolean hasWork = false; -+ Long2ObjectLinkedOpenHashMap[] buckets = this.buckets; -+ int priority = 0; -+ while (priority < MAX_PRIORITIES && !isEmpty()) { -+ Long2ObjectLinkedOpenHashMap bucket = buckets[priority]; -+ if (bucket.isEmpty()) { -+ priority++; -+ if (hasWork) { -+ return true; -+ } else { -+ continue; -+ } -+ } -+ ChunkLightQueue queue = bucket.removeFirst(); -+ this.size -= queue.pre.size() + queue.post.size(); -+ pre.addAll(queue.pre); -+ post.addAll(queue.post); -+ queue.pre.clear(); -+ queue.post.clear(); -+ hasWork = true; -+ if (queue.shouldFastUpdate) { -+ return true; -+ } -+ } -+ return hasWork; -+ } -+ } -+ -+ final LightQueue queue = new LightQueue(); -+ // Paper end -+ private final PlayerChunkMap d; private final PlayerChunkMap playerChunkMap; // Paper - private final Mailbox> e; - private volatile int f = 5; - private final AtomicBoolean g = new AtomicBoolean(); - - public LightEngineThreaded(ILightAccess ilightaccess, PlayerChunkMap playerchunkmap, boolean flag, ThreadedMailbox threadedmailbox, Mailbox> mailbox) { - super(ilightaccess, true, flag); -- this.d = playerchunkmap; -+ this.d = playerchunkmap; this.playerChunkMap = d; // Paper - this.e = mailbox; - this.b = threadedmailbox; - } -@@ -0,0 +0,0 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - } - - private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) { -- this.e.a(ChunkTaskQueueSorter.a(() -> { -- this.c.add(Pair.of(lightenginethreaded_update, runnable)); -- if (this.c.size() >= this.f) { -- this.b(); -- } -- -- }, ChunkCoordIntPair.pair(i, j), intsupplier)); -+ // Paper start - replace method -+ this.queue.add(ChunkCoordIntPair.pair(i, j), intsupplier, lightenginethreaded_update, runnable); -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - public CompletableFuture a(IChunkAccess ichunkaccess, boolean flag) { - ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos(); - -- ichunkaccess.b(false); -- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> { -+ // Paper start -+ //ichunkaccess.b(false); // Don't need to disable this -+ long pair = chunkcoordintpair.pair(); -+ CompletableFuture future = new CompletableFuture<>(); -+ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair); -+ boolean[] skippedPre = {false}; -+ this.queue.addChunk(pair, prioritySupplier, SystemUtils.a(() -> { -+ if (!isChunkLightStatus(pair)) { -+ future.complete(ichunkaccess); -+ skippedPre[0] = true; -+ return; -+ } -+ // Paper end - ChunkSection[] achunksection = ichunkaccess.getSections(); - - for (int i = 0; i < 16; ++i) { -@@ -0,0 +0,0 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable { - }); - } - -- this.d.c(chunkcoordintpair); -+ // this.d.c(chunkcoordintpair); // Paper - move into post task below - }, () -> { - return "lightChunk " + chunkcoordintpair + " " + flag; -- })); -- return CompletableFuture.supplyAsync(() -> { -+ // Paper start - merge the 2 together -+ }), () -> { -+ this.d.c(chunkcoordintpair); // Paper - release light tickets as post task to ensure they stay loaded until fully done -+ if (skippedPre[0]) return; // Paper - future's already complete - ichunkaccess.b(true); - super.b(chunkcoordintpair, false); -- return ichunkaccess; -- }, (runnable) -> { -- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.POST_UPDATE, runnable); -+ // Paper start -+ future.complete(ichunkaccess); - }); -+ return future; -+ // Paper end - } - - public void queueUpdate() { -- if ((!this.c.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { -+ if ((!this.queue.isEmpty() || super.a()) && this.g.compareAndSet(false, true)) { // Paper - this.b.a((() -> { // Paper - decompile error - this.b(); - this.g.set(false); -+ queueUpdate(); // Paper - if we still have work to do, do it! - })); - } - - } - -+ // Paper start - replace impl -+ private final java.util.List pre = new java.util.ArrayList<>(); -+ private final java.util.List post = new java.util.ArrayList<>(); - private void b() { -- int i = Math.min(this.c.size(), this.f); -- ObjectListIterator> objectlistiterator = this.c.iterator(); -- -- Pair pair; -- int j; -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -+ if (queue.poll(pre, post)) { -+ pre.forEach(Runnable::run); -+ pre.clear(); -+ super.a(Integer.MAX_VALUE, true, true); -+ post.forEach(Runnable::run); -+ post.clear(); -+ } else { -+ // might have level updates to go still -+ super.a(Integer.MAX_VALUE, true, true); - } -- -- objectlistiterator.back(j); -- super.a(Integer.MAX_VALUE, true, true); -- -- for (j = 0; objectlistiterator.hasNext() && j < i; ++j) { -- pair = (Pair) objectlistiterator.next(); -- if (pair.getFirst() == LightEngineThreaded.Update.POST_UPDATE) { -- ((Runnable) pair.getSecond()).run(); -- } -- -- objectlistiterator.remove(); -- } -- -+ // Paper end - } - - public void a(int i) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY; - } - chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority); -+ chunkMap.world.getChunkProvider().getLightEngine().queue.changePriority(location.pair(), getCurrentPriority(), priority); - } - if (getCurrentPriority() != priority) { - this.u.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.storage.RegionFile; - import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; - import net.minecraft.world.level.storage.Convertable; -+import net.minecraft.world.level.storage.WorldDataServer; - import net.minecraft.world.level.storage.WorldPersistentData; - import net.minecraft.world.phys.Vec3D; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - // Paper end - -+ private final java.util.concurrent.ExecutorService lightThread; - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); - //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - Mailbox mailbox = Mailbox.a("main", iasynctaskhandler::a); - - this.worldLoadListener = worldloadlistener; -- ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(executor, "light"); // Paper -+ // Paper start - use light thread -+ ThreadedMailbox lightthreaded; ThreadedMailbox threadedmailbox1 = lightthreaded = ThreadedMailbox.a(lightThread = java.util.concurrent.Executors.newSingleThreadExecutor(r -> { -+ Thread thread = new Thread(r); -+ thread.setName(((WorldDataServer)world.getWorldData()).getName() + " - Light"); -+ thread.setDaemon(true); -+ thread.setPriority(Thread.NORM_PRIORITY+1); -+ return thread; -+ }), "light"); -+ // Paper end - - this.p = new ChunkTaskQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); - this.mailboxWorldGen = this.p.a(threadedmailbox, false); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper end - } - -+ protected final IntSupplier getPrioritySupplier(long i) { return c(i); } // Paper - OBFHELPER - protected IntSupplier c(long i) { - return () -> { - PlayerChunk playerchunk = this.getVisibleChunk(i); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - @Override - public void close() throws IOException { - try { -+ this.lightThread.shutdown(); // Paper - this.p.close(); - this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line - this.m.close(); -diff --git a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -+++ b/src/main/java/net/minecraft/util/thread/ThreadedMailbox.java -@@ -0,0 +0,0 @@ public class ThreadedMailbox implements Mailbox, AutoCloseable, Runnable { - - } - -- @Override -+ -+ public final void queue(T t0) { a(t0); } @Override // Paper - OBFHELPER - public void a(T t0) { - this.a.a(t0); - this.f(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -0,0 +0,0 @@ import net.minecraft.server.MCUtil; - public class NibbleArray { - - // Paper start -+ public static final NibbleArray EMPTY_NIBBLE_ARRAY = new NibbleArray() { -+ @Override -+ public byte[] asBytes() { -+ throw new IllegalStateException(); -+ } -+ }; -+ public long lightCacheKey = Long.MIN_VALUE; - public static byte[] EMPTY_NIBBLE = new byte[2048]; - private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); - private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -@@ -0,0 +0,0 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int k = (int) ((i << 52) >> 52); -+ int l = (int) ((i << 26) >> 38); -+ // Paper end - IBlockAccess iblockaccess = this.a.c(j >> 4, l >> 4); - - return iblockaccess != null ? iblockaccess.g(this.f.d(j, k, l)) : 0; -@@ -0,0 +0,0 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { - return k; - } else { -- int l = Integer.signum(BlockPosition.b(j) - BlockPosition.b(i)); -- int i1 = Integer.signum(BlockPosition.c(j) - BlockPosition.c(i)); -- int j1 = Integer.signum(BlockPosition.d(j) - BlockPosition.d(i)); -+ // Paper start - reuse math - credit to JellySquid for idea -+ int jx = (int) (j >> 38); -+ int jy = (int) ((j << 52) >> 52); -+ int jz = (int) ((j << 26) >> 38); -+ int ix = (int) (i >> 38); -+ int iy = (int) ((i << 52) >> 52); -+ int iz = (int) ((i << 26) >> 38); -+ int l = Integer.signum(jx - ix); -+ int i1 = Integer.signum(jy - iy); -+ int j1 = Integer.signum(jz - iz); -+ // Paper end - EnumDirection enumdirection = EnumDirection.a(l, i1, j1); - - if (enumdirection == null) { - return 15; - } else { - //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded -- IBlockData iblockdata = this.a(j, mutableint); -- -- if (mutableint.getValue() >= 15) { -+ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); // Paper -+ int blockedLight = mutableint.getValue(); // Paper -+ if (blockedLight >= 15) { // Paper - return 15; - } else { -- IBlockData iblockdata1 = this.a(i, (MutableInt) null); -+ IBlockData iblockdata1 = this.getBlockOptimized(ix, iy, iz); // Paper - VoxelShape voxelshape = this.a(iblockdata1, i, enumdirection); - VoxelShape voxelshape1 = this.a(iblockdata, j, enumdirection.opposite()); - -- return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, mutableint.getValue()); -+ return VoxelShapes.b(voxelshape, voxelshape1) ? 15 : k + Math.max(1, blockedLight); // Paper - } - } - } -@@ -0,0 +0,0 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(x, y, z); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineBlock.e; - int l = aenumdirection.length; - - for (int i1 = 0; i1 < l; ++i1) { - EnumDirection enumdirection = aenumdirection[i1]; -- long j1 = BlockPosition.a(i, enumdirection); -- long k1 = SectionPosition.e(j1); -+ long j1 = BlockPosition.getAdjacent(x, y, z, enumdirection); // Paper -+ long k1 = SectionPosition.blockToSection(j1); // Paper - - if (k == k1 || ((LightEngineStorageBlock) this.c).g(k1)) { - this.b(i, j1, j, flag); -@@ -0,0 +0,0 @@ public final class LightEngineBlock extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineBlock.e; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - EnumDirection enumdirection = aenumdirection[l1]; -- long i2 = BlockPosition.a(i, enumdirection); -+ // Paper start -+ int newX = baseX + enumdirection.getAdjacentX(); -+ int newY = baseY + enumdirection.getAdjacentY(); -+ int newZ = baseZ + enumdirection.getAdjacentZ(); -+ long i2 = BlockPosition.asLong(newX, newY, newZ); - - if (i2 != j) { -- long j2 = SectionPosition.e(i2); -+ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - NibbleArray nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((LightEngineStorageBlock) this.c).a(j2, true); -+ nibblearray1 = ((LightEngineStorageBlock) this.c).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { -- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); -+ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineLayer.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; - import net.minecraft.world.phys.shapes.VoxelShape; -@@ -0,0 +0,0 @@ public abstract class LightEngineLayer, S e - protected final EnumSkyBlock b; - protected final S c; - private boolean f; -- protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); -+ protected final BlockPosition.MutableBlockPosition d = new BlockPosition.MutableBlockPosition(); protected final BlockPosition.MutableBlockPosition pos = d; // Paper - private final long[] g = new long[2]; -- private final IBlockAccess[] h = new IBlockAccess[2]; -+ private final IChunkAccess[] h = new IChunkAccess[2]; // Paper - -+ // Paper start - see fully commented out method below (look for Bedrock) -+ // optimized method with less branching for when scenarios arent needed. -+ // avoid using mutable version if can -+ protected final IBlockData getBlockOptimized(int x, int y, int z, MutableInt mutableint) { -+ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ mutableint.setValue(16); -+ return Blocks.BEDROCK.getBlockData(); -+ } else { -+ this.pos.setValues(x, y, z); -+ IBlockData iblockdata = iblockaccess.getType(x, y, z); -+ mutableint.setValue(iblockdata.b(this.a.getWorld(), this.pos)); -+ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); -+ } -+ } -+ protected final IBlockData getBlockOptimized(int x, int y, int z) { -+ IChunkAccess iblockaccess = this.a(x >> 4, z >> 4); -+ -+ if (iblockaccess == null) { -+ return Blocks.BEDROCK.getBlockData(); -+ } else { -+ IBlockData iblockdata = iblockaccess.getType(x, y, z); -+ return iblockdata.l() && iblockdata.e() ? iblockdata : Blocks.AIR.getBlockData(); -+ } -+ } -+ // Paper end - public LightEngineLayer(ILightAccess ilightaccess, EnumSkyBlock enumskyblock, S s0) { - super(16, 256, 8192); - this.a = ilightaccess; -@@ -0,0 +0,0 @@ public abstract class LightEngineLayer, S e - } - - @Nullable -- private IBlockAccess a(int i, int j) { -+ private IChunkAccess a(int i, int j) { // Paper - long k = ChunkCoordIntPair.pair(i, j); - - for (int l = 0; l < 2; ++l) { -@@ -0,0 +0,0 @@ public abstract class LightEngineLayer, S e - } - } - -- IBlockAccess iblockaccess = this.a.c(i, j); -+ IChunkAccess iblockaccess = (IChunkAccess) this.a.c(i, j); // Paper - - for (int i1 = 1; i1 > 0; --i1) { - this.g[i1] = this.g[i1 - 1]; -@@ -0,0 +0,0 @@ public abstract class LightEngineLayer, S e - Arrays.fill(this.h, (Object) null); - } - -- protected IBlockData a(long i, @Nullable MutableInt mutableint) { -- if (i == Long.MAX_VALUE) { -- if (mutableint != null) { -- mutableint.setValue(0); -- } -- -- return Blocks.AIR.getBlockData(); -- } else { -- int j = SectionPosition.a(BlockPosition.b(i)); -- int k = SectionPosition.a(BlockPosition.d(i)); -- IBlockAccess iblockaccess = this.a(j, k); -- -- if (iblockaccess == null) { -- if (mutableint != null) { -- mutableint.setValue(16); -- } -- -- return Blocks.BEDROCK.getBlockData(); -- } else { -- this.d.g(i); -- IBlockData iblockdata = iblockaccess.getType(this.d); -- boolean flag = iblockdata.l() && iblockdata.e(); -- -- if (mutableint != null) { -- mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); -- } -- -- return flag ? iblockdata : Blocks.AIR.getBlockData(); -- } -- } -- } -+ // Paper start - comment out, see getBlockOptimized -+// protected IBlockData a(long i, @Nullable MutableInt mutableint) { -+// if (i == Long.MAX_VALUE) { -+// if (mutableint != null) { -+// mutableint.setValue(0); -+// } -+// -+// return Blocks.AIR.getBlockData(); -+// } else { -+// int j = SectionPosition.a(BlockPosition.b(i)); -+// int k = SectionPosition.a(BlockPosition.d(i)); -+// IBlockAccess iblockaccess = this.a(j, k); -+// -+// if (iblockaccess == null) { -+// if (mutableint != null) { -+// mutableint.setValue(16); -+// } -+// -+// return Blocks.BEDROCK.getBlockData(); -+// } else { -+// this.d.g(i); -+// IBlockData iblockdata = iblockaccess.getType(this.d); -+// boolean flag = iblockdata.l() && iblockdata.e(); -+// -+// if (mutableint != null) { -+// mutableint.setValue(iblockdata.b(this.a.getWorld(), (BlockPosition) this.d)); -+// } -+// -+// return flag ? iblockdata : Blocks.AIR.getBlockData(); -+// } -+// } -+// } -+ // Paper end - - protected VoxelShape a(IBlockData iblockdata, long i, EnumDirection enumdirection) { - return iblockdata.l() ? iblockdata.a(this.a.getWorld(), this.d.g(i), enumdirection) : VoxelShapes.a(); -@@ -0,0 +0,0 @@ public abstract class LightEngineLayer, S e - return i == Long.MAX_VALUE ? 0 : 15 - this.c.i(i); - } - -+ protected int getNibbleLightInverse(NibbleArray nibblearray, int x, int y, int z) { return 15 - nibblearray.a(x & 15, y & 15, z & 15); } // Paper - x/y/z version of below - protected int a(NibbleArray nibblearray, long i) { -- return 15 - nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); -+ return 15 - nibblearray.a((int) (i >> 38) & 15, (int) ((i << 52) >> 52) & 15, (int) ((i << 26) >> 38) & 15); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.EnumDirection; - import net.minecraft.core.SectionPosition; - import net.minecraft.world.level.EnumSkyBlock; -+import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.chunk.ILightAccess; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -0,0 +0,0 @@ public final class LightEngineSky extends LightEngineLayer= 15) { -+ // Paper start - use x/y/z and optimized block lookup -+ int jx = (int) (j >> 38); -+ int jy = (int) ((j << 52) >> 52); -+ int jz = (int) ((j << 26) >> 38); -+ IBlockData iblockdata = this.getBlockOptimized(jx, jy, jz, mutableint); -+ int blockedLight = mutableint.getValue(); -+ if (blockedLight >= 15) { -+ // Paper end - return 15; - } else { -- int l = BlockPosition.b(i); -- int i1 = BlockPosition.c(i); -- int j1 = BlockPosition.d(i); -- int k1 = BlockPosition.b(j); -- int l1 = BlockPosition.c(j); -- int i2 = BlockPosition.d(j); -- boolean flag = l == k1 && j1 == i2; -- int j2 = Integer.signum(k1 - l); -- int k2 = Integer.signum(l1 - i1); -- int l2 = Integer.signum(i2 - j1); -+ // Paper start - inline math -+ int ix = (int) (i >> 38); -+ int iy = (int) ((i << 52) >> 52); -+ int iz = (int) ((i << 26) >> 38); -+ boolean flag = ix == jx && iz == jz; -+ int j2 = Integer.signum(jx - ix); -+ int k2 = Integer.signum(jy - iy); -+ int l2 = Integer.signum(jz - iz); -+ // Paper end - EnumDirection enumdirection; - - if (i == Long.MAX_VALUE) { -@@ -0,0 +0,0 @@ public final class LightEngineSky extends LightEngineLayer l1; -+ boolean flag1 = i == Long.MAX_VALUE || flag && iy > jy; // Paper rename vars to iy > jy - -- return flag1 && k == 0 && mutableint.getValue() == 0 ? 0 : k + Math.max(1, mutableint.getValue()); -+ return flag1 && k == 0 && blockedLight == 0 ? 0 : k + Math.max(1, blockedLight); // Paper - } - } - } -@@ -0,0 +0,0 @@ public final class LightEngineSky extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ int i1 = baseY & 15; -+ int j1 = baseY >> 4; -+ // Paper end - int k1; - - if (i1 != 0) { -@@ -0,0 +0,0 @@ public final class LightEngineSky extends LightEngineLayer> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j1 = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ NibbleArray nibblearray = this.c.updating.getUpdatingOptimized(j1); -+ // Paper end - EnumDirection[] aenumdirection = LightEngineSky.e; - int k1 = aenumdirection.length; - - for (int l1 = 0; l1 < k1; ++l1) { - EnumDirection enumdirection = aenumdirection[l1]; -- long i2 = BlockPosition.a(i, enumdirection); -- long j2 = SectionPosition.e(i2); -+ // Paper start -+ int newX = baseX + enumdirection.getAdjacentX(); -+ int newY = baseY + enumdirection.getAdjacentY(); -+ int newZ = baseZ + enumdirection.getAdjacentZ(); -+ long i2 = BlockPosition.asLong(newX, newY, newZ); -+ long j2 = SectionPosition.blockPosAsSectionLong(newX, newY, newZ); -+ // Paper end - NibbleArray nibblearray1; - - if (j1 == j2) { - nibblearray1 = nibblearray; - } else { -- nibblearray1 = ((LightEngineStorageSky) this.c).a(j2, true); -+ nibblearray1 = ((LightEngineStorageSky) this.c).updating.getUpdatingOptimized(j2); // Paper - } - - if (nibblearray1 != null) { - if (i2 != j) { -- int k2 = this.b(i2, i, this.a(nibblearray1, i2)); -+ int k2 = this.b(i2, i, this.getNibbleLightInverse(nibblearray1, newX, newY, newZ)); // Paper - - if (l > k2) { - l = k2; -@@ -0,0 +0,0 @@ public final class LightEngineSky extends LightEngineLayer> e - protected final LongSet c = new LongOpenHashSet(); - protected final LongSet d = new LongOpenHashSet(); - protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -- protected final M f; // Paper - diff on change, should be "updating" -+ protected final M f; protected final M updating; // Paper - diff on change, should be "updating" - protected final LongSet g = new LongOpenHashSet(); -- protected final LongSet h = new LongOpenHashSet(); -+ protected final LongSet h = new LongOpenHashSet(); LongSet dirty = h; // Paper - OBFHELPER - protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); - private final LongSet n = new LongOpenHashSet(); - private final LongSet o = new LongOpenHashSet(); -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - protected volatile boolean j; - - protected LightEngineStorage(EnumSkyBlock enumskyblock, ILightAccess ilightaccess, M m0) { -- super(3, 16, 256); -+ super(3, 256, 256); // Paper - bump expected size of level sets to improve collisions and reduce rehashing (seen a lot of it) - this.l = enumskyblock; - this.m = ilightaccess; -- this.f = m0; -+ this.f = m0; updating = m0; // Paper - this.e_visible = m0.b(); // Paper - avoid copying light data - this.e_visible.d(); // Paper - avoid copying light data - } - -- protected boolean g(long i) { -- return this.a(i, true) != null; -+ protected final boolean g(long i) { // Paper - final to help inlining -+ return this.updating.getUpdatingOptimized(i) != null; // Paper - inline to avoid branching - } - - @Nullable - protected NibbleArray a(long i, boolean flag) { - // Paper start - avoid copying light data - if (flag) { -- return this.a(this.f, i); -+ return this.updating.getUpdatingOptimized(i); - } else { - synchronized (this.visibleUpdateLock) { -- return this.a(this.e_visible, i); -+ return this.e_visible.lookup.apply(i); - } - } - // Paper end - avoid copying light data - } - - @Nullable -- protected NibbleArray a(M m0, long i) { -+ protected final NibbleArray a(M m0, long i) { // Paper - return m0.c(i); - } - -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - protected abstract int d(long i); - - protected int i(long i) { -- long j = SectionPosition.e(i); -- NibbleArray nibblearray = this.a(j, true); -+ // Paper start - reuse and inline math, use Optimized Updating path -+ final int x = (int) (i >> 38); -+ final int y = (int) ((i << 52) >> 52); -+ final int z = (int) ((i << 26) >> 38); -+ long j = SectionPosition.blockPosAsSectionLong(x, y, z); -+ NibbleArray nibblearray = this.updating.getUpdatingOptimized(j); -+ // BUG: Sometimes returns null and crashes, try to recover, but to prevent crash just return no light. -+ if (nibblearray == null) { -+ nibblearray = this.e_visible.lookup.apply(j); -+ } -+ if (nibblearray == null) { -+ System.err.println("Null nibble, preventing crash " + BlockPosition.fromLong(i)); -+ return 0; -+ } - -- return nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i))); -+ return nibblearray.a(x & 15, y & 15, z & 15); // Paper - inline operations -+ // Paper end - } - - protected void b(long i, int j) { -- long k = SectionPosition.e(i); -+ // Paper start - cache part of the math done in loop below -+ int x = (int) (i >> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ long k = SectionPosition.blockPosAsSectionLong(x, y, z); -+ // Paper end - - if (this.g.add(k)) { - this.f.a(k); - } - - NibbleArray nibblearray = this.a(k, true); -- -- nibblearray.a(SectionPosition.b(BlockPosition.b(i)), SectionPosition.b(BlockPosition.c(i)), SectionPosition.b(BlockPosition.d(i)), j); -- -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); -+ nibblearray.a(x & 15, y & 15, z & 15, j); // Paper - use already calculated x/y/z -+ -+ // Paper start - credit to JellySquid for a major optimization here: -+ /* -+ * An extremely important optimization is made here in regards to adding items to the pending notification set. The -+ * original implementation attempts to add the coordinate of every chunk which contains a neighboring block position -+ * even though a huge number of loop iterations will simply map to block positions within the same updating chunk. -+ * -+ * Our implementation here avoids this by pre-calculating the min/max chunk coordinates so we can iterate over only -+ * the relevant chunk positions once. This reduces what would always be 27 iterations to just 1-8 iterations. -+ * -+ * @reason Use faster implementation -+ * @author JellySquid -+ */ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - } - - if (k >= 2 && j != 2) { -- if (this.p.contains(i)) { -- this.p.remove(i); -- } else { -+ if (!this.p.remove(i)) { // Paper - remove useless contains - credit to JellySquid -+ //this.p.remove(i); // Paper -+ //} else { // Paper - this.f.a(i, this.j(i)); - this.g.add(i); - this.k(i); - -- for (int l = -1; l <= 1; ++l) { -- for (int i1 = -1; i1 <= 1; ++i1) { -- for (int j1 = -1; j1 <= 1; ++j1) { -- this.h.add(SectionPosition.e(BlockPosition.a(i, i1, j1, l))); -+ // Paper start - reuse x/y/z and only notify valid chunks - Credit to JellySquid (See above method for notes) -+ int x = (int) (i >> 38); -+ int y = (int) ((i << 52) >> 52); -+ int z = (int) ((i << 26) >> 38); -+ -+ for (int z2 = (z - 1) >> 4; z2 <= (z + 1) >> 4; ++z2) { -+ for (int x2 = (x - 1) >> 4; x2 <= (x + 1) >> 4; ++x2) { -+ for (int y2 = (y - 1) >> 4; y2 <= (y + 1) >> 4; ++y2) { -+ this.dirty.add(SectionPosition.asLong(x2, y2, z2)); -+ // Paper end - } - } - } -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - return SectionPosition.e(j) == i; - }); - } else { -- int j = SectionPosition.c(SectionPosition.b(i)); -- int k = SectionPosition.c(SectionPosition.c(i)); -- int l = SectionPosition.c(SectionPosition.d(i)); -+ int j = (int) (i >> 42) << 4; // Paper - inline -+ int k = (int) (i << 44 >> 44) << 4; // Paper - inline -+ int l = (int) (i << 22 >> 42) << 4; // Paper - inline - - for (int i1 = 0; i1 < 16; ++i1) { - for (int j1 = 0; j1 < 16; ++j1) { -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - NibbleArray nibblearray; - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.a(lightenginelayer, i); - NibbleArray nibblearray1 = (NibbleArray) this.i.remove(i); - -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - longiterator = this.p.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.l(i); - } - -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - Entry entry; - long j; - -+ NibbleArray test = null; // Paper - while (objectiterator.hasNext()) { - entry = (Entry) objectiterator.next(); - j = entry.getLongKey(); -- if (this.g(j)) { -+ if ((test = this.updating.getUpdatingOptimized(j)) != null) { // Paper - dont look up nibble twice - nibblearray = (NibbleArray) entry.getValue(); -- if (this.f.c(j) != nibblearray) { -+ if (test != nibblearray) { // Paper - this.a(lightenginelayer, j); - this.f.a(j, nibblearray); - this.g.add(j); -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - longiterator = this.i.keySet().iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.b(lightenginelayer, i); - } - } else { - longiterator = this.n.iterator(); - - while (longiterator.hasNext()) { -- i = (Long) longiterator.next(); -+ i = longiterator.nextLong(); // Paper - this.b(lightenginelayer, i); - } - } -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - - private void b(LightEngineLayer lightenginelayer, long i) { - if (this.g(i)) { -- int j = SectionPosition.c(SectionPosition.b(i)); -- int k = SectionPosition.c(SectionPosition.c(i)); -- int l = SectionPosition.c(SectionPosition.d(i)); -+ // Paper start -+ int secX = (int) (i >> 42); -+ int secY = (int) (i << 44 >> 44); -+ int secZ = (int) (i << 22 >> 42); -+ int j = secX << 4; // baseX -+ int k = secY << 4; // baseY -+ int l = secZ << 4; // baseZ -+ // Paper end - EnumDirection[] aenumdirection = LightEngineStorage.k; - int i1 = aenumdirection.length; - - for (int j1 = 0; j1 < i1; ++j1) { - EnumDirection enumdirection = aenumdirection[j1]; -- long k1 = SectionPosition.a(i, enumdirection); -+ long k1 = SectionPosition.getAdjacentFromSectionPos(secX, secY, secZ, enumdirection); // Paper - avoid extra unpacking - - if (!this.i.containsKey(k1) && this.g(k1)) { - for (int l1 = 0; l1 < 16; ++l1) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.NibbleArray; - - public abstract class LightEngineStorageArray> { - -- private final long[] b = new long[2]; -- private final NibbleArray[] c = new NibbleArray[2]; -+ // private final long[] b = new long[2]; // Paper - unused -+ private final NibbleArray[] c = new NibbleArray[]{NibbleArray.EMPTY_NIBBLE_ARRAY, NibbleArray.EMPTY_NIBBLE_ARRAY}; private final NibbleArray[] cache = c; // Paper - OBFHELPER - private boolean d; - protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data - protected final boolean isVisible; // Paper - avoid copying light data -- java.util.function.Function lookup; // Paper - faster branchless lookup - -+ // Paper start - faster lookups with less branching, use interface to avoid boxing instead of Function -+ public final NibbleArrayAccess lookup; -+ public interface NibbleArrayAccess { -+ NibbleArray apply(long id); -+ } -+ // Paper end - // Paper start - avoid copying light data - protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { - if (isVisible) { -@@ -0,0 +0,0 @@ public abstract class LightEngineStorageArray 0; --k) { -- this.b[k] = this.b[k - 1]; -- this.c[k] = this.c[k - 1]; -- } -- -- this.b[0] = i; -- this.c[0] = nibblearray; -- } -- -+ cache[1] = cache[0]; -+ cache[0] = nibblearray; - return nibblearray; - } - } -+ // Paper end -+ -+ @Nullable -+ public final NibbleArray c(final long i) { // Paper - final -+ // Paper start - optimize visible case or missed updating cases -+ if (this.d) { -+ // short circuit to optimized -+ return getUpdatingOptimized(i); -+ } -+ -+ return this.lookup.apply(i); -+ // Paper end -+ } - - @Nullable - public NibbleArray d(long i) { -@@ -0,0 +0,0 @@ public abstract class LightEngineStorageArray> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j = (((long) (baseX >> 4) & 4194303L) << 42) | (((long) (baseY >> 4) & 1048575L)) | (((long) (baseZ >> 4) & 4194303L) << 20); -+ NibbleArray nibblearray = this.e_visible.lookup.apply(j); -+ return nibblearray == null ? 0 : nibblearray.a(baseX & 15, baseY & 15, baseZ & 15); -+ // Paper end - } - - public static final class a extends LightEngineStorageArray { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage> 38); -+ int baseY = (int) ((i << 52) >> 52); -+ int baseZ = (int) ((i << 26) >> 38); -+ long j = SectionPosition.blockPosAsSectionLong(baseX, baseY, baseZ); -+ // Paper end - int k = SectionPosition.c(j); - synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage> 52) & 15, (int) baseZ & 15); // Paper - y changed above - } else { - return 15; - } -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - j = this.c(i); - if (j != 2 && !this.n.contains(i) && this.l.add(i)) { - int l; -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage> 42) << 4; // Paper -+ int baseY = (int) (i << 44 >> 44) << 4; // Paper -+ int baseZ = (int) (i << 22 >> 42) << 4; // Paper - if (this.l.remove(i) && this.g(i)) { - for (j = 0; j < 16; ++j) { - for (k = 0; k < 16; ++k) { -- long l3 = BlockPosition.a(SectionPosition.c(SectionPosition.b(i)) + j, SectionPosition.c(SectionPosition.c(i)) + 16 - 1, SectionPosition.c(SectionPosition.d(i)) + k); -+ long l3 = BlockPosition.a(baseX + j, baseY + 16 - 1, baseZ + k); // Paper - - lightenginelayer.a(Long.MAX_VALUE, l3, 15, false); - } diff --git a/Spigot-Server-Patches/Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/Spigot-Server-Patches/Optimize-Network-Manager-and-add-advanced-packet-sup.patch deleted file mode 100644 index ec3b801ce4..0000000000 --- a/Spigot-Server-Patches/Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ /dev/null @@ -1,390 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 04:53:35 -0400 -Subject: [PATCH] Optimize Network Manager and add advanced packet support - -Adds ability for 1 packet to bundle other packets to follow it -Adds ability for a packet to delay sending more packets until a state is ready. - -Removes synchronization from sending packets -Removes processing packet queue off of main thread - - for the few cases where it is allowed, order is not necessary nor - should it even be happening concurrently in first place (handshaking/login/status) - -Ensures packets sent asynchronously are dispatched on main thread - -This helps ensure safety for ProtocolLib as packet listeners -are commonly accessing world state. This will allow you to schedule -a packet to be sent async, but itll be dispatched sync for packet -listeners to process. - -This should solve some deadlock risks - -Also adds Netty Channel Flush Consolidation to reduce the amount of flushing - -Also avoids spamming closed channel exception by rechecking closed state in dispatch -and then catch exceptions and close if they fire. - -Part of this commit was authored by: Spottedleaf - -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/NetworkManager.java -+++ b/src/main/java/net/minecraft/network/NetworkManager.java -@@ -0,0 +0,0 @@ import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.EnumProtocolDirection; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketPlayOutBoss; -+import net.minecraft.network.protocol.game.PacketPlayOutChat; -+import net.minecraft.network.protocol.game.PacketPlayOutKeepAlive; - import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; -+import net.minecraft.network.protocol.game.PacketPlayOutTabComplete; -+import net.minecraft.network.protocol.game.PacketPlayOutTitle; - import net.minecraft.server.CancelledPacketHandleException; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.network.LoginListener; - import net.minecraft.server.network.PlayerConnection; - import net.minecraft.util.LazyInitVar; -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - public int protocolVersion; - public java.net.InetSocketAddress virtualHost; - private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); -+ // Optimize network -+ public boolean isPending = true; -+ public boolean queueImmunity = false; -+ public EnumProtocol protocol; - // Paper end - - public NetworkManager(EnumProtocolDirection enumprotocoldirection) { -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } - - public void setProtocol(EnumProtocol enumprotocol) { -+ protocol = enumprotocol; // Paper - this.channel.attr(NetworkManager.c).set(enumprotocol); - this.channel.config().setAutoRead(true); - NetworkManager.LOGGER.debug("Enabled auto read"); -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - Validate.notNull(packetlistener, "packetListener", new Object[0]); - this.packetListener = packetlistener; - } -+ // Paper start -+ public EntityPlayer getPlayer() { -+ if (packetListener instanceof PlayerConnection) { -+ return ((PlayerConnection) packetListener).player; -+ } else { -+ return null; -+ } -+ } -+ private static class InnerUtil { // Attempt to hide these methods from ProtocolLib so it doesn't accidently pick them up. -+ private static java.util.List buildExtraPackets(Packet packet) { -+ java.util.List extra = packet.getExtraPackets(); -+ if (extra == null || extra.isEmpty()) { -+ return null; -+ } -+ java.util.List ret = new java.util.ArrayList<>(1 + extra.size()); -+ buildExtraPackets0(extra, ret); -+ return ret; -+ } -+ -+ private static void buildExtraPackets0(java.util.List extraPackets, java.util.List into) { -+ for (Packet extra : extraPackets) { -+ into.add(extra); -+ java.util.List extraExtra = extra.getExtraPackets(); -+ if (extraExtra != null && !extraExtra.isEmpty()) { -+ buildExtraPackets0(extraExtra, into); -+ } -+ } -+ } -+ // Paper start -+ private static boolean canSendImmediate(NetworkManager networkManager, Packet packet) { -+ return networkManager.isPending || networkManager.protocol != EnumProtocol.PLAY || -+ packet instanceof PacketPlayOutKeepAlive || -+ packet instanceof PacketPlayOutChat || -+ packet instanceof PacketPlayOutTabComplete || -+ packet instanceof PacketPlayOutTitle || -+ packet instanceof PacketPlayOutBoss; -+ } -+ // Paper end -+ } -+ // Paper end - - public void sendPacket(Packet packet) { - this.sendPacket(packet, (GenericFutureListener) null); - } - - public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { -- if (this.isConnected()) { -- this.p(); -- this.b(packet, genericfuturelistener); -- } else { -- this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); -+ // Paper start - handle oversized packets better -+ boolean connected = this.isConnected(); -+ if (!connected && !preparing) { -+ return; // Do nothing -+ } -+ packet.onPacketDispatch(getPlayer()); -+ if (connected && (InnerUtil.canSendImmediate(this, packet) || ( -+ MCUtil.isMainThread() && packet.isReady() && this.packetQueue.isEmpty() && -+ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) -+ ))) { -+ this.dispatchPacket(packet, genericfuturelistener); -+ return; - } -+ // write the packets to the queue, then flush - antixray hooks there already -+ java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); -+ boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); -+ if (!hasExtraPackets) { -+ this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); -+ } else { -+ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); -+ packets.add(new NetworkManager.QueuedPacket(packet, null)); // delay the future listener until the end of the extra packets -+ -+ for (int i = 0, len = extraPackets.size(); i < len;) { -+ Packet extra = extraPackets.get(i); -+ boolean end = ++i == len; -+ packets.add(new NetworkManager.QueuedPacket(extra, end ? genericfuturelistener : null)); // append listener to the end -+ } - -+ this.packetQueue.addAll(packets); // atomic -+ } -+ this.sendPacketQueue(); -+ // Paper end - } - - private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - this.channel.config().setAutoRead(false); - } - -+ EntityPlayer player = getPlayer(); // Paper - if (this.channel.eventLoop().inEventLoop()) { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - - ChannelFuture channelfuture = this.channel.writeAndFlush(packet); - - if (genericfuturelistener != null) { - channelfuture.addListener(genericfuturelistener); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - } else { - this.channel.eventLoop().execute(() -> { - if (enumprotocol != enumprotocol1) { - this.setProtocol(enumprotocol); - } - -+ // Paper start -+ if (!isConnected()) { -+ packet.onPacketDispatchFinish(player, null); -+ return; -+ } -+ try { -+ // Paper end - ChannelFuture channelfuture1 = this.channel.writeAndFlush(packet); - -+ - if (genericfuturelistener != null) { - channelfuture1.addListener(genericfuturelistener); - } -+ // Paper start -+ if (packet.hasFinishListener()) { -+ channelfuture1.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); -+ } -+ // Paper end - - channelfuture1.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); -+ // Paper start -+ } catch (Exception e) { -+ LOGGER.error("NetworkException: " + player, e); -+ close(new ChatMessage("disconnect.genericReason", "Internal Exception: " + e.getMessage()));; -+ packet.onPacketDispatchFinish(player, null); -+ } -+ // Paper end - }); - } - - } - -- private void sendPacketQueue() { this.p(); } // Paper - OBFHELPER -- private void p() { -- if (this.channel != null && this.channel.isOpen()) { -- Queue queue = this.packetQueue; -- -+ // Paper start - rewrite this to be safer if ran off main thread -+ private boolean sendPacketQueue() { return this.p(); } // OBFHELPER // void -> boolean -+ private boolean p() { // void -> boolean -+ if (!isConnected()) { -+ return true; -+ } -+ if (MCUtil.isMainThread()) { -+ return processQueue(); -+ } else if (isPending) { -+ // Should only happen during login/status stages - synchronized (this.packetQueue) { -- NetworkManager.QueuedPacket networkmanager_queuedpacket; -- -- while ((networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.packetQueue.poll()) != null) { -- this.b(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); -- } -+ return this.processQueue(); -+ } -+ } -+ return false; -+ } -+ private boolean processQueue() { -+ if (this.packetQueue.isEmpty()) return true; -+ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore -+ // But if we are not on main due to login/status, the parent is synchronized on packetQueue -+ java.util.Iterator iterator = this.packetQueue.iterator(); -+ while (iterator.hasNext()) { -+ NetworkManager.QueuedPacket queued = iterator.next(); // poll -> peek -+ -+ // Fix NPE (Spigot bug caused by handleDisconnection()) -+ if (queued == null) { -+ return true; -+ } - -+ Packet packet = queued.getPacket(); -+ if (!packet.isReady()) { -+ return false; -+ } else { -+ iterator.remove(); -+ this.dispatchPacket(packet, queued.getGenericFutureListener()); - } - } -+ return true; - } -+ // Paper end - - public void a() { - this.p(); -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - return this.socketAddress; - } - -+ // Paper start -+ public void clearPacketQueue() { -+ EntityPlayer player = getPlayer(); -+ packetQueue.forEach(queuedPacket -> { -+ Packet packet = queuedPacket.getPacket(); -+ if (packet.hasFinishListener()) { -+ packet.onPacketDispatchFinish(player, null); -+ } -+ }); -+ packetQueue.clear(); -+ } // Paper end - public void close(IChatBaseComponent ichatbasecomponent) { - // Spigot Start - this.preparing = false; -+ clearPacketQueue(); // Paper - // Spigot End - if (this.channel.isOpen()) { - this.channel.close(); // We can't wait as this may be called from an event loop. -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - public void handleDisconnection() { - if (this.channel != null && !this.channel.isOpen()) { - if (this.o) { -- NetworkManager.LOGGER.warn("handleDisconnection() called twice"); -+ //NetworkManager.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message - } else { - this.o = true; - if (this.k() != null) { -@@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { - } else if (this.j() != null) { - this.j().a(new ChatMessage("multiplayer.disconnect.generic")); - } -- this.packetQueue.clear(); // Free up packet queue. -+ clearPacketQueue(); // Paper - // Paper start - Add PlayerConnectionCloseEvent - final PacketListener packetListener = this.j(); - if (packetListener instanceof PlayerConnection) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -0,0 +0,0 @@ - package net.minecraft.network.protocol; - -+import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.PacketListener; -@@ -0,0 +0,0 @@ public interface Packet { - void a(T t0); - - // Paper start -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ */ -+ default void onPacketDispatch(@javax.annotation.Nullable EntityPlayer player) {} -+ -+ /** -+ * @param player Null if not at PLAY stage yet -+ * @param future Can be null if packet was cancelled -+ */ -+ default void onPacketDispatchFinish(@javax.annotation.Nullable EntityPlayer player, @javax.annotation.Nullable ChannelFuture future) {} -+ default boolean hasFinishListener() { return false; } -+ default boolean isReady() { return true; } -+ default java.util.List getExtraPackets() { return null; } - default boolean packetTooLarge(NetworkManager manager) { - return false; - } -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/ServerConnection.java -+++ b/src/main/java/net/minecraft/server/network/ServerConnection.java -@@ -0,0 +0,0 @@ import io.netty.channel.epoll.EpollServerSocketChannel; - import io.netty.channel.nio.NioEventLoopGroup; - import io.netty.channel.socket.ServerSocketChannel; - import io.netty.channel.socket.nio.NioServerSocketChannel; -+import io.netty.handler.flush.FlushConsolidationHandler; // Paper - import io.netty.handler.timeout.ReadTimeoutHandler; - import java.io.IOException; - import java.net.InetAddress; -@@ -0,0 +0,0 @@ public class ServerConnection { - private final List connectedChannels = Collections.synchronizedList(Lists.newArrayList()); - // Paper start - prevent blocking on adding a new network manager while the server is ticking - private final java.util.Queue pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); -+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - private void addPending() { - NetworkManager manager = null; - while ((manager = pending.poll()) != null) { - connectedChannels.add(manager); -+ manager.isPending = false; - } - } - // Paper end -@@ -0,0 +0,0 @@ public class ServerConnection { - ; - } - -+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new FlushConsolidationHandler()); // Paper - channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(ServerConnection.this)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder(EnumProtocolDirection.SERVERBOUND)).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder(EnumProtocolDirection.CLIENTBOUND)); - int j = ServerConnection.this.e.k(); - Object object = j > 0 ? new NetworkManagerServer(j) : new NetworkManager(EnumProtocolDirection.SERVERBOUND); diff --git a/Spigot-Server-Patches/Optimize-NetworkManager-Exception-Handling.patch b/Spigot-Server-Patches/Optimize-NetworkManager-Exception-Handling.patch deleted file mode 100644 index 84ee4ff566..0000000000 --- a/Spigot-Server-Patches/Optimize-NetworkManager-Exception-Handling.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Sun, 5 Jul 2020 22:38:18 -0400 -Subject: [PATCH] Optimize NetworkManager Exception Handling - - -diff --git a/src/main/java/net/minecraft/network/EnumProtocol.java b/src/main/java/net/minecraft/network/EnumProtocol.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/EnumProtocol.java -+++ b/src/main/java/net/minecraft/network/EnumProtocol.java -@@ -0,0 +0,0 @@ public enum EnumProtocol { - - @Nullable - public Packet a(int i) { -+ if (i < 0 || i >= this.b.size()) return null; // Paper - Supplier> supplier = (Supplier) this.b.get(i); - - return supplier != null ? (Packet) supplier.get() : null; -diff --git a/src/main/java/net/minecraft/network/PacketSplitter.java b/src/main/java/net/minecraft/network/PacketSplitter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketSplitter.java -+++ b/src/main/java/net/minecraft/network/PacketSplitter.java -@@ -0,0 +0,0 @@ import java.util.List; - - public class PacketSplitter extends ByteToMessageDecoder { - -+ private final byte[] lenBuf = new byte[3]; // Paper - public PacketSplitter() {} - - protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { -+ // Paper start - if channel is not active just discard the packet -+ if (!channelhandlercontext.channel().isActive()) { -+ bytebuf.skipBytes(bytebuf.readableBytes()); -+ return; -+ } -+ // Paper end - bytebuf.markReaderIndex(); -- byte[] abyte = new byte[3]; -+ // Paper start - reuse temporary length buffer -+ byte[] abyte = lenBuf; -+ java.util.Arrays.fill(abyte, (byte) 0); -+ // Paper end - - for (int i = 0; i < abyte.length; ++i) { - if (!bytebuf.isReadable()) { -diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/Packet.java -+++ b/src/main/java/net/minecraft/network/protocol/Packet.java -@@ -0,0 +0,0 @@ package net.minecraft.network.protocol; - - import io.netty.channel.ChannelFuture; // Paper - import java.io.IOException; -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.PacketListener; -+import net.minecraft.server.level.EntityPlayer; - - public interface Packet { - -diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -@@ -0,0 +0,0 @@ - package net.minecraft.network.protocol; - -+import net.minecraft.network.NetworkManager; - import net.minecraft.network.PacketListener; -+import net.minecraft.network.chat.ChatComponentText; -+import net.minecraft.network.protocol.game.PacketPlayOutKickDisconnect; - import net.minecraft.server.CancelledPacketHandleException; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.thread.IAsyncTaskHandler; -@@ -0,0 +0,0 @@ public class PlayerConnectionUtils { - try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.a(t0); - } // Paper - timings -+ // Paper start -+ catch (Exception e) { -+ NetworkManager networkmanager = t0.a(); -+ if (networkmanager.getPlayer() != null) { -+ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getName(), networkmanager.getSocketAddress(), e); -+ } else { -+ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getSocketAddress(), e); -+ } -+ ChatComponentText error = new ChatComponentText("Packet processing error"); -+ networkmanager.sendPacket(new PacketPlayOutKickDisconnect(error), (future) -> { -+ networkmanager.close(error); -+ }); -+ networkmanager.stopReading(); -+ } -+ // Paper end - } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } diff --git a/Spigot-Server-Patches/Optimize-NibbleArray-to-use-pooled-buffers.patch b/Spigot-Server-Patches/Optimize-NibbleArray-to-use-pooled-buffers.patch deleted file mode 100644 index 66204e52c3..0000000000 --- a/Spigot-Server-Patches/Optimize-NibbleArray-to-use-pooled-buffers.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 23:30:30 -0400 -Subject: [PATCH] Optimize NibbleArray to use pooled buffers - -Massively reduces memory allocation of 2048 byte buffers by using -an object pool for these. - -Uses lots of advanced new capabilities of the Paper codebase :) - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutLightUpdate.java -@@ -0,0 +0,0 @@ - package net.minecraft.network.protocol.game; - - import com.google.common.collect.Lists; -+import io.netty.channel.ChannelFuture; // Paper -+ - import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.SectionPosition; - import net.minecraft.network.PacketDataSerializer; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumSkyBlock; - import net.minecraft.world.level.chunk.NibbleArray; -@@ -0,0 +0,0 @@ public class PacketPlayOutLightUpdate implements Packet { - private List h; - private boolean i; - -+ // Paper start -+ java.lang.Runnable cleaner1; -+ java.lang.Runnable cleaner2; -+ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); -+ -+ @Override -+ public void onPacketDispatch(EntityPlayer player) { -+ remainingSends.incrementAndGet(); -+ } -+ -+ @Override -+ public void onPacketDispatchFinish(EntityPlayer player, ChannelFuture future) { -+ if (remainingSends.decrementAndGet() <= 0) { -+ // incase of any race conditions, schedule this delayed -+ MCUtil.scheduleTask(5, () -> { -+ if (remainingSends.get() == 0) { -+ cleaner1.run(); -+ cleaner2.run(); -+ } -+ }, "Light Packet Release"); -+ } -+ } -+ -+ @Override -+ public boolean hasFinishListener() { -+ return true; -+ } -+ -+ // Paper end - public PacketPlayOutLightUpdate() {} - - public PacketPlayOutLightUpdate(ChunkCoordIntPair chunkcoordintpair, LightEngine lightengine, boolean flag) { - this.a = chunkcoordintpair.x; - this.b = chunkcoordintpair.z; - this.i = flag; -- this.g = Lists.newArrayList(); -- this.h = Lists.newArrayList(); -+ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -+ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper - - for (int i = 0; i < 18; ++i) { - NibbleArray nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + i)); -@@ -0,0 +0,0 @@ public class PacketPlayOutLightUpdate implements Packet { - this.e |= 1 << i; - } else { - this.c |= 1 << i; -- this.g.add(nibblearray.asBytes().clone()); -+ this.g.add(nibblearray.getCloneIfSet()); // Paper - } - } - -@@ -0,0 +0,0 @@ public class PacketPlayOutLightUpdate implements Packet { - this.f |= 1 << i; - } else { - this.d |= 1 << i; -- this.h.add(nibblearray1.asBytes().clone()); -+ this.h.add(nibblearray1.getCloneIfSet()); // Paper - } - } - } -@@ -0,0 +0,0 @@ public class PacketPlayOutLightUpdate implements Packet { - this.i = flag; - this.c = i; - this.d = j; -- this.g = Lists.newArrayList(); -- this.h = Lists.newArrayList(); -+ this.g = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.g, NibbleArray::releaseBytes); // Paper -+ this.h = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.h, NibbleArray::releaseBytes); // Paper - - for (int k = 0; k < 18; ++k) { - NibbleArray nibblearray; -@@ -0,0 +0,0 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.c & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.SKY).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.g.add(nibblearray.asBytes().clone()); -+ this.g.add(nibblearray.getCloneIfSet()); // Paper - } else { - this.c &= ~(1 << k); - if (nibblearray != null) { -@@ -0,0 +0,0 @@ public class PacketPlayOutLightUpdate implements Packet { - if ((this.d & 1 << k) != 0) { - nibblearray = lightengine.a(EnumSkyBlock.BLOCK).a(SectionPosition.a(chunkcoordintpair, -1 + k)); - if (nibblearray != null && !nibblearray.c()) { -- this.h.add(nibblearray.asBytes().clone()); -+ this.h.add(nibblearray.getCloneIfSet()); // Paper - } else { - this.d &= ~(1 << k); - if (nibblearray != null) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -+++ b/src/main/java/net/minecraft/world/level/chunk/NibbleArray.java -@@ -0,0 +0,0 @@ - // mc-dev import - package net.minecraft.world.level.chunk; - -+import com.destroystokyo.paper.util.pooled.PooledObjects; // Paper -+ -+import javax.annotation.Nonnull; - import javax.annotation.Nullable; - import net.minecraft.SystemUtils; -+import net.minecraft.server.MCUtil; - - public class NibbleArray { - -- @Nullable -- protected byte[] a; -+ // Paper start -+ public static byte[] EMPTY_NIBBLE = new byte[2048]; -+ private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072); -+ private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8)); -+ public static final PooledObjects BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); -+ public static void releaseBytes(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { -+ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); -+ BYTE_2048.release(bytes); -+ } -+ } -+ -+ public NibbleArray markPoolSafe(byte[] bytes) { -+ if (bytes != EMPTY_NIBBLE) this.a = bytes; -+ return markPoolSafe(); -+ } -+ public NibbleArray markPoolSafe() { -+ poolSafe = true; -+ return this; -+ } -+ public byte[] getIfSet() { -+ return this.a != null ? this.a : EMPTY_NIBBLE; -+ } -+ public byte[] getCloneIfSet() { -+ if (a == null) { -+ return EMPTY_NIBBLE; -+ } -+ byte[] ret = BYTE_2048.acquire(); -+ System.arraycopy(getIfSet(), 0, ret, 0, 2048); -+ return ret; -+ } -+ -+ public NibbleArray cloneAndSet(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE) { -+ this.a = BYTE_2048.acquire(); -+ System.arraycopy(bytes, 0, this.a, 0, 2048); -+ } -+ return this; -+ } -+ boolean poolSafe = false; -+ public java.lang.Runnable cleaner; -+ private void registerCleaner() { -+ if (!poolSafe) { -+ cleaner = MCUtil.registerCleaner(this, this.a, NibbleArray::releaseBytes); -+ } else { -+ cleaner = MCUtil.once(() -> NibbleArray.releaseBytes(this.a)); -+ } -+ } -+ // Paper end -+ @Nullable protected byte[] a; -+ - - public NibbleArray() {} - - public NibbleArray(byte[] abyte) { -+ // Paper start -+ this(abyte, false); -+ } -+ public NibbleArray(byte[] abyte, boolean isSafe) { - this.a = abyte; -+ if (!isSafe) this.a = getCloneIfSet(); // Paper - clone for safety -+ registerCleaner(); -+ // Paper end - if (abyte.length != 2048) { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); - } -@@ -0,0 +0,0 @@ public class NibbleArray { - - public void a(int i, int j) { // PAIL: private -> public - if (this.a == null) { -- this.a = new byte[2048]; -+ this.a = BYTE_2048.acquire(); // Paper -+ registerCleaner();// Paper - } - - int k = this.d(i); -@@ -0,0 +0,0 @@ public class NibbleArray { - public byte[] asBytes() { - if (this.a == null) { - this.a = new byte[2048]; -+ } else { // Paper start -+ // Accessor may need this object past garbage collection so need to clone it and return pooled value -+ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() -+ Runnable cleaner = this.cleaner; -+ if (cleaner != null) { -+ this.a = this.a.clone(); -+ cleaner.run(); // release the previously pooled value -+ this.cleaner = null; -+ } -+ } -+ // Paper end -+ -+ return this.a; -+ } -+ -+ @Nonnull -+ public byte[] asBytesPoolSafe() { -+ if (this.a == null) { -+ this.a = BYTE_2048.acquire(); // Paper -+ registerCleaner(); // Paper - } - -+ //noinspection ConstantConditions - return this.a; - } -+ // Paper end - - public NibbleArray copy() { return this.b(); } // Paper - OBFHELPER - public NibbleArray b() { -- return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone()); -+ return this.a == null ? new NibbleArray() : new NibbleArray(this.a); // Paper - clone in ctor - } - - public String toString() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - } - - if (nibblearray != null && !nibblearray.c()) { -- nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytes()); -+ nbttagcompound2.setByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper - } - - if (nibblearray1 != null && !nibblearray1.c()) { -- nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytes()); -+ nbttagcompound2.setByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper - } - - nbttaglist.add(nbttagcompound2); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - protected NibbleArray j(long i) { - NibbleArray nibblearray = (NibbleArray) this.i.get(i); - -- return nibblearray != null ? nibblearray : new NibbleArray(); -+ return nibblearray != null ? nibblearray : new NibbleArray().markPoolSafe(); // Paper - } - - protected void a(LightEngineLayer lightenginelayer, long i) { -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - - protected void a(long i, @Nullable NibbleArray nibblearray, boolean flag) { - if (nibblearray != null) { -- this.i.put(i, nibblearray); -+ NibbleArray remove = this.i.put(i, nibblearray); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - if (!flag) { - this.n.add(i); - } - } else { -- this.i.remove(i); -+ NibbleArray remove = this.i.remove(i); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - } - - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.lighting; - - import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - import javax.annotation.Nullable; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.level.chunk.NibbleArray; - - public abstract class LightEngineStorageArray> { -@@ -0,0 +0,0 @@ public abstract class LightEngineStorageArray -Date: Tue, 4 Aug 2020 22:24:15 +0200 -Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections - -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. - -I expect us to just drop this patch on next major update and re-apply -it with the IDE again and re-apply the collections optimization. - -Optimize collection by creating a list instead of a set of the key and value. - -This lets us get faster foreach iteration, as well as avoids map lookups on -the values when needed. - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/Pathfinder.java -@@ -0,0 +0,0 @@ public class Pathfinder { - this.d.a(); - this.c.a(chunkcache, entityinsentient); - PathPoint pathpoint = this.c.b(); -- Map map = (Map) set.stream().collect(Collectors.toMap((blockposition) -> { -- return this.c.a((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); -- }, Function.identity())); -+ // Paper start - remove streams - and optimize collection -+ List> map = Lists.newArrayList(); -+ for (BlockPosition blockposition : set) { -+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.c.a((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition)); -+ } -+ // Paper end - PathEntity pathentity = this.a(pathpoint, map, f, i, f1); - - this.c.a(); -@@ -0,0 +0,0 @@ public class Pathfinder { - } - - @Nullable -- private PathEntity a(PathPoint pathpoint, Map map, float f, int i, float f1) { -- Set set = map.keySet(); -+ private PathEntity a(PathPoint pathpoint, List> list, float f, int i, float f1) { // Paper - optimize collection -+ //Set set = map.keySet(); // Paper - - pathpoint.e = 0.0F; -- pathpoint.f = this.a(pathpoint, set); -+ pathpoint.f = this.a(pathpoint, list); // Paper - optimize collection - pathpoint.g = pathpoint.f; - this.d.a(); - this.d.a(pathpoint); - Set set1 = ImmutableSet.of(); - int j = 0; -- Set set2 = Sets.newHashSetWithExpectedSize(set.size()); -+ List> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection - int k = (int) ((float) this.b * f1); - - while (!this.d.e()) { -@@ -0,0 +0,0 @@ public class Pathfinder { - PathPoint pathpoint1 = this.d.c(); - - pathpoint1.i = true; -- Iterator iterator = set.iterator(); -- -- while (iterator.hasNext()) { -- PathDestination pathdestination = (PathDestination) iterator.next(); -+ // Paper start - optimize collection -+ for (int i1 = 0; i1 < list.size(); i1++) { -+ Map.Entry entry = list.get(i1); -+ PathDestination pathdestination = entry.getKey(); - - if (pathpoint1.c((PathPoint) pathdestination) <= (float) i) { - pathdestination.e(); -- set2.add(pathdestination); -+ set2.add(entry); -+ // Paper end - } - } - -@@ -0,0 +0,0 @@ public class Pathfinder { - if (pathpoint2.j < f && (!pathpoint2.c() || f3 < pathpoint2.e)) { - pathpoint2.h = pathpoint1; - pathpoint2.e = f3; -- pathpoint2.f = this.a(pathpoint2, set) * 1.5F; -+ pathpoint2.f = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set - if (pathpoint2.c()) { - this.d.a(pathpoint2, pathpoint2.e + pathpoint2.f); - } else { -@@ -0,0 +0,0 @@ public class Pathfinder { - } - } - -- Optional optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> { -- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), true); -- }).min(Comparator.comparingInt(PathEntity::e)) : set.stream().map((pathdestination1) -> { -- return this.a(pathdestination1.d(), (BlockPosition) map.get(pathdestination1), false); -- }).min(Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e)); -- -- if (!optional.isPresent()) { -- return null; -- } else { -- PathEntity pathentity = (PathEntity) optional.get(); -- -- return pathentity; -+ // Paper start - remove streams - and optimize collection -+ PathEntity best = null; -+ boolean useSet1 = set2.isEmpty(); -+ Comparator comparator = useSet1 ? Comparator.comparingInt(PathEntity::e) -+ : Comparator.comparingDouble(PathEntity::n).thenComparingInt(PathEntity::e); -+ for (Map.Entry entry : useSet1 ? list : set2) { -+ PathEntity pathEntity = this.a(entry.getKey().d(), entry.getValue(), !useSet1); -+ if (best == null || comparator.compare(pathEntity, best) < 0) -+ best = pathEntity; - } -+ return best; -+ // Paper end - } - -- private float a(PathPoint pathpoint, Set set) { -+ private float a(PathPoint pathpoint, List> list) { // Paper - optimize collection - float f = Float.MAX_VALUE; - - float f1; - -- for (Iterator iterator = set.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { -- PathDestination pathdestination = (PathDestination) iterator.next(); -+ // Paper start - optimize collection -+ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper -+ PathDestination pathdestination = list.get(i).getKey(); // Paper -+ // Paper end - - f1 = pathpoint.a(pathdestination); - pathdestination.a(f1, pathpoint); diff --git a/Spigot-Server-Patches/Optimize-Pathfinding.patch b/Spigot-Server-Patches/Optimize-Pathfinding.patch deleted file mode 100644 index 1e2c538960..0000000000 --- a/Spigot-Server-Patches/Optimize-Pathfinding.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:02:07 -0600 -Subject: [PATCH] Optimize Pathfinding - -Prevents pathfinding from spamming failures for things such as -arrow attacks. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.core.IPosition; - import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER - protected final World b; - @Nullable -- protected PathEntity c; -+ protected PathEntity c; protected final PathEntity getCurrentPath() { return this.c; } // Paper - OBFHELPER - protected double d; - protected int e; - protected int f; -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - return this.a(this.a(d0, d1, d2, 1), d3); - } - -+ // Paper start - optimise pathfinding -+ private int lastFailure = 0; -+ private int pathfindFailures = 0; -+ // Paper end -+ - public boolean a(Entity entity, double d0) { -+ // Paper start - Pathfinding optimizations -+ if (this.pathfindFailures > 10 && this.getCurrentPath() == null && MinecraftServer.currentTick < this.lastFailure + 40) { -+ return false; -+ } -+ // Paper end - PathEntity pathentity = this.a(entity, 1); - -- return pathentity != null && this.a(pathentity, d0); -+ // Paper start - Pathfinding optimizations -+ if (pathentity != null && this.a(pathentity, d0)) { -+ this.lastFailure = 0; -+ this.pathfindFailures = 0; -+ return true; -+ } else { -+ this.pathfindFailures++; -+ this.lastFailure = MinecraftServer.currentTick; -+ return false; -+ } -+ // Paper end - } - - public boolean setDestination(@Nullable PathEntity pathentity, double speed) { return a(pathentity, speed); } // Paper - OBFHELPER diff --git a/Spigot-Server-Patches/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/Spigot-Server-Patches/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch deleted file mode 100644 index 4a251f3698..0000000000 --- a/Spigot-Server-Patches/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 8 Apr 2020 03:06:30 -0400 -Subject: [PATCH] Optimize PlayerChunkMap memory use for visibleChunks - -No longer clones visible chunks which is causing massive memory -allocation issues, likely the source of Humongous Objects on large servers. - -Instead we just synchronize, clear and rebuild, reusing the same object buffers -as before with only 2 small objects created (FastIterator/MapEntry) - -This should result in siginificant memory use reduction and improved GC behavior. - -diff --git a/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/map/Long2ObjectLinkedOpenHashMapFastCopy.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util.map; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+ -+public class Long2ObjectLinkedOpenHashMapFastCopy extends Long2ObjectLinkedOpenHashMap { -+ -+ public void copyFrom(Long2ObjectLinkedOpenHashMapFastCopy map) { -+ if (key.length != map.key.length) { -+ key = null; -+ key = new long[map.key.length]; -+ } -+ if (value.length != map.value.length) { -+ value = null; -+ //noinspection unchecked -+ value = (V[]) new Object[map.value.length]; -+ } -+ if (link.length != map.link.length) { -+ link = null; -+ link = new long[map.link.length]; -+ } -+ System.arraycopy(map.key, 0, this.key, 0, map.key.length); -+ System.arraycopy(map.value, 0, this.value, 0, map.value.length); -+ System.arraycopy(map.link, 0, this.link, 0, map.link.length); -+ this.size = map.size; -+ this.mask = map.mask; -+ this.first = map.first; -+ this.last = map.last; -+ this.n = map.n; -+ this.maxFill = map.maxFill; -+ this.containsNullKey = map.containsNullKey; -+ } -+ -+ @Override -+ public Long2ObjectLinkedOpenHashMapFastCopy clone() { -+ Long2ObjectLinkedOpenHashMapFastCopy clone = (Long2ObjectLinkedOpenHashMapFastCopy) super.clone(); -+ clone.copyFrom(this); -+ return clone; -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MCUtil.java -+++ b/src/main/java/net/minecraft/server/MCUtil.java -@@ -0,0 +0,0 @@ public final class MCUtil { - - WorldServer world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); - PlayerChunkMap chunkMap = world.getChunkProvider().playerChunkMap; -- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunks; -+ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); - ChunkMapDistance chunkMapDistance = chunkMap.chunkDistanceManager; - List allChunks = new ArrayList<>(visibleChunks.values()); - List players = world.players; -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - }; - // Paper end - this.world.timings.chunkTicks.startTiming(); // Paper -- this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... -+ this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - private static final Logger LOGGER = LogManager.getLogger(); - public static final int GOLDEN_TICKET = 33 + ChunkStatus.b(); -- public final Long2ObjectLinkedOpenHashMap updatingChunks = new Long2ObjectLinkedOpenHashMap(); -- public volatile Long2ObjectLinkedOpenHashMap visibleChunks; -+ // Paper start - faster copying -+ public final Long2ObjectLinkedOpenHashMap updatingChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying -+ public final Long2ObjectLinkedOpenHashMap visibleChunks = new ProtectedVisibleChunksMap(); // Paper - faster copying -+ -+ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { -+ @Override -+ public PlayerChunk put(long k, PlayerChunk playerChunk) { -+ throw new UnsupportedOperationException("Updating visible Chunks"); -+ } -+ -+ @Override -+ public PlayerChunk remove(long k) { -+ throw new UnsupportedOperationException("Removing visible Chunks"); -+ } -+ -+ @Override -+ public PlayerChunk get(long k) { -+ return PlayerChunkMap.this.getVisibleChunk(k); -+ } -+ -+ public PlayerChunk safeGet(long k) { -+ return super.get(k); -+ } -+ } -+ // Paper end -+ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only -+ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed - private final Long2ObjectLinkedOpenHashMap pendingUnload; - public final LongSet loadedChunks; // Paper - private -> public - public final WorldServer world; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier supplier, int i, boolean flag) { - super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag); -- this.visibleChunks = this.updatingChunks.clone(); -+ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning - this.pendingUnload = new Long2ObjectLinkedOpenHashMap(); - this.loadedChunks = new LongOpenHashSet(); - this.unloadQueue = new LongOpenHashSet(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return (PlayerChunk) this.updatingChunks.get(i); - } - -+ // Paper start - remove cloning of visible chunks unless accessed as a collection async -+ private static final boolean DEBUG_ASYNC_VISIBLE_CHUNKS = Boolean.getBoolean("paper.debug-async-visible-chunks"); -+ private boolean isIterating = false; -+ private boolean hasPendingVisibleUpdate = false; -+ public void forEachVisibleChunk(java.util.function.Consumer consumer) { -+ org.spigotmc.AsyncCatcher.catchOp("forEachVisibleChunk"); -+ boolean prev = isIterating; -+ isIterating = true; -+ try { -+ for (PlayerChunk value : this.visibleChunks.values()) { -+ consumer.accept(value); -+ } -+ } finally { -+ this.isIterating = prev; -+ if (!this.isIterating && this.hasPendingVisibleUpdate) { -+ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom(this.pendingVisibleChunks); -+ this.pendingVisibleChunks.clear(); -+ this.hasPendingVisibleUpdate = false; -+ } -+ } -+ } -+ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { -+ if (Thread.currentThread() == this.world.serverThread) { -+ return this.visibleChunks; -+ } else { -+ synchronized (this.visibleChunks) { -+ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); -+ if (this.visibleChunksClone == null) { -+ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunks).clone(); -+ } -+ return this.visibleChunksClone; -+ } -+ } -+ } -+ // Paper end -+ - @Nullable - public PlayerChunk getVisibleChunk(long i) { // Paper - protected -> public -- return (PlayerChunk) this.visibleChunks.get(i); -+ // Paper start - mt safe get -+ if (Thread.currentThread() != this.world.serverThread) { -+ synchronized (this.visibleChunks) { -+ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); -+ } -+ } -+ return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i)); -+ // Paper end - } - - protected IntSupplier c(long i) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // Paper end - - protected void save(boolean flag) { -+ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) - if (flag) { -- List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); -+ List list = (List) visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); // Paper - remove cloning of visible chunks - MutableBoolean mutableboolean = new MutableBoolean(); - - do { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - // this.i(); // Paper - nuke IOWorker - PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); - } else { -- this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { -+ visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { - IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error - - if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - if (!this.updatingChunksModified) { - return false; - } else { -- this.visibleChunks = this.updatingChunks.clone(); -+ // Paper start - stop cloning visibleChunks -+ synchronized (this.visibleChunks) { -+ if (isIterating) { -+ hasPendingVisibleUpdate = true; -+ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); -+ } else { -+ hasPendingVisibleUpdate = false; -+ this.pendingVisibleChunks.clear(); -+ ((ProtectedVisibleChunksMap)this.visibleChunks).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunks); -+ this.visibleChunksClone = null; -+ } -+ } -+ // Paper end -+ - this.updatingChunksModified = false; - return true; - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - protected Iterable f() { -- return Iterables.unmodifiableIterable(this.visibleChunks.values()); -+ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper - } - - void a(Writer writer) throws IOException { - CSVWriter csvwriter = CSVWriter.a().a("x").a("z").a("level").a("in_memory").a("status").a("full_status").a("accessible_ready").a("ticking_ready").a("entity_ticking_ready").a("ticket").a("spawning").a("entity_count").a("block_entity_count").a(writer); -- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunks.long2ObjectEntrySet().iterator(); -+ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper - - while (objectbidirectionaliterator.hasNext()) { - Entry entry = (Entry) objectbidirectionaliterator.next(); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - return ret; - } - public int getTileEntityCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - // We don't use the full world tile entity list, so we must iterate chunks - Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; - int size = 0; -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - size += chunk.tileEntities.size(); - } - return size; -+ }); - } - public int getTickableTileEntityCount() { - return world.tileEntityListTick.size(); - } - public int getChunkCount() { -+ return net.minecraft.server.MCUtil.ensureMain(() -> { - int ret = 0; - - for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - } - } - -- return ret; -+ return ret; }); - } - public int getPlayerCount() { - return world.players.size(); -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public Chunk[] getLoadedChunks() { -+ // Paper start -+ if (Thread.currentThread() != world.getMinecraftWorld().serverThread) { -+ synchronized (world.getChunkProvider().playerChunkMap.visibleChunks) { -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; -+ return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); -+ } -+ } -+ // Paper end - Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; - return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.Chunk::getBukkitChunk).toArray(Chunk[]::new); - } diff --git a/Spigot-Server-Patches/Optimize-RegistryID.c.patch b/Spigot-Server-Patches/Optimize-RegistryID.c.patch deleted file mode 100644 index 931e69e468..0000000000 --- a/Spigot-Server-Patches/Optimize-RegistryID.c.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Andrew Steinborn -Date: Mon, 23 Jul 2018 13:08:19 -0400 -Subject: [PATCH] Optimize RegistryID.c() - -This is a frequent hotspot for world loading/saving. - -diff --git a/src/main/java/net/minecraft/util/RegistryID.java b/src/main/java/net/minecraft/util/RegistryID.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/RegistryID.java -+++ b/src/main/java/net/minecraft/util/RegistryID.java -@@ -0,0 +0,0 @@ public class RegistryID implements Registry { - private K[] d; - private int e; - private int f; -+ private java.util.BitSet usedIds; // Paper - - public RegistryID(int i) { - i = (int) ((float) i / 0.8F); - this.b = (K[]) (new Object[i]); // Paper - decompile fix - this.c = new int[i]; - this.d = (K[]) (new Object[i]); // Paper - decompile fix -+ this.usedIds = new java.util.BitSet(); // Paper - } - - // Paper start - decompile fix -@@ -0,0 +0,0 @@ public class RegistryID implements Registry { - } - - private int c() { -+ // Paper start -+ /* - while (this.e < this.d.length && this.d[this.e] != null) { - ++this.e; - } -+ */ -+ this.e = this.usedIds.nextClearBit(0); -+ // Paper end - - return this.e; - } -@@ -0,0 +0,0 @@ public class RegistryID implements Registry { - this.d = (K[]) (new Object[i]); // Paper - decompile fix - this.e = 0; - this.f = 0; -+ this.usedIds.clear(); // Paper - - for (int j = 0; j < ak.length; ++j) { - if (ak[j] != null) { -@@ -0,0 +0,0 @@ public class RegistryID implements Registry { - this.b[k] = k0; - this.c[k] = i; - this.d[i] = k0; -+ this.usedIds.set(i); // Paper - ++this.f; - if (i == this.e) { - ++this.e; -@@ -0,0 +0,0 @@ public class RegistryID implements Registry { - Arrays.fill(this.d, (Object) null); - this.e = 0; - this.f = 0; -+ this.usedIds.clear(); // Paper - } - - public int b() { diff --git a/Spigot-Server-Patches/Optimize-RegistryMaterials.patch b/Spigot-Server-Patches/Optimize-RegistryMaterials.patch deleted file mode 100644 index c485b3f524..0000000000 --- a/Spigot-Server-Patches/Optimize-RegistryMaterials.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 26 Aug 2018 20:49:50 -0400 -Subject: [PATCH] Optimize RegistryMaterials - -Use larger initial sizes to increase bucket capacity on the BiMap - -BiMap.get was seen to be using a good bit of CPU time. - -diff --git a/src/main/java/net/minecraft/core/RegistryMaterials.java b/src/main/java/net/minecraft/core/RegistryMaterials.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/RegistryMaterials.java -+++ b/src/main/java/net/minecraft/core/RegistryMaterials.java -@@ -0,0 +0,0 @@ import net.minecraft.SystemUtils; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.RegistryDataPackCodec; - import net.minecraft.resources.ResourceKey; -+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Paper - import org.apache.commons.lang3.Validate; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -0,0 +0,0 @@ public class RegistryMaterials extends IRegistryWritable { - - protected static final Logger LOGGER = LogManager.getLogger(); - private final ObjectList bf = new ObjectArrayList(256); -- private final Object2IntMap bg = new Object2IntOpenCustomHashMap(SystemUtils.k()); -+ private final Reference2IntOpenHashMap bg = new Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map - private final BiMap bh; - private final BiMap, T> bi; - private final Map bj; -@@ -0,0 +0,0 @@ public class RegistryMaterials extends IRegistryWritable { - public RegistryMaterials(ResourceKey> resourcekey, Lifecycle lifecycle) { - super(resourcekey, lifecycle); - this.bg.defaultReturnValue(-1); -- this.bh = HashBiMap.create(); -- this.bi = HashBiMap.create(); -- this.bj = Maps.newIdentityHashMap(); -+ this.bh = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.bi = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions -+ this.bj = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions - this.bk = lifecycle; - } - -@@ -0,0 +0,0 @@ public class RegistryMaterials extends IRegistryWritable { - this.b = collection.toArray(new Object[collection.size()]); - } - -- return SystemUtils.a(this.b, random); -+ return (T) SystemUtils.a(this.b, random); // Paper - Decompile fix - } - - public static Codec> a(ResourceKey> resourcekey, Lifecycle lifecycle, Codec codec) { -@@ -0,0 +0,0 @@ public class RegistryMaterials extends IRegistryWritable { - Iterator iterator = registrymaterials.iterator(); - - while (iterator.hasNext()) { -- T t0 = iterator.next(); -+ T t0 = (T) iterator.next(); // Paper - Decompile fix - - builder.add(new RegistryMaterials.a<>((ResourceKey) registrymaterials.c(t0).get(), registrymaterials.a(t0), t0)); - } diff --git a/Spigot-Server-Patches/Optimize-TileEntity-Ticking.patch b/Spigot-Server-Patches/Optimize-TileEntity-Ticking.patch deleted file mode 100644 index 5013cc7ac5..0000000000 --- a/Spigot-Server-Patches/Optimize-TileEntity-Ticking.patch +++ /dev/null @@ -1,248 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 8 Mar 2015 22:55:25 -0600 -Subject: [PATCH] Optimize TileEntity Ticking - - -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +0,0 @@ public class TimingsExport extends Thread { - pair("end", System.currentTimeMillis() / 1000), - pair("online-mode", Bukkit.getServer().getOnlineMode()), - pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().e(), pack -> { - // Don't feel like obf helper'ing these, non fatal if its temp missed. - return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); - })) -@@ -0,0 +0,0 @@ public class TimingsExport extends Thread { - ); - - parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { -- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -- return pair(world.getWorldData().getName(), createObject( -+ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorld().getName(), createObject( - pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { - return pair(rule, world.getWorld().getGameRuleValue(rule)); - })), -diff --git a/src/main/java/net/minecraft/world/level/block/BlockChest.java b/src/main/java/net/minecraft/world/level/block/BlockChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockChest.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockChest.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.shapes.VoxelShapeCollision; - public class BlockChest extends BlockChestAbstract implements IBlockWaterlogged { - - public static final BlockStateDirection FACING = BlockFacingHorizontal.FACING; -- public static final BlockStateEnum c = BlockProperties.aF; -- public static final BlockStateBoolean d = BlockProperties.C; -+ public static final BlockStateEnum c = BlockProperties.aF; public static final BlockStateEnum CHEST_TYPE_PROPERTY = c; // Paper - OBFHELPER -+ public static final BlockStateBoolean d = BlockProperties.C; public static final BlockStateBoolean waterlogged() { return d; } // Paper OBFHELPER - protected static final VoxelShape e = Block.a(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D); - protected static final VoxelShape f = Block.a(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D); - protected static final VoxelShape g = Block.a(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityChest.java -@@ -0,0 +0,0 @@ import net.minecraft.core.NonNullList; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; - import net.minecraft.sounds.SoundEffects; -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; - import org.bukkit.entity.HumanEntity; - // CraftBukkit end - --public class TileEntityChest extends TileEntityLootable implements ITickable { -+public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITickable - - private NonNullList items; - protected float a; -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - return nbttagcompound; - } - -- @Override - public void tick() { - int i = this.position.getX(); - int j = this.position.getY(); - int k = this.position.getZ(); - - ++this.j; -- this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); -+ } -+ -+ public void doOpenLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ -+ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set - this.b = this.a; - float f = 0.1F; - -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - if (this.viewingCount > 0 && this.a == 0.0F) { - this.playOpenSound(SoundEffects.BLOCK_CHEST_OPEN); - } -+ } - -- if (this.viewingCount == 0 && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F) { -+ public void doCloseLogic() { -+ if (this.viewingCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check -+ /* // Paper - disable animation stuff - float f1 = this.a; - - if (this.viewingCount > 0) { -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - float f2 = 0.5F; - - if (this.a < 0.5F && f1 >= 0.5F) { -+ */ -+ MCUtil.scheduleTask(10, () -> { - this.playOpenSound(SoundEffects.BLOCK_CHEST_CLOSE); -- } -+ }, "Chest Sounds"); -+ //} // Paper end - - if (this.a < 0.0F) { - this.a = 0.0F; -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - } - - public void playOpenSound(SoundEffect soundeffect) { -+ if (!this.getBlock().contains(BlockChest.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074 - BlockPropertyChestType blockpropertychesttype = (BlockPropertyChestType) this.getBlock().get(BlockChest.c); - - if (blockpropertychesttype != BlockPropertyChestType.LEFT) { -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - - ++this.viewingCount; - if (this.world == null) return; // CraftBukkit -+ doOpenLogic(); // Paper - - // CraftBukkit start - Call redstone event - if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { -@@ -0,0 +0,0 @@ public class TileEntityChest extends TileEntityLootable implements ITickable { - --this.viewingCount; - - // CraftBukkit start - Call redstone event -+ doCloseLogic(); // Paper - if (this.getBlock().getBlock() == Blocks.TRAPPED_CHEST) { - int newPower = Math.max(0, Math.min(15, this.viewingCount)); - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEnderChest.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block.entity; - -+import net.minecraft.server.MCUtil; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.block.Blocks; - --public class TileEntityEnderChest extends TileEntity implements ITickable { -+public class TileEntityEnderChest extends TileEntity { // Paper - Remove ITickable - - public float a; - public float b; -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - super(TileEntityTypes.ENDER_CHEST); - } - -- @Override - public void tick() { - if (++this.g % 20 * 4 == 0) { - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); - } - - this.b = this.a; -+ /* // Paper - int i = this.position.getX(); - int j = this.position.getY(); - int k = this.position.getZ(); - float f = 0.1F; - double d0; -+ // Paper start -+ */ -+ } -+ -+ private void doOpenLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ double d0; -+ // Paper end - - if (this.c > 0 && this.a == 0.0F) { - double d1 = (double) i + 0.5D; -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - d0 = (double) k + 0.5D; - this.world.playSound((EntityHuman) null, d1, (double) j + 0.5D, d0, SoundEffects.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); - } -+ // Paper start -+ } - -- if (this.c == 0 && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { -+ private void doCloseLogic() { -+ int i = this.position.getX(); -+ int j = this.position.getY(); -+ int k = this.position.getZ(); -+ double d0; -+ -+ if (this.c == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) { -+ // Paper end - float f1 = this.a; - - if (this.c > 0) { -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - float f2 = 0.5F; - - if (this.a < 0.5F && f1 >= 0.5F) { -+ // Paper start -+ */ - d0 = (double) i + 0.5D; - double d2 = (double) k + 0.5D; - -+ MCUtil.scheduleTask(10, () -> { - this.world.playSound((EntityHuman) null, d0, (double) j + 0.5D, d2, SoundEffects.BLOCK_ENDER_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.world.random.nextFloat() * 0.1F + 0.9F); -- } -+ }, "Chest Sounds"); - - if (this.a < 0.0F) { - this.a = 0.0F; -@@ -0,0 +0,0 @@ public class TileEntityEnderChest extends TileEntity implements ITickable { - public void d() { - ++this.c; - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); -+ doOpenLogic(); // Paper - } - - public void f() { - --this.c; - this.world.playBlockAction(this.position, Blocks.ENDER_CHEST, 1, this.c); -+ doCloseLogic(); // Paper - } - - public boolean a(EntityHuman entityhuman) { -diff --git a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -+++ b/src/main/java/net/minecraft/world/level/block/state/IBlockDataHolder.java -@@ -0,0 +0,0 @@ public abstract class IBlockDataHolder { - return Collections.unmodifiableCollection(this.b.keySet()); - } - -+ public > boolean contains(IBlockState iblockstate) { return this.b(iblockstate); } // Paper - OBFHELPER - public > boolean b(IBlockState iblockstate) { - return this.b.containsKey(iblockstate); - } diff --git a/Spigot-Server-Patches/Optimize-UserCache-Thread-Safe.patch b/Spigot-Server-Patches/Optimize-UserCache-Thread-Safe.patch deleted file mode 100644 index 79ce621193..0000000000 --- a/Spigot-Server-Patches/Optimize-UserCache-Thread-Safe.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 16 May 2016 20:47:41 -0400 -Subject: [PATCH] Optimize UserCache / Thread Safe - -Because Techable keeps complaining about how this isn't thread safe, -easier to do this than replace the entire thing. - -Additionally, move Saving of the User cache to be done async, incase -the user never changed the default setting for Spigot's save on stop only. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { // Paper - - try { - BufferedWriter bufferedwriter = Files.newWriter(this.g, StandardCharsets.UTF_8); -@@ -0,0 +0,0 @@ public class UserCache { - } catch (IOException ioexception) { - ; - } -+ // Paper start -+ }; -+ if (asyncSave) { -+ MCUtil.scheduleAsyncTask(save); -+ } else { -+ save.run(); -+ } -+ // Paper end - - } - diff --git a/Spigot-Server-Patches/Optimize-Voxel-Shape-Merging.patch b/Spigot-Server-Patches/Optimize-Voxel-Shape-Merging.patch deleted file mode 100644 index b22050ab79..0000000000 --- a/Spigot-Server-Patches/Optimize-Voxel-Shape-Merging.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 3 May 2020 22:35:09 -0400 -Subject: [PATCH] Optimize Voxel Shape Merging - -This method shows up as super hot in profiler, and also a high "self" time. - -Upon analyzing, it appears most usages of this method fall down to the final -else statement of the nasty ternary. - -Upon even further analyzation, it appears then the majority of those have a -consistent list 1.... One with Infinity head and Tails. - -First optimization is to detect these infinite states and immediately return that -VoxelShapeMergerList so we can avoid testing the rest for most cases. - -Break the method into 2 to help the JVM promote inlining of this fast path. - -Then it was also noticed that VoxelShapeMergerList constructor is also a hotspot -with a high self time... - -Well, knowing that in most cases our list 1 is actualy the same value, it allows -us to know that with an infinite list1, the result on the merger is essentially -list2 as the final values. - -This let us analyze the 2 potential states (Infinite with 2 sources or 4 sources) -and compute a deterministic result for the MergerList values. - -Additionally, this lets us avoid even allocating new objects for this too, further -reducing memory usage. - -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapeMergerList.java -@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; - - public final class VoxelShapeMergerList implements VoxelShapeMerger { - -- private final DoubleArrayList a; -+ private final DoubleList a; // Paper - private final IntArrayList b; - private final IntArrayList c; - -+ // Paper start -+ private static final IntArrayList INFINITE_B_1 = new IntArrayList(new int[]{1, 1}); -+ private static final IntArrayList INFINITE_B_0 = new IntArrayList(new int[]{0, 0}); -+ private static final IntArrayList INFINITE_C = new IntArrayList(new int[]{0, 1}); -+ // Paper end -+ - protected VoxelShapeMergerList(DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { - int i = 0; - int j = 0; -@@ -0,0 +0,0 @@ public final class VoxelShapeMergerList implements VoxelShapeMerger { - int l = doublelist1.size(); - int i1 = k + l; - -+ // Paper start - optimize common path of infinity doublelist -+ int size = doublelist.size(); -+ double tail = doublelist.getDouble(size - 1); -+ double head = doublelist.getDouble(0); -+ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !flag && !flag1 && (size == 2 || size == 4)) { -+ this.a = doublelist1; -+ if (size == 2) { -+ this.b = INFINITE_B_0; -+ } else { -+ this.b = INFINITE_B_1; -+ } -+ this.c = INFINITE_C; -+ return; -+ } -+ // Paper end -+ - this.a = new DoubleArrayList(i1); - this.b = new IntArrayList(i1); - this.c = new IntArrayList(i1); -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -0,0 +0,0 @@ public final class VoxelShapes { - } - - @VisibleForTesting -- protected static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { -+ private static VoxelShapeMerger a(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { // Paper - private -+ // Paper start - fast track the most common scenario -+ // doublelist is usually a DoubleArrayList with Infinite head/tails that falls to the final else clause -+ // This is actually the most common path, so jump to it straight away -+ if (doublelist.getDouble(0) == Double.NEGATIVE_INFINITY && doublelist.getDouble(doublelist.size() - 1) == Double.POSITIVE_INFINITY) { -+ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); -+ } -+ // Split out rest to hopefully inline the above -+ return lessCommonMerge(i, doublelist, doublelist1, flag, flag1); -+ } -+ -+ private static VoxelShapeMerger lessCommonMerge(int i, DoubleList doublelist, DoubleList doublelist1, boolean flag, boolean flag1) { - int j = doublelist.size() - 1; - int k = doublelist1.size() - 1; -+ // Paper note - Rewrite below as optimized order if instead of nasty ternary - - if (doublelist instanceof VoxelShapeCubePoint && doublelist1 instanceof VoxelShapeCubePoint) { - long l = a(j, k); -@@ -0,0 +0,0 @@ public final class VoxelShapes { - } - } - -- return (VoxelShapeMerger) (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist, doublelist1, false) : (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-7D ? new VoxelShapeMergerDisjoint(doublelist1, doublelist, true) : (j == k && Objects.equals(doublelist, doublelist1) ? (doublelist instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist : (doublelist1 instanceof VoxelShapeMergerIdentical ? (VoxelShapeMerger) doublelist1 : new VoxelShapeMergerIdentical(doublelist))) : new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1)))); -+ // Identical happens more often than Disjoint -+ if (j == k && Objects.equals(doublelist, doublelist1)) { -+ if (doublelist instanceof VoxelShapeMergerIdentical) { -+ return (VoxelShapeMerger) doublelist; -+ } else if (doublelist1 instanceof VoxelShapeMergerIdentical) { -+ return (VoxelShapeMerger) doublelist1; -+ } -+ return new VoxelShapeMergerIdentical(doublelist); -+ } else if (doublelist.getDouble(j) < doublelist1.getDouble(0) - 1.0E-07) { -+ return new VoxelShapeMergerDisjoint(doublelist, doublelist1, false); -+ } else if (doublelist1.getDouble(k) < doublelist.getDouble(0) - 1.0E-07) { -+ return new VoxelShapeMergerDisjoint(doublelist1, doublelist, true); -+ } else { -+ return new VoxelShapeMergerList(doublelist, doublelist1, flag, flag1); -+ } -+ // Paper end - } - - public interface a { diff --git a/Spigot-Server-Patches/Optimize-World-Time-Updates.patch b/Spigot-Server-Patches/Optimize-World-Time-Updates.patch deleted file mode 100644 index 3bd8bdf92b..0000000000 --- a/Spigot-Server-Patches/Optimize-World-Time-Updates.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 2 Nov 2018 23:11:51 -0400 -Subject: [PATCH] Optimize World Time Updates - -Splits time updates into incremental updates as well as does -the updates per world, so that we can re-use the same packet -object for every player unless they have per-player time enabled. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Fri, 2 Dec 2016 00:11:43 -0500 -Subject: [PATCH] Optimize World.isLoaded(BlockPosition)Z - -Reduce method invocations for World.isLoaded(BlockPosition)Z - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return chunk == null ? null : chunk.getFluid(blockposition); - } - -+ public final boolean isLoaded(BlockPosition blockposition) { -+ return getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; // Paper -+ } -+ - public final boolean isLoadedAndInBounds(BlockPosition blockposition) { // Paper - final for inline - return getWorldBorder().isInBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; - } diff --git a/Spigot-Server-Patches/Optimize-WorldBorder-collision-checks-and-air.patch b/Spigot-Server-Patches/Optimize-WorldBorder-collision-checks-and-air.patch deleted file mode 100644 index a4da25f9ca..0000000000 --- a/Spigot-Server-Patches/Optimize-WorldBorder-collision-checks-and-air.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sun, 10 May 2020 22:49:05 -0400 -Subject: [PATCH] Optimize WorldBorder collision checks and air - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - VoxelShapeCollision voxelshapecollision = VoxelShapeCollision.a(this); - VoxelShape voxelshape = this.world.getWorldBorder().c(); -- Stream stream = VoxelShapes.c(voxelshape, VoxelShapes.a(axisalignedbb.shrink(1.0E-7D)), OperatorBoolean.AND) ? Stream.empty() : Stream.of(voxelshape); -+ Stream stream = !this.world.getWorldBorder().isInBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper - Stream stream1 = this.world.c(this, axisalignedbb.b(vec3d), (entity) -> { - return true; - }); -diff --git a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -+++ b/src/main/java/net/minecraft/world/level/VoxelShapeSpliterator.java -@@ -0,0 +0,0 @@ public class VoxelShapeSpliterator extends AbstractSpliterator { - AxisAlignedBB axisalignedbb = this.a.getBoundingBox(); - - if (!a(worldborder, axisalignedbb)) { -- VoxelShape voxelshape = worldborder.c(); -- -- if (!b(voxelshape, axisalignedbb) && a(voxelshape, axisalignedbb)) { -- consumer.accept(voxelshape); -+ // Paper start -+ if (worldborder.isInBounds(axisalignedbb.shrink(1.0E-7D)) && !worldborder.isInBounds(axisalignedbb.grow(1.0E-7D))) { -+ consumer.accept(worldborder.asVoxelShape()); -+ // Paper end - return true; - } - } -diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java -+++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -0,0 +0,0 @@ public class WorldBorder { - return (double) chunkcoordintpair.f() > this.e() && (double) chunkcoordintpair.d() < this.g() && (double) chunkcoordintpair.g() > this.f() && (double) chunkcoordintpair.e() < this.h(); - } - -+ public final boolean isInBounds(AxisAlignedBB aabb) { return this.a(aabb); } // Paper - OBFHELPER - public boolean a(AxisAlignedBB axisalignedbb) { - return axisalignedbb.maxX > this.e() && axisalignedbb.minX < this.g() && axisalignedbb.maxZ > this.f() && axisalignedbb.minZ < this.h(); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -0,0 +0,0 @@ public final class VoxelShapes { - IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper - if (iblockdata == null) return 0.0D; // Paper - -- if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { -+ if (!iblockdata.isAir() && (k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) { // Paper - d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0); - if (Math.abs(d0) < 1.0E-7D) { - return 0.0D; diff --git a/Spigot-Server-Patches/Optimize-brigadier-child-sorting-performance.patch b/Spigot-Server-Patches/Optimize-brigadier-child-sorting-performance.patch deleted file mode 100644 index dd9ac2d9e7..0000000000 --- a/Spigot-Server-Patches/Optimize-brigadier-child-sorting-performance.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: virustotalop -Date: Thu, 16 Apr 2020 20:51:32 -0700 -Subject: [PATCH] Optimize brigadier child sorting performance - - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -0,0 +0,0 @@ import java.util.stream.Collectors; - import net.minecraft.commands.CommandListenerWrapper; // CraftBukkit - - public abstract class CommandNode implements Comparable> { -- private Map> children = Maps.newLinkedHashMap(); -+ private Map> children = Maps.newTreeMap(); //Paper - Switch to tree map for automatic sorting - private Map> literals = Maps.newLinkedHashMap(); - private Map> arguments = Maps.newLinkedHashMap(); - private final Predicate requirement; -@@ -0,0 +0,0 @@ public abstract class CommandNode implements Comparable> { - arguments.put(node.getName(), (ArgumentCommandNode) node); - } - } -- -- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); -+ //Paper - Remove manual sorting, it is no longer needed - } - - public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/Spigot-Server-Patches/Optimize-call-to-getFluid-for-explosions.patch b/Spigot-Server-Patches/Optimize-call-to-getFluid-for-explosions.patch deleted file mode 100644 index 367c44a186..0000000000 --- a/Spigot-Server-Patches/Optimize-call-to-getFluid-for-explosions.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BrodyBeckwith -Date: Tue, 14 Jan 2020 17:49:03 -0500 -Subject: [PATCH] Optimize call to getFluid for explosions - - -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -0,0 +0,0 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPosition blockposition = new BlockPosition(d4, d5, d6); - IBlockData iblockdata = this.world.getType(blockposition); -- Fluid fluid = this.world.getFluid(blockposition); -+ Fluid fluid = iblockdata.getFluid(); // Paper - Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); - - if (optional.isPresent()) { diff --git a/Spigot-Server-Patches/Optimize-explosions.patch b/Spigot-Server-Patches/Optimize-explosions.patch deleted file mode 100644 index bc2ddb1253..0000000000 --- a/Spigot-Server-Patches/Optimize-explosions.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 11:59:48 -0600 -Subject: [PATCH] Optimize explosions - -The process of determining an entity's exposure from explosions can be -expensive when there are hundreds or more entities in range. - -This patch adds a per-tick cache that is used for storing and retrieving -an entity's exposure during an explosion. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); - log("End credits disabled: " + disableEndCredits); - } -+ -+ public boolean optimizeExplosions; -+ private void optimizeExplosions() { -+ optimizeExplosions = getBoolean("optimize-explosions", false); -+ log("Optimize explosions: " + optimizeExplosions); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant>> 32)); -+ temp = Double.doubleToLongBits(posY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(posZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(minZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxX); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxY); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ temp = Double.doubleToLongBits(maxZ); -+ result = 31 * result + (int) (temp ^ (temp >>> 32)); -+ return result; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; -+ public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - - public CraftWorld getWorld() { - return this.world; diff --git a/Spigot-Server-Patches/Optimize-isOutsideRange-to-use-distance-maps.patch b/Spigot-Server-Patches/Optimize-isOutsideRange-to-use-distance-maps.patch deleted file mode 100644 index 31c7f24b30..0000000000 --- a/Spigot-Server-Patches/Optimize-isOutsideRange-to-use-distance-maps.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:40:53 -0700 -Subject: [PATCH] Optimize isOutsideRange to use distance maps - -Use a distance map to find the players in range quickly - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - private final Long2ObjectMap> c = new Long2ObjectOpenHashMap(); - public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); - private final ChunkMapDistance.a ticketLevelTracker = new ChunkMapDistance.a(); -- private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); -+ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used - private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); - // Paper start use a queue, but still keep unique requirement - public final java.util.Queue pendingChunkUpdates = new java.util.ArrayDeque() { -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - private final Executor m; - private long currentTick; - -+ PlayerChunkMap chunkMap; // Paper -+ - protected ChunkMapDistance(Executor executor, Executor executor1) { - executor1.getClass(); - Mailbox mailbox = Mailbox.a("player ticket throttler", executor1::execute); -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - protected abstract PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k); - - public boolean a(PlayerChunkMap playerchunkmap) { -- this.f.a(); -+ //this.f.a(); // Paper - no longer used - this.g.a(); - int i = Integer.MAX_VALUE - this.ticketLevelTracker.a(Integer.MAX_VALUE); - boolean flag = i != 0; -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - ((ObjectSet) this.c.computeIfAbsent(i, (j) -> { - return new ObjectOpenHashSet(); - })).add(entityplayer); -- this.f.update(i, 0, true); -+ //this.f.update(i, 0, true); // Paper - no longer used - this.g.update(i, 0, true); - } - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - if (objectset != null) objectset.remove(entityplayer); // Paper - some state corruption happens here, don't crash, clean up gracefully. - if (objectset == null || objectset.isEmpty()) { // Paper - this.c.remove(i); -- this.f.update(i, Integer.MAX_VALUE, false); -+ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used - this.g.update(i, Integer.MAX_VALUE, false); - } - -@@ -0,0 +0,0 @@ public abstract class ChunkMapDistance { - } - - public int b() { -- this.f.a(); -- return this.f.a.size(); -+ // Paper start - use distance map to implement -+ // note: this is the spawn chunk count -+ return this.chunkMap.playerChunkTickRangeMap.size(); -+ // Paper end - use distance map to implement - } - - public boolean d(long i) { -- this.f.a(); -- return this.f.a.containsKey(i); -+ // Paper start - use distance map to implement -+ // note: this is the is spawn chunk method -+ return this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(i) != null; -+ // Paper end - use distance map to implement - } - - public String c() { -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - boolean flag1 = this.world.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && !world.getPlayers().isEmpty(); // CraftBukkit - - if (!flag) { -+ // Paper start - optimize isOutisdeRange -+ PlayerChunkMap playerChunkMap = this.playerChunkMap; -+ for (EntityPlayer player : this.world.players) { -+ if (!player.affectsSpawning || player.isSpectator()) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int viewDistance = this.playerChunkMap.getEffectiveViewDistance(); -+ -+ // copied and modified from isOutisdeRange -+ int chunkRange = world.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; -+ chunkRange = (chunkRange > ChunkMapDistance.MOB_SPAWN_RANGE) ? ChunkMapDistance.MOB_SPAWN_RANGE : chunkRange; -+ -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); -+ event.callEvent(); -+ if (event.isCancelled() || event.getSpawnRadius() < 0 || playerChunkMap.playerChunkTickRangeMap.getLastViewDistance(player) == -1) { -+ playerChunkMap.playerMobSpawnMap.remove(player); -+ continue; -+ } -+ -+ int range = Math.min(event.getSpawnRadius(), 32); // limit to max view distance -+ int chunkX = net.minecraft.server.MCUtil.getChunkCoordinate(player.locX()); -+ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.locZ()); -+ -+ playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); -+ player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in isOutsideRange -+ player.playerNaturallySpawnedEvent = event; -+ } -+ // Paper end - optimize isOutisdeRange - this.world.getMethodProfiler().enter("pollingChunks"); - int k = this.world.getGameRules().getInt(GameRules.RANDOM_TICK_SPEED); - boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -- //Paper start - call player naturally spawn event -- int chunkRange = world.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -- chunkRange = Math.min(chunkRange, 8); -- for (EntityPlayer entityPlayer : this.world.getPlayers()) { -- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -- entityPlayer.playerNaturallySpawnedEvent.callEvent(); -- }; -- // Paper end -+ // Paper - moved up - this.world.timings.chunkTicks.startTiming(); // Paper - final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - Chunk chunk = (Chunk) optional1.get(); - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - -- if (!this.playerChunkMap.isOutsideOfRange(chunkcoordintpair)) { -+ if (!this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange - chunk.setInhabitedTime(chunk.getInhabitedTime() + j); -- if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot -+ if (flag1 && (this.allowMonsters || this.allowAnimals) && this.world.getWorldBorder().isInBounds(chunk.getPos()) && !this.playerChunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange - SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); - } - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -+ double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks -+ - public EntityPlayer(MinecraftServer minecraftserver, WorldServer worldserver, GameProfile gameprofile, PlayerInteractManager playerinteractmanager) { - super(worldserver, worldserver.getSpawn(), worldserver.v(), gameprofile); - this.spawnDimension = World.OVERWORLD; -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - long lastAutoSaveTime; // Paper - incremental autosave - long inactiveTimeStart; // Paper - incremental autosave - -+ // Paper start - optimise isOutsideOfRange -+ // cached here to avoid a map lookup -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInChunkTickRange; -+ -+ void updateRanges() { -+ long key = net.minecraft.server.MCUtil.getCoordinateKey(this.location); -+ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); -+ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); -+ } -+ // Paper end - optimise isOutsideOfRange -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -0,0 +0,0 @@ public class PlayerChunk { - this.n = this.oldTicketLevel; - this.a(i); - this.chunkMap = (PlayerChunkMap)playerchunk_d; // Paper -+ this.updateRanges(); // Paper - optimise isOutsideOfRange - } - - // Paper start -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ // A note about the naming used here: -+ // Previously, mojang used a "spawn range" of 8 for controlling both ticking and -+ // mob spawn range. However, spigot makes the spawn range configurable by -+ // checking if the chunk is in the tick range (8) and the spawn range -+ // obviously this means a spawn range > 8 cannot be implemented -+ -+ // these maps are named after spigot's uses -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerEntityTrackerTrackMaps[i].remove(player); - } - // Paper end - use distance map to optimise tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerMobSpawnMap.remove(player); -+ this.playerChunkTickRangeMap.remove(player); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - void updateMaps(EntityPlayer player) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, ChunkMapDistance.MOB_SPAWN_RANGE); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - // Paper end - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.mailboxWorldGen = this.p.a(threadedmailbox, false); - this.mailboxMain = this.p.a(mailbox, false); - this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false)); -- this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); -+ this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager.chunkMap = this; // Paper - this.l = supplier; - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); - } - // Paper end - use distance map to optimise entity tracker -+ // Paper start - optimise PlayerChunkMap#isOutsideRange -+ this.playerChunkTickRangeMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInChunkTickRange = newState; -+ } -+ }); -+ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }, -+ (EntityPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { -+ PlayerChunk playerChunk = PlayerChunkMap.this.getUpdatingChunk(MCUtil.getCoordinateKey(rangeX, rangeZ)); -+ if (playerChunk != null) { -+ playerChunk.playersInMobSpawnRange = newState; -+ } -+ }); -+ // Paper end - optimise PlayerChunkMap#isOutsideRange - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - -+ private static double getDistanceSquaredFromChunk(ChunkCoordIntPair chunkPos, Entity entity) { return a(chunkPos, entity); } // Paper - OBFHELPER - private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { - double d0 = (double) (chunkcoordintpair.x * 16 + 8); - double d1 = (double) (chunkcoordintpair.z * 16 + 8); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } else { - if (playerchunk != null) { - playerchunk.a(j); -+ playerchunk.updateRanges(); // Paper - optimise isOutsideOfRange - } - - if (playerchunk != null) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return isOutsideOfRange(chunkcoordintpair, false); - } - -- boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -- int chunkRange = world.spigotConfig.mobSpawnRange; -- chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -- chunkRange = (chunkRange > 8) ? 8 : chunkRange; -+ // Paper start - optimise isOutsideOfRange -+ final boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -+ return this.isOutsideOfRange(this.getUpdatingChunk(chunkcoordintpair.pair()), chunkcoordintpair, reducedRange); -+ } - -- final int finalChunkRange = chunkRange; // Paper for lambda below -- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event -- // Spigot end -- long i = chunkcoordintpair.pair(); -+ final boolean isOutsideOfRange(PlayerChunk playerchunk, ChunkCoordIntPair chunkcoordintpair, boolean reducedRange) { -+ // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance -+ // tested and confirmed via System.nanoTime() -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInRange = reducedRange ? playerchunk.playersInMobSpawnRange : playerchunk.playersInChunkTickRange; - -- return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- // Paper start - -- com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -- double blockRange = 16384.0D; -- if (reducedRange) { -- event = entityplayer.playerNaturallySpawnedEvent; -- if (event == null || event.isCancelled()) return false; -- blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -- } -+ if (playersInRange == null) { -+ return true; -+ } - -- return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -- // Paper end -- }); -+ Object[] backingSet = playersInRange.getBackingSet(); -+ -+ if (reducedRange) { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (player.lastEntitySpawnRadiusSquared > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } else { -+ final double range = (ChunkMapDistance.MOB_SPAWN_RANGE * 16) * (ChunkMapDistance.MOB_SPAWN_RANGE * 16); -+ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer) raw; -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (range > getDistanceSquaredFromChunk(chunkcoordintpair, player)) { -+ return false; // in range -+ } -+ } -+ } -+ // no players in range -+ return true; - } -+ // Paper end - optimise isOutsideOfRange - - private boolean b(EntityPlayer entityplayer) { - return entityplayer.isSpectator() && !this.world.getGameRules().getBoolean(GameRules.SPECTATORS_GENERATE_CHUNKS); diff --git a/Spigot-Server-Patches/Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/Spigot-Server-Patches/Optimize-isValidLocation-getType-and-getBlockData-fo.patch deleted file mode 100644 index 73c343c2a9..0000000000 --- a/Spigot-Server-Patches/Optimize-isValidLocation-getType-and-getBlockData-fo.patch +++ /dev/null @@ -1,206 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 02:07:55 -0600 -Subject: [PATCH] Optimize isValidLocation, getType and getBlockData for - inlining - -Hot methods, so reduce # of instructions for the method. - -Move is valid location test to the BlockPosition class so that it can access local variables. - -Replace all calls to the new place to the unnecessary forward. - -Optimize getType and getBlockData to manually inline and optimize the calls - -diff --git a/src/main/java/net/minecraft/core/BaseBlockPosition.java b/src/main/java/net/minecraft/core/BaseBlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BaseBlockPosition.java -+++ b/src/main/java/net/minecraft/core/BaseBlockPosition.java -@@ -0,0 +0,0 @@ public class BaseBlockPosition implements Comparable { - private int b;public final void setY(final int y) { this.b = y; } // Paper - OBFHELPER - private int e;public final void setZ(final int z) { this.e = z; } // Paper - OBFHELPER - -+ // Paper start -+ public boolean isValidLocation() { -+ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && getY() >= 0 && getY() < 256; -+ } -+ public boolean isInvalidYLocation() { -+ return b < 0 || b >= 256; -+ } -+ // Paper end -+ - public BaseBlockPosition(int i, int j, int k) { - this.a = i; - this.b = j; -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public static boolean isValidLocation(BlockPosition blockposition) { -- return !isOutsideWorld(blockposition) && D(blockposition); -+ return blockposition.isValidLocation(); // Paper - use better/optimized check - } - - public static boolean l(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - return this.sections; - } - -- @Override -+ // Paper start - Optimize getBlockData to reduce instructions -+ public final IBlockData getBlockData(BlockPosition pos) { return getBlockData(pos.getX(), pos.getY(), pos.getZ()); } // Paper - public IBlockData getType(BlockPosition blockposition) { -- int i = blockposition.getX(); -- int j = blockposition.getY(); -- int k = blockposition.getZ(); -+ return this.getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ } -+ -+ public IBlockData getType(final int x, final int y, final int z) { -+ return getBlockData(x, y, z); -+ } -+ public final IBlockData getBlockData(final int x, final int y, final int z) { -+ // Method body / logic copied from below -+ final int i = y >> 4; -+ if (y < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { -+ return Blocks.AIR.getBlockData(); -+ } -+ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) -+ return this.sections[i].blockIds.a((y & 15) << 8 | (z & 15) << 4 | x & 15); -+ } - -+ public IBlockData getBlockData_unused(int i, int j, int k) { -+ // Paper end - if (this.world.isDebugWorld()) { - IBlockData iblockdata = null; - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkEmpty.java -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.AxisAlignedBB; - - public class ChunkEmpty extends Chunk { - -- private static final BiomeBase[] b = (BiomeBase[]) SystemUtils.a((Object) (new BiomeBase[BiomeStorage.a]), (abiomebase) -> { -+ private static final BiomeBase[] b = SystemUtils.a((new BiomeBase[BiomeStorage.a]), (abiomebase) -> { // Paper - decompile error - Arrays.fill(abiomebase, BiomeRegistry.a); - }); - -@@ -0,0 +0,0 @@ public class ChunkEmpty extends Chunk { - super(world, chunkcoordintpair, new BiomeStorage(world.r().b(IRegistry.ay), ChunkEmpty.b)); - } - -+ // Paper start -+ @Override public IBlockData getType(int x, int y, int z) { -+ return Blocks.VOID_AIR.getBlockData(); -+ } -+ // Paper end - @Override - public IBlockData getType(BlockPosition blockposition) { - return Blocks.VOID_AIR.getBlockData(); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -0,0 +0,0 @@ public class ChunkSection { - - public static final DataPalette GLOBAL_PALETTE = new DataPaletteGlobal<>(Block.REGISTRY_ID, Blocks.AIR.getBlockData()); - private final int yPos; -- private short nonEmptyBlockCount; -+ short nonEmptyBlockCount; // Paper - package-private - private short tickingBlockCount; - private short e; -- private final DataPaletteBlock blockIds; -+ final DataPaletteBlock blockIds; // Paper - package-private - - public ChunkSection(int i) { - this(i, (short) 0, (short) 0, (short) 0); -@@ -0,0 +0,0 @@ public class ChunkSection { - this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); - } - -- public IBlockData getType(int i, int j, int k) { -- return (IBlockData) this.blockIds.a(i, j, k); -+ public final IBlockData getType(int i, int j, int k) { // Paper -+ return this.blockIds.a(j << 8 | k << 4 | i); // Paper - inline - } - - public Fluid b(int i, int j, int k) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public T a(int i, int j, int k) { -- return this.a(b(i, j, k)); -+ return this.a(j << 8 | k << 4 | i); // Paper - inline - } - - protected T a(int i) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/IChunkAccess.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; - - public interface IChunkAccess extends IBlockAccess, IStructureAccess { - -+ IBlockData getType(final int x, final int y, final int z); // Paper - @Nullable - IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag); - -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -0,0 +0,0 @@ public class ProtoChunk implements IChunkAccess { - - @Override - public IBlockData getType(BlockPosition blockposition) { -- int i = blockposition.getY(); -- -- if (World.b(i)) { -+ return getType(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -+ } -+ // Paper start -+ public IBlockData getType(final int x, final int y, final int z) { -+ if (y < 0 || y >= 256) { - return Blocks.VOID_AIR.getBlockData(); - } else { -- ChunkSection chunksection = this.getSections()[i >> 4]; -- -- return ChunkSection.a(chunksection) ? Blocks.AIR.getBlockData() : chunksection.getType(blockposition.getX() & 15, i & 15, blockposition.getZ() & 15); -+ ChunkSection chunksection = this.getSections()[y >> 4]; -+ return chunksection == Chunk.EMPTY_CHUNK_SECTION || chunksection.c() ? Blocks.AIR.getBlockData() : chunksection.getType(x & 15, y & 15, z & 15); - } - } -+ // Paper end - - @Override - public Fluid getFluid(BlockPosition blockposition) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunkExtension.java -@@ -0,0 +0,0 @@ public class ProtoChunkExtension extends ProtoChunk { - public IBlockData getType(BlockPosition blockposition) { - return this.a.getType(blockposition); - } -+ // Paper start -+ public final IBlockData getType(final int x, final int y, final int z) { -+ return this.a.getBlockData(x, y, z); -+ } -+ // Paper end - - @Override - public Fluid getFluid(BlockPosition blockposition) { diff --git a/Spigot-Server-Patches/Optimize-redstone-algorithm.patch b/Spigot-Server-Patches/Optimize-redstone-algorithm.patch deleted file mode 100644 index b140e10da6..0000000000 --- a/Spigot-Server-Patches/Optimize-redstone-algorithm.patch +++ /dev/null @@ -1,1158 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: theosib -Date: Thu, 27 Sep 2018 01:43:35 -0600 -Subject: [PATCH] Optimize redstone algorithm - -Author: theosib -Co-authored-by: egg82 - -Original license: MIT - -This patch implements theosib's redstone algorithms to completely overhaul the way redstone works. -The new algorithms should be many times faster than current vanilla ones. -From the original author's comments, it looks like it shouldn't interfere with any redstone save for very extreme edge-cases. - -Surprisingly, not a lot was touched aside from a few obfuscation helpers and BlockRedstoneWire. -A lot of this code is self-contained in a helper class. - -Aside from making the obvious class/function renames and obfhelpers I didn't need to modify much. -Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void zombiesTargetTurtleEggs() { - zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); - } -+ -+ public boolean useEigencraftRedstone = false; -+ private void useEigencraftRedstone() { -+ useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); -+ if (useEigencraftRedstone) { -+ log("Using Eigencraft redstone algorithm by theosib."); -+ } else { -+ log("Using vanilla redstone algorithm."); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util; -+ -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.ThreadLocalRandom; -+ -+import net.minecraft.core.BlockPosition; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.Items; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.BlockRedstoneWire; -+import net.minecraft.world.level.block.state.IBlockData; -+import org.bukkit.event.block.BlockRedstoneEvent; -+ -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+ -+/** -+ * Used for the faster redstone algorithm. -+ * Original author: theosib -+ * Original license: MIT -+ * -+ * Ported to Paper and updated to 1.13 by egg82 -+ */ -+public class RedstoneWireTurbo { -+ /* -+ * This is Helper class for BlockRedstoneWire. It implements a minimally-invasive -+ * bolt-on accelerator that performs a breadth-first search through redstone wire blocks -+ * in order to more efficiently and deterministically compute new redstone wire power levels -+ * and determine the order in which other blocks should be updated. -+ * -+ * Features: -+ * - Changes to BlockRedstoneWire are very limited, no other classes are affected, and the -+ * choice between old and new redstone wire update algorithms is switchable on-line. -+ * - The vanilla implementation relied on World.notifyNeighborsOfStateChange for redstone -+ * wire blocks to communicate power level changes to each other, generating 36 block -+ * updates per call. This improved implementation propagates power level changes directly -+ * between redstone wire blocks. Redstone wire power levels are therefore computed more quickly, -+ * and block updates are sent only to non-redstone blocks, many of which may perform an -+ * action when informed of a change in redstone power level. (Note: Block updates are not -+ * the same as state changes to redstone wire. Wire block states are updated as soon -+ * as they are computed.) -+ * - Of the 36 block updates generated by a call to World.notifyNeighborsOfStateChange, -+ * 12 of them are obviously redundant (e.g. the west neighbor of the east neighbor). -+ * These are eliminated. -+ * - Updates to redstone wire and other connected blocks are propagated in a breath-first -+ * manner, radiating out from the initial trigger (a block update to a redstone wire -+ * from something other than redstone wire). -+ * - Updates are scheduled both deterministically and in an intuitive order, addressing bug -+ * MC-11193. -+ * - All redstone behavior that used to be locational now works the same in all locations. -+ * - All behaviors of redstone wire that used to be orientational now work the same in all -+ * orientations, as long as orientation can be determined; random otherwise. Some other -+ * redstone components still update directionally (e.g. switches), and this code can't -+ * compensate for that. -+ * - Information that is otherwise computed over and over again or which is expensive to -+ * to compute is cached for faster lookup. This includes coordinates of block position -+ * neighbors and block states that won't change behind our backs during the execution of -+ * this search algorithm. -+ * - Redundant block updates (both to redstone wire and to other blocks) are heavily -+ * consolidated. For worst-case scenarios (depowering of redstone wire) this results -+ * in a reduction of block updates by as much as 95% (factor of 1/21). Due to overheads, -+ * empirical testing shows a speedup better than 10x. This addresses bug MC-81098. -+ * -+ * Extensive testing has been performed to ensure that existing redstone contraptions still -+ * behave as expected. Results of early testing that identified undesirable behavior changes -+ * were addressed. Additionally, real-time performance testing revealed compute inefficiencies -+ * With earlier implementations of this accelerator. Some compatibility adjustments and -+ * performance optimizations resulted in harmless increases in block updates above the -+ * theoretical minimum. -+ * -+ * Only a single redstone machine was found to break: An instant dropper line hack that -+ * relies on powered rails and quasi-connectivity but doesn't work in all directions. The -+ * replacement is to lay redstone wire directly on top of the dropper line, which now works -+ * reliably in any direction. -+ * -+ * There are numerous other optimization that can be made, but those will be provided later in -+ * separate updates. This version is designed to be minimalistic. -+ * -+ * Many thanks to the following individuals for their help in testing this functionality: -+ * - pokechu22, _MethodZz_, WARBEN, NarcolepticFrog, CommandHelper (nessie), ilmango, -+ * OreoLamp, Xcom6000, tryashtar, RedCMD, Smokey95Dog, EDDxample, Rays Works, -+ * Nodnam, BlockyPlays, Grumm, NeunEinser, HelVince. -+ */ -+ -+ /* Reference to BlockRedstoneWire object, which uses this accelerator */ -+ private final BlockRedstoneWire wire; -+ -+ /* -+ * Implementation: -+ * -+ * RedstoneWire Blocks are updated in concentric rings or "layers" radiating out from the -+ * initial block update that came from a call to BlockRedstoneWire.neighborChanged(). -+ * All nodes put in Layer N are those with Manhattan distance N from the trigger -+ * position, reachable through connected redstone wire blocks. -+ * -+ * Layer 0 represents the trigger block position that was input to neighborChanged. -+ * Layer 1 contains the immediate neighbors of that position. -+ * Layer N contains the neighbors of blocks in layer N-1, not including -+ * those in previous layers. -+ * -+ * Layers enforce an update order that is a function of Manhattan distance -+ * from the initial coordinates input to neighborChanged. The same -+ * coordinates may appear in multiple layers, but redundant updates are minimized. -+ * Block updates are sent layer-by-layer. If multiple of a block's neighbors experience -+ * redstone wire changes before its layer is processed, then those updates will be merged. -+ * If a block's update has been sent, but its neighboring redstone changes -+ * after that, then another update will be sent. This preserves compatibility with -+ * machines that rely on zero-tick behavior, except that the new functionality is non- -+ * locational. -+ * -+ * Within each layer, updates are ordered left-to-right relative to the direction of -+ * information flow. This makes the implementation non-orientational. Only when -+ * this direction is ambiguous is randomness applied (intentionally). -+ */ -+ private List updateQueue0 = Lists.newArrayList(); -+ private List updateQueue1 = Lists.newArrayList(); -+ private List updateQueue2 = Lists.newArrayList(); -+ -+ public RedstoneWireTurbo(BlockRedstoneWire wire) { -+ this.wire = wire; -+ } -+ -+ /* -+ * Compute neighbors of a block. When a redstone wire value changes, previously it called -+ * World.notifyNeighborsOfStateChange. That lists immediately neighboring blocks in -+ * west, east, down, up, north, south order. For each of those neighbors, their own -+ * neighbors are updated in the same order. This generates 36 updates, but 12 of them are -+ * redundant; for instance the west neighbor of a block's east neighbor. -+ * -+ * Note that this ordering is only used to create the initial list of neighbors. Once -+ * the direction of signal flow is identified, the ordering of updates is completely -+ * reorganized. -+ */ -+ public static BlockPosition[] computeAllNeighbors(final BlockPosition pos) { -+ final int x = pos.getX(); -+ final int y = pos.getY(); -+ final int z = pos.getZ(); -+ final BlockPosition[] n = new BlockPosition[24]; -+ -+ // Immediate neighbors, in the same order as -+ // World.notifyNeighborsOfStateChange, etc.: -+ // west, east, down, up, north, south -+ n[0] = new BlockPosition(x - 1, y, z); -+ n[1] = new BlockPosition(x + 1, y, z); -+ n[2] = new BlockPosition(x, y - 1, z); -+ n[3] = new BlockPosition(x, y + 1, z); -+ n[4] = new BlockPosition(x, y, z - 1); -+ n[5] = new BlockPosition(x, y, z + 1); -+ -+ // Neighbors of neighbors, in the same order, -+ // except that duplicates are not included -+ n[6] = new BlockPosition(x - 2, y, z); -+ n[7] = new BlockPosition(x - 1, y - 1, z); -+ n[8] = new BlockPosition(x - 1, y + 1, z); -+ n[9] = new BlockPosition(x - 1, y, z - 1); -+ n[10] = new BlockPosition(x - 1, y, z + 1); -+ n[11] = new BlockPosition(x + 2, y, z); -+ n[12] = new BlockPosition(x + 1, y - 1, z); -+ n[13] = new BlockPosition(x + 1, y + 1, z); -+ n[14] = new BlockPosition(x + 1, y, z - 1); -+ n[15] = new BlockPosition(x + 1, y, z + 1); -+ n[16] = new BlockPosition(x, y - 2, z); -+ n[17] = new BlockPosition(x, y - 1, z - 1); -+ n[18] = new BlockPosition(x, y - 1, z + 1); -+ n[19] = new BlockPosition(x, y + 2, z); -+ n[20] = new BlockPosition(x, y + 1, z - 1); -+ n[21] = new BlockPosition(x, y + 1, z + 1); -+ n[22] = new BlockPosition(x, y, z - 2); -+ n[23] = new BlockPosition(x, y, z + 2); -+ return n; -+ } -+ -+ /* -+ * We only want redstone wires to update redstone wires that are -+ * immediately adjacent. Some more distant updates can result -+ * in cross-talk that (a) wastes time and (b) can make the update -+ * order unintuitive. Therefore (relative to the neighbor order -+ * computed by computeAllNeighbors), updates are not scheduled -+ * for redstone wire in those non-connecting positions. On the -+ * other hand, updates will always be sent to *other* types of blocks -+ * in any of the 24 neighboring positions. -+ */ -+ private static final boolean[] update_redstone = { -+ true, true, false, false, true, true, // 0 to 5 -+ false, true, true, false, false, false, // 6 to 11 -+ true, true, false, false, false, true, // 12 to 17 -+ true, false, true, true, false, false // 18 to 23 -+ }; -+ -+ // Internal numbering for cardinal directions -+ private static final int North = 0; -+ private static final int East = 1; -+ private static final int South = 2; -+ private static final int West = 3; -+ -+ /* -+ * These lookup tables completely remap neighbor positions into a left-to-right -+ * ordering, based on the cardinal direction that is determined to be forward. -+ * See below for more explanation. -+ */ -+ private static final int[] forward_is_north = {2, 3, 16, 19, 0, 4, 1, 5, 7, 8, 17, 20, 12, 13, 18, 21, 6, 9, 22, 14, 11, 10, 23, 15}; -+ private static final int[] forward_is_east = {2, 3, 16, 19, 4, 1, 5, 0, 17, 20, 12, 13, 18, 21, 7, 8, 22, 14, 11, 15, 23, 9, 6, 10}; -+ private static final int[] forward_is_south = {2, 3, 16, 19, 1, 5, 0, 4, 12, 13, 18, 21, 7, 8, 17, 20, 11, 15, 23, 10, 6, 14, 22, 9}; -+ private static final int[] forward_is_west = {2, 3, 16, 19, 5, 0, 4, 1, 18, 21, 7, 8, 17, 20, 12, 13, 23, 10, 6, 9, 22, 15, 11, 14}; -+ -+ /* For any orientation, we end up with the update order defined below. This order is relative to any redstone wire block -+ * that is itself having an update computed, and this center position is marked with C. -+ * - The update position marked 0 is computed first, and the one marked 23 is last. -+ * - Forward is determined by the local direction of information flow into position C from prior updates. -+ * - The first updates are scheduled for the four positions below and above C. -+ * - Then updates are scheduled for the four horizontal neighbors of C, followed by the positions below and above those neighbors. -+ * - Finally, updates are scheduled for the remaining positions with Manhattan distance 2 from C (at the same Y coordinate). -+ * - For a given horizontal distance from C, updates are scheduled starting from directly left and stepping clockwise to directly -+ * right. The remaining positions behind C are scheduled counterclockwise so as to maintain the left-to-right ordering. -+ * - If C is in layer N of the update schedule, then all 24 positions may be scheduled for layer N+1. For redstone wire, no -+ * updates are scheduled for positions that cannot directly connect. Additionally, the four positions above and below C -+ * are ALSO scheduled for layer N+2. -+ * - This update order was selected after experimenting with a number of alternative schedules, based on its compatibility -+ * with existing redstone designs and behaviors that were considered to be intuitive by various testers. WARBEN in particular -+ * made some of the most challenging test cases, but the 3-tick clocks (made by RedCMD) were also challenging to fix, -+ * along with the rail-based instant dropper line built by ilmango. Numerous others made test cases as well, including -+ * NarcolepticFrog, nessie, and Pokechu22. -+ * -+ * - The forward direction is determined locally. So when there are branches in the redstone wire, the left one will get updated -+ * before the right one. Each branch can have its own relative forward direction, resulting in the left side of a left branch -+ * having priority over the right branch of a left branch, which has priority over the left branch of a right branch, followed -+ * by the right branch of a right branch. And so forth. Since redstone power reduces to zero after a path distance of 15, -+ * that imposes a practical limit on the branching. Note that the branching is not tracked explicitly -- relative forward -+ * directions dictate relative sort order, which maintains the proper global ordering. This also makes it unnecessary to be -+ * concerned about branches meeting up with each other. -+ * -+ * ^ -+ * | -+ * Forward -+ * <-- Left Right --> -+ * -+ * 18 -+ * 10 17 5 19 11 -+ * 2 8 0 12 16 4 C 6 20 9 1 13 3 -+ * 14 21 7 23 15 -+ * Further 22 Further -+ * Down Down Up Up -+ * -+ * Backward -+ * | -+ * V -+ */ -+ -+ // This allows the above remapping tables to be looked up by cardial direction index -+ private static final int[][] reordering = { forward_is_north, forward_is_east, forward_is_south, forward_is_west }; -+ -+ /* -+ * Input: Array of UpdateNode objects in an order corresponding to the positions -+ * computed by computeAllNeighbors above. -+ * Output: Array of UpdateNode objects oriented using the above remapping tables -+ * corresponding to the identified heading (direction of information flow). -+ */ -+ private static void orientNeighbors(final UpdateNode[] src, final UpdateNode[] dst, final int heading) { -+ final int[] re = reordering[heading]; -+ for (int i = 0; i < 24; i++) { -+ dst[i] = src[re[i]]; -+ } -+ } -+ -+ /* -+ * Structure to keep track of redstone wire blocks and -+ * neighbors that will receive updates. -+ */ -+ private static class UpdateNode { -+ public static enum Type { -+ UNKNOWN, REDSTONE, OTHER -+ } -+ -+ IBlockData currentState; // Keep track of redstone wire value -+ UpdateNode[] neighbor_nodes; // References to neighbors (directed graph edges) -+ BlockPosition self; // UpdateNode's own position -+ BlockPosition parent; // Which block pos spawned/updated this node -+ Type type = Type.UNKNOWN; // unknown, redstone wire, other type of block -+ int layer; // Highest layer this node is scheduled in -+ boolean visited; // To keep track of information flow direction, visited restone wire is marked -+ int xbias, zbias; // Remembers directionality of ancestor nodes; helps eliminate directional ambiguities. -+ } -+ -+ /* -+ * Keep track of all block positions discovered during search and their current states. -+ * We want to remember one entry for each position. -+ */ -+ private final Map nodeCache = Maps.newHashMap(); -+ -+ /* -+ * For a newly created UpdateNode object, determine what type of block it is. -+ */ -+ private void identifyNode(final World worldIn, final UpdateNode upd1) { -+ final BlockPosition pos = upd1.self; -+ final IBlockData oldState = worldIn.getType(pos); -+ upd1.currentState = oldState; -+ -+ // Some neighbors of redstone wire are other kinds of blocks. -+ // These need to receive block updates to inform them that -+ // redstone wire values have changed. -+ final Block block = oldState.getBlock(); -+ if (block != wire) { -+ // Mark this block as not redstone wire and therefore -+ // requiring updates -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Non-redstone blocks may propagate updates, but those updates -+ // are not handled by this accelerator. Therefore, we do not -+ // expand this position's neighbors. -+ return; -+ } -+ -+ // One job of BlockRedstoneWire.neighborChanged is to convert -+ // redstone wires to items if the block beneath was removed. -+ // With this accelerator, BlockRedstoneWire.neighborChanged -+ // is only typically called for a single wire block, while -+ // others are processed internally by the breadth first search -+ // algorithm. To preserve this game behavior, this check must -+ // be replicated here. -+ if (!wire.canPlace(null, worldIn, pos)) { -+ // Pop off the redstone dust -+ Block.a(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO -+ worldIn.setAir(pos); -+ -+ // Mark this position as not being redstone wire -+ upd1.type = UpdateNode.Type.OTHER; -+ -+ // Note: Sending updates to air blocks leads to an empty method. -+ // Testing shows this to be faster than explicitly avoiding updates to -+ // air blocks. -+ return; -+ } -+ -+ // If the above conditions fail, then this is a redstone wire block. -+ upd1.type = UpdateNode.Type.REDSTONE; -+ } -+ -+ /* -+ * Given which redstone wire blocks have been visited and not visited -+ * around the position currently being updated, compute the cardinal -+ * direction that is "forward." -+ * -+ * rx is the forward direction along the West/East axis -+ * rz is the forward direction along the North/South axis -+ */ -+ static private int computeHeading(final int rx, final int rz) { -+ // rx and rz can only take on values -1, 0, and 1, so we can -+ // compute a code number that allows us to use a single switch -+ // to determine the heading. -+ final int code = (rx + 1) + 3 * (rz + 1); -+ switch (code) { -+ case 0: { -+ // Both rx and rz are -1 (northwest) -+ // Randomly choose one to be forward. -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : West; -+ } -+ case 1: { -+ // rx=0, rz=-1 -+ // Definitively North -+ return North; -+ } -+ case 2: { -+ // rx=1, rz=-1 (northeast) -+ // Choose randomly between north and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? North : East; -+ } -+ case 3: { -+ // rx=-1, rz=0 -+ // Definitively West -+ return West; -+ } -+ case 4: { -+ // rx=0, rz=0 -+ // Heading is completely ambiguous. Choose -+ // randomly among the four cardinal directions. -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ case 5: { -+ // rx=1, rz=0 -+ // Definitively East -+ return East; -+ } -+ case 6: { -+ // rx=-1, rz=1 (southwest) -+ // Choose randomly between south and west -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : West; -+ } -+ case 7: { -+ // rx=0, rz=1 -+ // Definitively South -+ return South; -+ } -+ case 8: { -+ // rx=1, rz=1 (southeast) -+ // Choose randomly between south and east -+ final int j = ThreadLocalRandom.current().nextInt(0, 1); -+ return (j == 0) ? South : East; -+ } -+ } -+ -+ // We should never get here -+ return ThreadLocalRandom.current().nextInt(0, 4); -+ } -+ -+ // Select whether to use updateSurroundingRedstone from BlockRedstoneWire (old) -+ // or this helper class (new) -+ private static final boolean old_current_change = false; -+ -+ /* -+ * Process a node whose neighboring redstone wire has experienced value changes. -+ */ -+ private void updateNode(final World worldIn, final UpdateNode upd1, final int layer) { -+ final BlockPosition pos = upd1.self; -+ -+ // Mark this redstone wire as having been visited so that it can be used -+ // to calculate direction of information flow. -+ upd1.visited = true; -+ -+ // Look up the last known state. -+ // Due to the way other redstone components are updated, we do not -+ // have to worry about a state changing behind our backs. The rare -+ // exception is handled by scheduleReentrantNeighborChanged. -+ final IBlockData oldState = upd1.currentState; -+ -+ // Ask the wire block to compute its power level from its neighbors. -+ // This will also update the wire's power level and return a new -+ // state if it has changed. When a wire power level is changed, -+ // calculateCurrentChanges will immediately update the block state in the world -+ // and return the same value here to be cached in the corresponding -+ // UpdateNode object. -+ IBlockData newState; -+ if (old_current_change) { -+ newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); -+ } else { -+ // Looking up block state is slow. This accelerator includes a version of -+ // calculateCurrentChanges that uses cahed wire values for a -+ // significant performance boost. -+ newState = this.calculateCurrentChanges(worldIn, upd1); -+ } -+ -+ // Only inform neighbors if the state has changed -+ if (newState != oldState) { -+ // Store the new state -+ upd1.currentState = newState; -+ -+ // Inform neighbors of the change -+ propagateChanges(worldIn, upd1, layer); -+ } -+ } -+ -+ /* -+ * This identifies the neighboring positions of a new UpdateNode object, -+ * determines their types, and links those to into the graph. Then based on -+ * what nodes in the redstone wire graph have been visited, the neighbors -+ * are reordered left-to-right relative to the direction of information flow. -+ */ -+ private void findNeighbors(final World worldIn, final UpdateNode upd1) { -+ final BlockPosition pos = upd1.self; -+ -+ // Get the list of neighbor coordinates -+ final BlockPosition[] neighbors = computeAllNeighbors(pos); -+ -+ // Temporary array of neighbors in cardinal ordering -+ final UpdateNode[] neighbor_nodes = new UpdateNode[24]; -+ -+ // Target array of neighbors sorted left-to-right -+ upd1.neighbor_nodes = new UpdateNode[24]; -+ -+ for (int i=0; i<24; i++) { -+ // Look up each neighbor in the node cache -+ final BlockPosition pos2 = neighbors[i]; -+ UpdateNode upd2 = nodeCache.get(pos2); -+ if (upd2 == null) { -+ // If this is a previously unreached position, create -+ // a new update node, add it to the cache, and identify what it is. -+ upd2 = new UpdateNode(); -+ upd2.self = pos2; -+ upd2.parent = pos; -+ nodeCache.put(pos2, upd2); -+ identifyNode(worldIn, upd2); -+ } -+ -+ // For non-redstone blocks, any of the 24 neighboring positions -+ // should receive a block update. However, some block coordinates -+ // may contain a redstone wire that does not directly connect to the -+ // one being expanded. To avoid redundant calculations and confusing -+ // cross-talk, those neighboring positions are not included. -+ if (update_redstone[i] || upd2.type != UpdateNode.Type.REDSTONE) { -+ neighbor_nodes[i] = upd2; -+ } -+ } -+ -+ // Determine the directions from which the redstone signal may have come from. This -+ // checks for redstone wire at the same Y level and also Y+1 and Y-1, relative to the -+ // block being expanded. -+ final boolean fromWest = (neighbor_nodes[0].visited || neighbor_nodes[7].visited || neighbor_nodes[8].visited); -+ final boolean fromEast = (neighbor_nodes[1].visited || neighbor_nodes[12].visited || neighbor_nodes[13].visited); -+ final boolean fromNorth = (neighbor_nodes[4].visited || neighbor_nodes[17].visited || neighbor_nodes[20].visited); -+ final boolean fromSouth = (neighbor_nodes[5].visited || neighbor_nodes[18].visited || neighbor_nodes[21].visited); -+ -+ int cx = 0, cz = 0; -+ if (fromWest) cx += 1; -+ if (fromEast) cx -= 1; -+ if (fromNorth) cz += 1; -+ if (fromSouth) cz -= 1; -+ -+ int heading; -+ if (cx==0 && cz==0) { -+ // If there is no clear direction, try to inherit the heading from ancestor nodes. -+ heading = computeHeading(upd1.xbias, upd1.zbias); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = upd1.xbias; -+ nn.zbias = upd1.zbias; -+ } -+ } -+ } else { -+ if (cx != 0 && cz != 0) { -+ // If the heading is somewhat ambiguous, try to disambiguate based on -+ // ancestor nodes. -+ if (upd1.xbias != 0) cz = 0; -+ if (upd1.zbias != 0) cx = 0; -+ } -+ heading = computeHeading(cx, cz); -+ -+ // Propagate that heading to descendant nodes. -+ for (int i=0; i<24; i++) { -+ final UpdateNode nn = neighbor_nodes[i]; -+ if (nn != null) { -+ nn.xbias = cx; -+ nn.zbias = cz; -+ } -+ } -+ } -+ -+ // Reorder neighboring UpdateNode objects according to the forward direction -+ // determined above. -+ orientNeighbors(neighbor_nodes, upd1.neighbor_nodes, heading); -+ } -+ -+ /* -+ * For any redstone wire block in layer N, inform neighbors to recompute their states -+ * in layers N+1 and N+2; -+ */ -+ private void propagateChanges(final World worldIn, final UpdateNode upd1, final int layer) { -+ if (upd1.neighbor_nodes == null) { -+ // If this node has not been expanded yet, find its neighbors -+ findNeighbors(worldIn, upd1); -+ } -+ -+ final BlockPosition pos = upd1.self; -+ -+ // All neighbors may be scheduled for layer N+1 -+ final int layer1 = layer + 1; -+ -+ // If the node being updated (upd1) has already been expanded, then merely -+ // schedule updates to its neighbors. -+ for (int i = 0; i < 24; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ -+ // This test ensures that an UpdateNode is never scheduled to the same layer -+ // more than once. Also, skip non-connecting redstone wire blocks -+ if (upd2 != null && layer1 > upd2.layer) { -+ upd2.layer = layer1; -+ updateQueue1.add(upd2); -+ -+ // Keep track of which block updated this neighbor -+ upd2.parent = pos; -+ } -+ } -+ -+ // Nodes above and below are scheduled ALSO for layer N+2 -+ final int layer2 = layer + 2; -+ -+ // Repeat of the loop above, but only for the first four (above and below) neighbors -+ // and for layer N+2; -+ for (int i = 0; i < 4; i++) { -+ final UpdateNode upd2 = upd1.neighbor_nodes[i]; -+ if (upd2 != null && layer2 > upd2.layer) { -+ upd2.layer = layer2; -+ updateQueue2.add(upd2); -+ upd2.parent = pos; -+ } -+ } -+ } -+ -+ // The breadth-first search below will send block updates to blocks -+ // that are not redstone wire. If one of those updates results in -+ // a distant redstone wire getting an update, then this.neighborChanged -+ // will get called. This would be a reentrant call, and -+ // it is necessary to properly integrate those updates into the -+ // on-going search through redstone wire. Thus, we make the layer -+ // currently being processed visible at the object level. -+ -+ // The current layer being processed by the breadth-first search -+ private int currentWalkLayer = 0; -+ -+ private void shiftQueue() { -+ final List t = updateQueue0; -+ t.clear(); -+ updateQueue0 = updateQueue1; -+ updateQueue1 = updateQueue2; -+ updateQueue2 = t; -+ } -+ -+ /* -+ * Perform a breadth-first (layer by layer) traversal through redstone -+ * wire blocks, propagating value changes to neighbors in an order -+ * that is a function of distance from the initial call to -+ * this.neighborChanged. -+ */ -+ private void breadthFirstWalk(final World worldIn) { -+ shiftQueue(); -+ currentWalkLayer = 1; -+ -+ // Loop over all layers -+ while (updateQueue0.size()>0 || updateQueue1.size()>0) { -+ // Get the set of blocks in this layer -+ final List thisLayer = updateQueue0; -+ -+ // Loop over all blocks in the layer. Recall that -+ // this is a List, preserving the insertion order of -+ // left-to-right based on direction of information flow. -+ for (UpdateNode upd : thisLayer) { -+ if (upd.type == UpdateNode.Type.REDSTONE) { -+ // If the node is is redstone wire, -+ // schedule updates to neighbors if its value -+ // has changed. -+ updateNode(worldIn, upd, currentWalkLayer); -+ } else { -+ // If this block is not redstone wire, send a block update. -+ // Redstone wire blocks get state updates, but they don't -+ // need block updates. Only non-redstone neighbors need updates. -+ -+ // World.neighborChanged is called from -+ // World.notifyNeighborsOfStateChange, and -+ // notifyNeighborsOfStateExcept. We don't use -+ // World.notifyNeighborsOfStateChange here, since we are -+ // already keeping track of all of the neighbor positions -+ // that need to be updated. All on its own, handling neighbors -+ // this way reduces block updates by 1/3 (24 instead of 36). -+ worldIn.neighborChanged(upd.self, wire, upd.parent); -+ } -+ } -+ -+ // Move on to the next layer -+ shiftQueue(); -+ currentWalkLayer++; -+ } -+ -+ currentWalkLayer = 0; -+ } -+ -+ /* -+ * Normally, when Minecraft is computing redstone wire power changes, and a wire power level -+ * change sends a block update to a neighboring functional component (e.g. piston, repeater, etc.), -+ * those updates are queued. Only once all redstone wire updates are complete will any component -+ * action generate any further block updates to redstone wire. Instant repeater lines, for instance, -+ * will process all wire updates for one redstone line, after which the pistons will zero-tick, -+ * after which the next redstone line performs all of its updates. Thus, each wire is processed in its -+ * own discrete wave. -+ * -+ * However, there are some corner cases where this pattern breaks, with a proof of concept discovered -+ * by Rays Works, which works the same in vanilla. The scenario is as follows: -+ * (1) A redstone wire is conducting a signal. -+ * (2) Part-way through that wave of updates, a neighbor is updated that causes an update to a completely -+ * separate redstone wire. -+ * (3) This results in a call to BlockRedstoneWire.neighborChanged for that other wire, in the middle of -+ * an already on-going propagation through the first wire. -+ * -+ * The vanilla code, being depth-first, would end up fully processing the second wire before going back -+ * to finish processing the first one. (Although technically, vanilla has no special concept of "being -+ * in the middle" of processing updates to a wire.) For the breadth-first algorithm, we give this -+ * situation special handling, where the updates for the second wire are incorporated into the schedule -+ * for the first wire, and then the callstack is allowed to unwind back to the on-going search loop in -+ * order to continue processing both the first and second wire in the order of distance from the initial -+ * trigger. -+ */ -+ private IBlockData scheduleReentrantNeighborChanged(final World worldIn, final BlockPosition pos, final IBlockData newState, final BlockPosition source) { -+ if (source != null) { -+ // If the cause of the redstone wire update is known, we can use that to help determine -+ // direction of information flow. -+ UpdateNode src = nodeCache.get(source); -+ if (src == null) { -+ src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ identifyNode(worldIn, src); -+ nodeCache.put(source, src); -+ } -+ } -+ -+ // Find or generate a node for the redstone block position receiving the update -+ UpdateNode upd = nodeCache.get(pos); -+ if (upd == null) { -+ upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = pos; -+ upd.visited = true; -+ identifyNode(worldIn, upd); -+ nodeCache.put(pos, upd); -+ } -+ upd.currentState = newState; -+ -+ // Receiving this block update may mean something in the world changed. -+ // Therefore we clear the cached block info about all neighbors of -+ // the position receiving the update and then re-identify what they are. -+ if (upd.neighbor_nodes != null) { -+ for (int i=0; i<24; i++) { -+ final UpdateNode upd2 = upd.neighbor_nodes[i]; -+ if (upd2 == null) continue; -+ upd2.type = UpdateNode.Type.UNKNOWN; -+ upd2.currentState = null; -+ identifyNode(worldIn, upd2); -+ } -+ } -+ -+ // The block at 'pos' is a redstone wire and has been updated already by calling -+ // wire.calculateCurrentChanges, so we don't schedule that. However, we do need -+ // to schedule its neighbors. By passing the current value of 'currentWalkLayer' to -+ // propagateChanges, the neighbors of 'pos' are scheduled for layers currentWalkLayer+1 -+ // and currentWalkLayer+2. -+ propagateChanges(worldIn, upd, currentWalkLayer); -+ -+ // Return here. The call stack will unwind back to the first call to -+ // updateSurroundingRedstone, whereupon the new updates just scheduled will -+ // be propagated. This also facilitates elimination of superfluous and -+ // redundant block updates. -+ return newState; -+ } -+ -+ /* -+ * New version of pre-existing updateSurroundingRedstone, which is called from -+ * wire.updateSurroundingRedstone, which is called from wire.neighborChanged and a -+ * few other methods in BlockRedstoneWire. This sets off the breadth-first -+ * walk through all redstone dust connected to the initial position triggered. -+ */ -+ public IBlockData updateSurroundingRedstone(final World worldIn, final BlockPosition pos, final IBlockData state, final BlockPosition source) { -+ // Check this block's neighbors and see if its power level needs to change -+ // Use the calculateCurrentChanges method in BlockRedstoneWire since we have no -+ // cached block states at this point. -+ final IBlockData newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); -+ -+ // If no change, exit -+ if (newState == state) { -+ return state; -+ } -+ -+ // Check to see if this update was received during an on-going breadth first search -+ if (currentWalkLayer > 0 || nodeCache.size() > 0) { -+ // As breadthFirstWalk progresses, it sends block updates to neighbors. Some of those -+ // neighbors may affect the world so as to cause yet another redstone wire block to receive -+ // an update. If that happens, we need to integrate those redstone wire updates into the -+ // already on-going graph walk being performed by breadthFirstWalk. -+ return scheduleReentrantNeighborChanged(worldIn, pos, newState, source); -+ } -+ // If there are no on-going walks through redstone wire, then start a new walk. -+ -+ // If the source of the block update to the redstone wire at 'pos' is known, we can use -+ // that to help determine the direction of information flow. -+ if (source != null) { -+ final UpdateNode src = new UpdateNode(); -+ src.self = source; -+ src.parent = source; -+ src.visited = true; -+ nodeCache.put(source, src); -+ identifyNode(worldIn, src); -+ } -+ -+ // Create a node representing the block at 'pos', and then propagate updates -+ // to its neighbors. As stated above, the call to wire.calculateCurrentChanges -+ // already performs the update to the block at 'pos', so it is not added to the schedule. -+ final UpdateNode upd = new UpdateNode(); -+ upd.self = pos; -+ upd.parent = source!=null ? source : pos; -+ upd.currentState = newState; -+ upd.type = UpdateNode.Type.REDSTONE; -+ upd.visited = true; -+ nodeCache.put(pos, upd); -+ propagateChanges(worldIn, upd, 0); -+ -+ // Perform the walk over all directly reachable redstone wire blocks, propagating wire value -+ // updates in a breadth first order out from the initial update received for the block at 'pos'. -+ breadthFirstWalk(worldIn); -+ -+ // With the whole search completed, clear the list of all known blocks. -+ // We do not want to keep around state information that may be changed by other code. -+ // In theory, we could cache the neighbor block positions, but that is a separate -+ // optimization. -+ nodeCache.clear(); -+ -+ return newState; -+ } -+ -+ // For any array of neighbors in an UpdateNode object, these are always -+ // the indices of the four immediate neighbors at the same Y coordinate. -+ private static final int[] rs_neighbors = {4, 5, 6, 7}; -+ private static final int[] rs_neighbors_up = {9, 11, 13, 15}; -+ private static final int[] rs_neighbors_dn = {8, 10, 12, 14}; -+ -+ /* -+ * Updated calculateCurrentChanges that is optimized for speed and uses -+ * the UpdateNode's neighbor array to find the redstone states of neighbors -+ * that might power it. -+ */ -+ private IBlockData calculateCurrentChanges(final World worldIn, final UpdateNode upd) { -+ IBlockData state = upd.currentState; -+ final int i = state.get(BlockRedstoneWire.POWER).intValue(); -+ int j = 0; -+ j = getMaxCurrentStrength(upd, j); -+ int l = 0; -+ -+ wire.setCanProvidePower(false); -+ // Unfortunately, World.isBlockIndirectlyGettingPowered is complicated, -+ // and I'm not ready to try to replicate even more functionality from -+ // elsewhere in Minecraft into this accelerator. So sadly, we must -+ // suffer the performance hit of this very expensive call. If there -+ // is consistency to what this call returns, we may be able to cache it. -+ final int k = worldIn.isBlockIndirectlyGettingPowered(upd.self); -+ wire.setCanProvidePower(true); -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (k < 15) { -+ if (upd.neighbor_nodes == null) { -+ // If this node's neighbors are not known, expand the node -+ findNeighbors(worldIn, upd); -+ } -+ -+ // These remain constant, so pull them out of the loop. -+ // Regardless of which direction is forward, the UpdateNode for the -+ // position directly above the node being calculated is always -+ // at index 1. -+ UpdateNode center_up = upd.neighbor_nodes[1]; -+ boolean center_up_is_cube = center_up.currentState.isOccluding(worldIn, center_up.self); // TODO -+ -+ for (int m = 0; m < 4; m++) { -+ // Get the neighbor array index of each of the four cardinal -+ // neighbors. -+ int n = rs_neighbors[m]; -+ -+ // Get the max redstone power level of each of the cardinal -+ // neighbors -+ UpdateNode neighbor = upd.neighbor_nodes[n]; -+ l = getMaxCurrentStrength(neighbor, l); -+ -+ // Also check the positions above and below the cardinal -+ // neighbors -+ boolean neighbor_is_cube = neighbor.currentState.isOccluding(worldIn, neighbor.self); // TODO -+ if (!neighbor_is_cube) { -+ UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; -+ l = getMaxCurrentStrength(neighbor_down, l); -+ } else -+ if (!center_up_is_cube) { -+ UpdateNode neighbor_up = upd.neighbor_nodes[rs_neighbors_up[m]]; -+ l = getMaxCurrentStrength(neighbor_up, l); -+ } -+ } -+ } -+ -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ -+ // egg82's amendment -+ // Adding Bukkit's BlockRedstoneEvent - er.. event. -+ if (i != j) { -+ BlockRedstoneEvent event = new BlockRedstoneEvent(worldIn.getWorld().getBlockAt(upd.self.getX(), upd.self.getY(), upd.self.getZ()), i, j); -+ worldIn.getServer().getPluginManager().callEvent(event); -+ j = event.getNewCurrent(); -+ } -+ -+ if (i != j) { -+ // If the power level has changed from its previous value, compute a new state -+ // and set it in the world. -+ // Possible optimization: Don't commit state changes to the world until they -+ // need to be known by some nearby non-redstone-wire block. -+ BlockPosition pos = new BlockPosition(upd.self.getX(), upd.self.getY(), upd.self.getZ()); -+ if (wire.canPlace(null, worldIn, pos)) { -+ state = state.set(BlockRedstoneWire.POWER, Integer.valueOf(j)); -+ worldIn.setTypeAndData(upd.self, state, 2); -+ } -+ } -+ -+ return state; -+ } -+ -+ /* -+ * Optimized function to compute a redstone wire's power level based on cached -+ * state. -+ */ -+ private static int getMaxCurrentStrength(final UpdateNode upd, final int strength) { -+ if (upd.type != UpdateNode.Type.REDSTONE) return strength; -+ final int i = upd.currentState.get(BlockRedstoneWire.POWER).intValue(); -+ return i > strength ? i : strength; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - } - -+ public void neighborChanged(BlockPosition pos, Block blockIn, BlockPosition fromPos) { a(pos, blockIn, fromPos); } // Paper - OBFHELPER - public void a(BlockPosition blockposition, Block block, BlockPosition blockposition1) { - if (!this.isClientSide) { - IBlockData iblockdata = this.getType(blockposition); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return this.getBlockFacePower(blockposition.down(), EnumDirection.DOWN) > 0 ? true : (this.getBlockFacePower(blockposition.up(), EnumDirection.UP) > 0 ? true : (this.getBlockFacePower(blockposition.north(), EnumDirection.NORTH) > 0 ? true : (this.getBlockFacePower(blockposition.south(), EnumDirection.SOUTH) > 0 ? true : (this.getBlockFacePower(blockposition.west(), EnumDirection.WEST) > 0 ? true : this.getBlockFacePower(blockposition.east(), EnumDirection.EAST) > 0)))); - } - -+ public int isBlockIndirectlyGettingPowered(BlockPosition pos) { return this.s(pos); } // Paper - OBFHELPER - public int s(BlockPosition blockposition) { - int i = 0; - EnumDirection[] aenumdirection = World.a; -diff --git a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockRedstoneWire.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block; - -+import com.destroystokyo.paper.PaperConfig; -+import com.destroystokyo.paper.util.RedstoneWireTurbo; - import com.google.common.collect.ImmutableMap; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - private final Map j = Maps.newHashMap(); - private static final Vector3fa[] k = new Vector3fa[16]; - private final IBlockData o; -- private boolean p = true; -+ private boolean p = true; public final boolean canProvidePower() { return this.p; } public final void setCanProvidePower(boolean value) { this.p = value; } // Paper - OBFHELPER - - public BlockRedstoneWire(BlockBase.Info blockbase_info) { - super(blockbase_info); -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - return iblockdata.d(iblockaccess, blockposition, EnumDirection.UP) || iblockdata.a(Blocks.HOPPER); - } - -+ // Paper start - Optimize redstone -+ // The bulk of the new functionality is found in RedstoneWireTurbo.java -+ RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); -+ -+ /* -+ * Modified version of pre-existing updateSurroundingRedstone, which is called from -+ * this.neighborChanged and a few other methods in this class. -+ * Note: Added 'source' argument so as to help determine direction of information flow -+ */ -+ private void updateSurroundingRedstone(World worldIn, BlockPosition pos, IBlockData state, BlockPosition source) { -+ if (worldIn.paperConfig.useEigencraftRedstone) { -+ turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ return; -+ } -+ a(worldIn, pos, state); -+ } -+ -+ /* -+ * Slightly modified method to compute redstone wire power levels from neighboring blocks. -+ * Modifications cut the number of power level changes by about 45% from vanilla, and this -+ * optimization synergizes well with the breadth-first search implemented in -+ * RedstoneWireTurbo. -+ * Note: RedstoneWireTurbo contains a faster version of this code. -+ * Note: Made this public so that RedstoneWireTurbo can access it. -+ */ -+ public IBlockData calculateCurrentChanges(World worldIn, BlockPosition pos1, BlockPosition pos2, IBlockData state) { -+ IBlockData iblockstate = state; -+ int i = state.get(POWER); -+ int j = 0; -+ j = this.getPower(j, worldIn.getType(pos2)); -+ this.setCanProvidePower(false); -+ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); -+ this.setCanProvidePower(true); -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // This code is totally redundant to if statements just below the loop. -+ if (k > 0 && k > j - 1) { -+ j = k; -+ } -+ } -+ -+ int l = 0; -+ -+ // The variable 'k' holds the maximum redstone power value of any adjacent blocks. -+ // If 'k' has the highest level of all neighbors, then the power level of this -+ // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the -+ // following loop can affect the power level of the wire. Therefore, the loop is -+ // skipped if k is already 15. -+ if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { -+ for (EnumDirection enumfacing : EnumDirection.EnumDirectionLimit.HORIZONTAL) { -+ BlockPosition blockpos = pos1.shift(enumfacing); -+ boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); -+ -+ if (flag) { -+ l = this.getPower(l, worldIn.getType(blockpos)); -+ } -+ -+ if (worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && !worldIn.getType(pos1.up()).isOccluding(worldIn, pos1)) { -+ if (flag && pos1.getY() >= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.up())); -+ } -+ } else if (!worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.down())); -+ } -+ } -+ } -+ -+ if (!worldIn.paperConfig.useEigencraftRedstone) { -+ // The old code would decrement the wire value only by 1 at a time. -+ if (l > j) { -+ j = l - 1; -+ } else if (j > 0) { -+ --j; -+ } else { -+ j = 0; -+ } -+ -+ if (k > j - 1) { -+ j = k; -+ } -+ } else { -+ // The new code sets this RedstoneWire block's power level to the highest neighbor -+ // minus 1. This usually results in wire power levels dropping by 2 at a time. -+ // This optimization alone has no impact on update order, only the number of updates. -+ j = l - 1; -+ -+ // If 'l' turns out to be zero, then j will be set to -1, but then since 'k' will -+ // always be in the range of 0 to 15, the following if will correct that. -+ if (k > j) j = k; -+ } -+ -+ if (i != j) { -+ state = state.set(POWER, j); -+ -+ if (worldIn.getType(pos1) == iblockstate) { -+ worldIn.setTypeAndData(pos1, state, 2); -+ } -+ -+ // 1.16(.1?) dropped the need for blocks needing updates. -+ // Whether this is necessary after all is to be seen. -+// if (!worldIn.paperConfig.useEigencraftRedstone) { -+// // The new search algorithm keeps track of blocks needing updates in its own data structures, -+// // so only add anything to blocksNeedingUpdate if we're using the vanilla update algorithm. -+// this.getBlocksNeedingUpdate().add(pos1); -+// -+// for (EnumDirection enumfacing1 : EnumDirection.values()) { -+// this.getBlocksNeedingUpdate().add(pos1.shift(enumfacing1)); -+// } -+// } -+ } -+ -+ return state; -+ } -+ // Paper end -+ - private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { - int i = this.a(world, blockposition); - -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - return Math.max(i, j - 1); - } - -+ private int getPower(int min, IBlockData iblockdata) { return Math.max(min, getPower(iblockdata)); } // Paper - Optimize redstone -+ private int getPower(IBlockData iblockdata) { return this.o(iblockdata); } // Paper - OBFHELPER - private int o(IBlockData iblockdata) { - return iblockdata.a((Block) this) ? (Integer) iblockdata.get(BlockRedstoneWire.POWER) : 0; - } -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - @Override - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - if (!iblockdata1.a(iblockdata.getBlock()) && !world.isClientSide) { -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone - Iterator iterator = EnumDirection.EnumDirectionLimit.VERTICAL.iterator(); - - while (iterator.hasNext()) { -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - world.applyPhysics(blockposition.shift(enumdirection), this); - } - -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone - this.d(world, blockposition); - } - } -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { - if (!world.isClientSide) { - if (iblockdata.canPlace(world, blockposition)) { -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, blockposition1); // Paper - Optimize redstone - } else { - c(iblockdata, world, blockposition); - world.a(blockposition, false); diff --git a/Spigot-Server-Patches/Optimize-sending-packets-to-nearby-locations-sounds-.patch b/Spigot-Server-Patches/Optimize-sending-packets-to-nearby-locations-sounds-.patch deleted file mode 100644 index 2fef302423..0000000000 --- a/Spigot-Server-Patches/Optimize-sending-packets-to-nearby-locations-sounds-.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 23 May 2020 17:03:41 -0400 -Subject: [PATCH] Optimize sending packets to nearby locations (sounds/effects) - -Instead of using the entire world or player list, use the distance -maps to only iterate players who are even seeing the chunk the packet -is originating from. - -This will drastically cut down on packet sending cost for worlds with -lots of players in them. - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, ResourceKey resourcekey, Packet packet) { -- for (int i = 0; i < this.players.size(); ++i) { -- EntityPlayer entityplayer = (EntityPlayer) this.players.get(i); -+ WorldServer world = null; -+ if (entityhuman != null && entityhuman.world instanceof WorldServer) { -+ world = (WorldServer) entityhuman.world; -+ } - -- // CraftBukkit start - Test if player receiving packet can see the source of the packet -- if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { -- continue; -+ // Paper start -+ if (world == null) { -+ world = server.getWorldServer(resourcekey); -+ } -+ PlayerChunkMap chunkMap = world != null ? world.getChunkProvider().playerChunkMap : null; -+ Object[] backingSet; -+ if (chunkMap == null) { -+ // Really shouldn't happen... -+ backingSet = world != null ? world.players.toArray() : players.toArray(); -+ } else { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(d0) >> 4, MCUtil.fastFloor(d2) >> 4); -+ if (nearbyPlayers == null) { -+ return; - } -+ backingSet = nearbyPlayers.getBackingSet(); -+ } -+ -+ for (Object object : backingSet) { -+ if (!(object instanceof EntityPlayer)) continue; -+ EntityPlayer entityplayer = (EntityPlayer) object; -+ // Paper end -+ -+ // CraftBukkit start - Test if player receiving packet can see the source of the packet -+ //if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) { // Paper -+ //continue; // Paper -+ //} // Paper - // CraftBukkit end - -- if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey) { -+ if (entityplayer != entityhuman && entityplayer.world.getDimensionKey() == resourcekey && (!(entityhuman instanceof EntityPlayer) || entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity()))) { // Paper - double d4 = d0 - entityplayer.locX(); - double d5 = d1 - entityplayer.locY(); - double d6 = d2 - entityplayer.locZ(); diff --git a/Spigot-Server-Patches/Optimize-the-advancement-data-player-iteration-to-be.patch b/Spigot-Server-Patches/Optimize-the-advancement-data-player-iteration-to-be.patch deleted file mode 100644 index 5098b7151c..0000000000 --- a/Spigot-Server-Patches/Optimize-the-advancement-data-player-iteration-to-be.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Sat, 4 Jul 2020 23:07:43 -0400 -Subject: [PATCH] Optimize the advancement data player iteration to be O(N) - rather than O(N^2) - - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -0,0 +0,0 @@ public class AdvancementDataPlayer { - } - - private void e(Advancement advancement) { -+ // Paper start -+ e(advancement, IterationEntryPoint.ROOT); -+ } -+ private enum IterationEntryPoint { -+ ROOT, -+ ITERATOR, -+ PARENT_OF_ITERATOR -+ } -+ private void e(Advancement advancement, IterationEntryPoint entryPoint) { -+ // Paper end - boolean flag = this.f(advancement); - boolean flag1 = this.h.contains(advancement); - -@@ -0,0 +0,0 @@ public class AdvancementDataPlayer { - } - - if (flag != flag1 && advancement.b() != null) { -- this.e(advancement.b()); -+ // Paper start - If we're not coming from an iterator consider this to be a root entry, otherwise -+ // market that we're entering from the parent of an iterator. -+ this.e(advancement.b(), entryPoint == IterationEntryPoint.ITERATOR ? IterationEntryPoint.PARENT_OF_ITERATOR : IterationEntryPoint.ROOT); - } - -+ // If this is true, we've went through a child iteration, entered the parent, processed the parent -+ // and are about to reprocess the children. Stop processing here to prevent O(N^2) processing. -+ if (entryPoint == IterationEntryPoint.PARENT_OF_ITERATOR) { -+ return; -+ } // Paper end -+ - Iterator iterator = advancement.e().iterator(); - - while (iterator.hasNext()) { - Advancement advancement1 = (Advancement) iterator.next(); - -- this.e(advancement1); -+ this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration - } - - } diff --git a/Spigot-Server-Patches/Optimized-tick-ready-check.patch b/Spigot-Server-Patches/Optimized-tick-ready-check.patch deleted file mode 100644 index 0cf13a61de..0000000000 --- a/Spigot-Server-Patches/Optimized-tick-ready-check.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas -Date: Sun, 27 Dec 2020 17:19:51 +0100 -Subject: [PATCH] Optimized tick ready check - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - if (!tileentity.isRemoved() && tileentity.hasWorld()) { - BlockPosition blockposition = tileentity.getPosition(); - -- if (this.getChunkProvider().a(blockposition) && this.getWorldBorder().a(blockposition)) { -+ Chunk chunk; PlayerChunk playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity - try { - gameprofilerfiller.a(() -> { - return String.valueOf(TileEntityTypes.a(tileentity.getTileType())); - }); - tileentity.tickTimer.startTiming(); // Spigot -- if (tileentity.getTileType().isValidBlock(this.getType(blockposition).getBlock())) { -+ if (tileentity.getTileType().isValidBlock(chunk.getType(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again - ((ITickable) tileentity).tick(); - } else { - tileentity.w(); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.tileEntityListTick.remove(tileTickPosition--); - // Spigot end - //this.tileEntityList.remove(tileentity); // Paper - remove unused list -- if (this.isLoaded(tileentity.getPosition())) { -- this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); -+ // Paper - prevent double chunk lookups -+ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getPosition())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ chunk.removeTileEntity(tileentity.getPosition()); - } -+ // Paper end - } - } - -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - // CraftBukkit end */ - -- if (this.isLoaded(tileentity1.getPosition())) { -- Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); -+ Chunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getPosition())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again -+ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above - IBlockData iblockdata = chunk.getType(tileentity1.getPosition()); - - chunk.setTileEntity(tileentity1.getPosition(), tileentity1); diff --git a/Spigot-Server-Patches/Option-for-maximum-exp-value-when-merging-orbs.patch b/Spigot-Server-Patches/Option-for-maximum-exp-value-when-merging-orbs.patch deleted file mode 100644 index ecb9b4572d..0000000000 --- a/Spigot-Server-Patches/Option-for-maximum-exp-value-when-merging-orbs.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 10 Nov 2017 23:03:12 -0500 -Subject: [PATCH] Option for maximum exp value when merging orbs - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); - log("Creeper lingering effect: " + disableCreeperLingeringEffect); - } -+ -+ public int expMergeMaxValue; -+ private void expMergeMaxValue() { -+ expMergeMaxValue = getInt("experience-merge-max-value", -1); -+ log("Experience Merge Max Value: " + expMergeMaxValue); -+ } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - EntityExperienceOrb xp = (EntityExperienceOrb) entity; - double radius = world.spigotConfig.expMerge; - if (radius > 0) { -+ // Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics -+ final int maxValue = world.paperConfig.expMergeMaxValue; -+ final boolean mergeUnconditionally = world.paperConfig.expMergeMaxValue <= 0; -+ if (mergeUnconditionally || xp.value < maxValue) { // Paper - Skip iteration if unnecessary -+ - List entities = world.getEntities(entity, entity.getBoundingBox().grow(radius, radius, radius)); - for (Entity e : entities) { - if (e instanceof EntityExperienceOrb) { - EntityExperienceOrb loopItem = (EntityExperienceOrb) e; -- if (!loopItem.dead) { -- xp.value += loopItem.value; -- loopItem.die(); -+ // Paper start -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { -+ long newTotal = (long)xp.value + (long)loopItem.value; -+ if ((int) newTotal < 0) continue; // Overflow -+ if (maxValue > 0 && newTotal > (long)maxValue) { -+ loopItem.value = (int) (newTotal - maxValue); -+ xp.value = maxValue; -+ } else { -+ xp.value += loopItem.value; -+ loopItem.die(); -+ } -+ // Paper end - } - } - } -+ -+ } // Paper end - End iteration skip check - All tweaking ends here - } - // Spigot end - } else if (!(entity instanceof EntityPlayer)) { diff --git a/Spigot-Server-Patches/Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/Spigot-Server-Patches/Option-to-prevent-armor-stands-from-doing-entity-loo.patch deleted file mode 100644 index a20acb0cc4..0000000000 --- a/Spigot-Server-Patches/Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 12:57:39 +0200 -Subject: [PATCH] Option to prevent armor stands from doing entity lookups - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void scanForLegacyEnderDragon() { - scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); - } -+ -+ public boolean armorStandEntityLookups = true; -+ private void armorStandEntityLookups() { -+ armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityArmorStand.java -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { - - @Override - protected void collideNearby() { -+ if (!world.paperConfig.armorStandEntityLookups) return; // Paper - List list = this.world.getEntities(this, this.getBoundingBox(), EntityArmorStand.br); - - for (int i = 0; i < list.size(); ++i) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ import net.minecraft.world.DifficultyDamageScaler; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.decoration.EntityArmorStand; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.crafting.CraftingManager; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // Paper end - } - } -+ // Paper start - Prevent armor stands from doing entity lookups -+ @Override -+ public boolean getCubes(@Nullable Entity entity, AxisAlignedBB axisAlignedBB) { -+ if (entity instanceof EntityArmorStand && !entity.world.paperConfig.armorStandEntityLookups) return false; -+ return GeneratorAccess.super.getCubes(entity, axisAlignedBB); -+ } -+ // Paper end - - public Explosion explode(@Nullable Entity entity, double d0, double d1, double d2, float f, Explosion.Effect explosion_effect) { - return this.createExplosion(entity, (DamageSource) null, (ExplosionDamageCalculator) null, d0, d1, d2, f, false, explosion_effect); diff --git a/Spigot-Server-Patches/Option-to-remove-corrupt-tile-entities.patch b/Spigot-Server-Patches/Option-to-remove-corrupt-tile-entities.patch deleted file mode 100644 index fcfdfda214..0000000000 --- a/Spigot-Server-Patches/Option-to-remove-corrupt-tile-entities.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Wed, 5 Oct 2016 16:27:36 -0500 -Subject: [PATCH] Option to remove corrupt tile entities - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); - log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); - } -+ -+ public boolean removeCorruptTEs = false; -+ private void removeCorruptTEs() { -+ removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16)); - e.printStackTrace(); - ServerInternalException.reportInternalException(e); -+ -+ if (this.world.paperConfig.removeCorruptTEs) { -+ this.removeTileEntity(tileentity.getPosition()); -+ this.markDirty(); -+ org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); -+ } - // Paper end - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/Spigot-Server-Patches/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch deleted file mode 100644 index f32e2e0813..0000000000 --- a/Spigot-Server-Patches/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Wed, 6 Apr 2016 01:04:23 -0500 -Subject: [PATCH] Option to use vanilla per-world scoreboard coloring on names - -This change is basically a bandaid to fix CB's complete and utter lack -of support for vanilla scoreboard name modifications. - -In the future, finding a way to merge the vanilla expectations in with -bukkit's concept of a display name would be preferable. There was a PR -for this on CB at one point but I can't find it. We may need to do this -ourselves at some point in the future. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); - log("Grass Spread Tick Rate: " + grassUpdateRate); - } -+ -+ public boolean useVanillaScoreboardColoring; -+ private void useVanillaScoreboardColoring() { -+ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); -+ } - } -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -0,0 +0,0 @@ import net.kyori.adventure.text.event.ClickEvent; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.world.scores.ScoreboardTeam; -+import net.minecraft.world.scores.ScoreboardTeamBase; - import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.util.LazyPlayerSet; - import org.bukkit.craftbukkit.util.Waitable; -@@ -0,0 +0,0 @@ public final class ChatProcessor { - } - - private static String legacyDisplayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ final EntityPlayer ep = player.getHandle(); -+ IChatBaseComponent name = ep.getDisplayName(); -+ final ScoreboardTeamBase team = ep.getScoreboardTeam(); -+ if (team != null) { -+ name = team.getFormattedName(name); -+ } -+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(PaperAdventure.asAdventure(name)) + ChatColor.RESET; -+ } - return player.getDisplayName(); - } - - private static Component displayName(final CraftPlayer player) { -+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) { -+ return PaperAdventure.asAdventure(ScoreboardTeam.a(player.getHandle().getScoreboardTeam(), player.getHandle().getDisplayName())); -+ } - return player.displayName(); - } - diff --git a/Spigot-Server-Patches/Optional-TNT-doesn-t-move-in-water.patch b/Spigot-Server-Patches/Optional-TNT-doesn-t-move-in-water.patch deleted file mode 100644 index 09689e1db1..0000000000 --- a/Spigot-Server-Patches/Optional-TNT-doesn-t-move-in-water.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sun, 22 May 2016 20:20:55 -0500 -Subject: [PATCH] Optional TNT doesn't move in water - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ package com.destroystokyo.paper; - - import java.util.List; - --import org.bukkit.Bukkit; - import org.bukkit.configuration.file.YamlConfiguration; - import org.spigotmc.SpigotWorldConfig; - -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - ); - } - } -+ -+ public boolean preventTntFromMovingInWater; -+ private void preventTntFromMovingInWater() { -+ if (PaperConfig.version < 13) { -+ boolean oldVal = getBoolean("enable-old-tnt-cannon-behaviors", false); -+ set("prevent-tnt-from-moving-in-water", oldVal); -+ } -+ preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); -+ log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - private boolean q; - private boolean r; - // CraftBukkit start -- private final Set trackedPlayers; -+ final Set trackedPlayers; // Paper - private -> package - // Paper start - private java.util.Map trackedPlayerMap = null; - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean bV() { -+ // Paper start -+ return this.pushedByWater(); -+ } -+ public boolean pushedByWater() { -+ // Paper end - return true; - } - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityTNTPrimed.java -@@ -0,0 +0,0 @@ import javax.annotation.Nullable; - import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport; -+import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.PlayerChunkMap; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.EntityPose; -@@ -0,0 +0,0 @@ public class EntityTNTPrimed extends Entity { - this.world.addParticle(Particles.SMOKE, this.locX(), this.locY() + 0.5D, this.locZ(), 0.0D, 0.0D, 0.0D); - } - } -- -+ // Paper start - Optional prevent TNT from moving in water -+ if (!this.dead && this.inWater && this.world.paperConfig.preventTntFromMovingInWater) { -+ /* -+ * Author: Jedediah Smith -+ */ -+ // Send position and velocity updates to nearby players on every tick while the TNT is in water. -+ // This does pretty well at keeping their clients in sync with the server. -+ PlayerChunkMap.EntityTracker ete = ((WorldServer)this.world).getChunkProvider().playerChunkMap.trackedEntities.get(this.getId()); -+ if (ete != null) { -+ PacketPlayOutEntityVelocity velocityPacket = new PacketPlayOutEntityVelocity(this); -+ PacketPlayOutEntityTeleport positionPacket = new PacketPlayOutEntityTeleport(this); -+ -+ ete.trackedPlayers.stream() -+ .filter(viewer -> (viewer.locX() - this.locX()) * (viewer.locY() - this.locY()) * (viewer.locZ() - this.locZ()) < 16 * 16) -+ .forEach(viewer -> { -+ viewer.playerConnection.sendPacket(velocityPacket); -+ viewer.playerConnection.sendPacket(positionPacket); -+ }); -+ } -+ } -+ // Paper end - } - - private void explode() { -@@ -0,0 +0,0 @@ public class EntityTNTPrimed extends Entity { - public Packet P() { - return new PacketPlayOutSpawnEntity(this); - } -+ -+ // Paper start - Optional prevent TNT from moving in water -+ @Override -+ public boolean pushedByWater() { -+ return !world.paperConfig.preventTntFromMovingInWater && super.pushedByWater(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/POM-Changes.patch b/Spigot-Server-Patches/POM-Changes.patch deleted file mode 100644 index 6d7520f4ad..0000000000 --- a/Spigot-Server-Patches/POM-Changes.patch +++ /dev/null @@ -1,291 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Mon, 29 Feb 2016 20:40:33 -0600 -Subject: [PATCH] POM Changes - - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - - 4.0.0 -- org.spigotmc -- spigot -+ paper - jar - 1.16.5-R0.1-SNAPSHOT -- Spigot -- https://www.spigotmc.org/ -+ Paper -+ https://papermc.io - - -- true -+ - UTF-8 - unknown - git -@@ -0,0 +0,0 @@ - - - -- org.spigotmc -- spigot-parent -+ com.destroystokyo.paper -+ paper-parent - dev-SNAPSHOT - ../pom.xml - - -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-bom -+ 2.11.2 -+ pom -+ import -+ -+ -+ -+ - - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api -+ ${project.version} -+ compile -+ -+ -+ com.destroystokyo.paper -+ paper-mojangapi - ${project.version} - compile - - -- org.spigotmc -+ io.papermc - minecraft-server - ${minecraft.version}-SNAPSHOT - compile -@@ -0,0 +0,0 @@ - 2.12.1 - compile - -+ -+ org.apache.logging.log4j -+ log4j-api -+ compile -+ - - org.apache.logging.log4j - log4j-iostreams -- 2.8.1 - compile -- -- -- -- org.apache.logging.log4j -- log4j-api -- -- - - - org.ow2.asm -@@ -0,0 +0,0 @@ - 9.1 - compile - -+ -+ -+ co.aikar -+ cleaner -+ 1.0-SNAPSHOT -+ -+ -+ io.netty -+ netty-all -+ 4.1.50.Final -+ - - - com.googlecode.json-simple - json-simple - 1.1.1 -- runtime -+ compile - - - org.xerial -@@ -0,0 +0,0 @@ - - mysql - mysql-connector-java -- 5.1.49 -+ 8.0.23 - runtime - - -@@ -0,0 +0,0 @@ - - org.apache.logging.log4j - log4j-slf4j-impl -- 2.8.1 -+ - runtime - - -@@ -0,0 +0,0 @@ - - - -+ paper-${minecraft.version} -+ clean install - - -- net.md-5 -- scriptus -- 0.4.1 -+ com.lukegb.mojo -+ gitdescribe-maven-plugin -+ 1.3 -+ -+ git-Paper- -+ .. -+ - - -- ex-spigot -- -- ${bt.name}-Spigot-%s -- ../ -- spigot.desc -- -- initialize -- -- describe -- -- -- -- ex-craftbukkit -- -- -%s -- ../../CraftBukkit -- craftbukkit.desc -- -- initialize -+ compile - -- describe -+ gitdescribe - - - -@@ -0,0 +0,0 @@ - maven-jar-plugin - 3.2.0 - -+ true - - - false -@@ -0,0 +0,0 @@ - - org.bukkit.craftbukkit.Main - CraftBukkit -- ${spigot.desc}${craftbukkit.desc} -- ${project.build.outputTimestamp} -+ -+ ${describe} -+ ${maven.build.timestamp} - Bukkit - ${api.version} - Bukkit Team -+ true - - - -@@ -0,0 +0,0 @@ - shade - - -+ ${project.build.directory}/dependency-reduced-pom.xml - ${shadeSourcesJar} - - -- org.spigotmc:minecraft-server -+ io.papermc:minecraft-server - - com/google/common/** - com/google/gson/** - com/google/thirdparty/** -+ -+ io/netty/** -+ META-INF/native/libnetty* -+ com/mojang/brigadier/** -+ META-INF/MANIFEST.MF -+ com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.class -+ com/mojang/datafixers/util/Either* -+ org/apache/logging/log4j/** -+ META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat - - - -@@ -0,0 +0,0 @@ - jline - org.bukkit.craftbukkit.libs.jline - -- -- it.unimi -- org.bukkit.craftbukkit.libs.it.unimi -- -+ -+ -+ -+ -+ - - org.apache.commons.codec - org.bukkit.craftbukkit.libs.org.apache.commons.codec -@@ -0,0 +0,0 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - } - - if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { -- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); -+ Date buildDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(Main.class.getPackage().getImplementationVendor()); // Paper - - Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -28); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java -@@ -0,0 +0,0 @@ public final class Versioning { - public static String getBukkitVersion() { - String result = "Unknown-Version"; - -- InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/org.spigotmc/spigot-api/pom.properties"); -+ InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/com.destroystokyo.paper/paper-api/pom.properties"); - Properties properties = new Properties(); - - if (stream != null) { diff --git a/Spigot-Server-Patches/Paper-Metrics.patch b/Spigot-Server-Patches/Paper-Metrics.patch deleted file mode 100644 index 32d531b4cf..0000000000 --- a/Spigot-Server-Patches/Paper-Metrics.patch +++ /dev/null @@ -1,735 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Fri, 24 Mar 2017 23:56:01 -0500 -Subject: [PATCH] Paper Metrics - -Removes Spigot's mcstats metrics in favor of a system using bStats - -To disable for privacy or other reasons go to the bStats folder in your plugins folder -and edit the config.yml file present there. - -Please keep in mind the data collected is anonymous and collection should have no -tangible effect on server performance. The data is used to allow the authors of -PaperMC to track version and platform usage so that we can make better management -decisions on behalf of the project. - -diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/Metrics.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.bukkit.craftbukkit.util.CraftMagicNumbers; -+import org.bukkit.plugin.Plugin; -+ -+import org.json.simple.JSONArray; -+import org.json.simple.JSONObject; -+ -+import javax.net.ssl.HttpsURLConnection; -+import java.io.ByteArrayOutputStream; -+import java.io.DataOutputStream; -+import java.io.File; -+import java.io.IOException; -+import java.net.URL; -+import java.util.*; -+import java.util.concurrent.Callable; -+import java.util.concurrent.Executors; -+import java.util.concurrent.ScheduledExecutorService; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.logging.Logger; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+import java.util.zip.GZIPOutputStream; -+ -+/** -+ * bStats collects some data for plugin authors. -+ * -+ * Check out https://bStats.org/ to learn more about bStats! -+ */ -+public class Metrics { -+ -+ // Executor service for requests -+ // We use an executor service because the Bukkit scheduler is affected by server lags -+ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); -+ -+ // The version of this bStats class -+ public static final int B_STATS_VERSION = 1; -+ -+ // The url to which the data is sent -+ private static final String URL = "https://bStats.org/submitData/server-implementation"; -+ -+ // Should failed requests be logged? -+ private static boolean logFailedRequests = false; -+ -+ // The logger for the failed requests -+ private static Logger logger = Logger.getLogger("bStats"); -+ -+ // The name of the server software -+ private final String name; -+ -+ // The uuid of the server -+ private final String serverUUID; -+ -+ // A list with all custom charts -+ private final List charts = new ArrayList<>(); -+ -+ /** -+ * Class constructor. -+ * -+ * @param name The name of the server software. -+ * @param serverUUID The uuid of the server. -+ * @param logFailedRequests Whether failed requests should be logged or not. -+ * @param logger The logger for the failed requests. -+ */ -+ public Metrics(String name, String serverUUID, boolean logFailedRequests, Logger logger) { -+ this.name = name; -+ this.serverUUID = serverUUID; -+ Metrics.logFailedRequests = logFailedRequests; -+ Metrics.logger = logger; -+ -+ // Start submitting the data -+ startSubmitting(); -+ } -+ -+ /** -+ * Adds a custom chart. -+ * -+ * @param chart The chart to add. -+ */ -+ public void addCustomChart(CustomChart chart) { -+ if (chart == null) { -+ throw new IllegalArgumentException("Chart cannot be null!"); -+ } -+ charts.add(chart); -+ } -+ -+ /** -+ * Starts the Scheduler which submits our data every 30 minutes. -+ */ -+ private void startSubmitting() { -+ final Runnable submitTask = this::submitData; -+ -+ // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution of requests on the -+ // bStats backend. To circumvent this problem, we introduce some randomness into the initial and second delay. -+ // WARNING: You must not modify any part of this Metrics class, including the submit delay or frequency! -+ // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! -+ long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); -+ long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); -+ scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); -+ scheduler.scheduleAtFixedRate(submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); -+ } -+ -+ /** -+ * Gets the plugin specific data. -+ * -+ * @return The plugin specific data. -+ */ -+ private JSONObject getPluginData() { -+ JSONObject data = new JSONObject(); -+ -+ data.put("pluginName", name); // Append the name of the server software -+ JSONArray customCharts = new JSONArray(); -+ for (CustomChart customChart : charts) { -+ // Add the data of the custom charts -+ JSONObject chart = customChart.getRequestJsonObject(); -+ if (chart == null) { // If the chart is null, we skip it -+ continue; -+ } -+ customCharts.add(chart); -+ } -+ data.put("customCharts", customCharts); -+ -+ return data; -+ } -+ -+ /** -+ * Gets the server specific data. -+ * -+ * @return The server specific data. -+ */ -+ private JSONObject getServerData() { -+ // OS specific data -+ String osName = System.getProperty("os.name"); -+ String osArch = System.getProperty("os.arch"); -+ String osVersion = System.getProperty("os.version"); -+ int coreCount = Runtime.getRuntime().availableProcessors(); -+ -+ JSONObject data = new JSONObject(); -+ -+ data.put("serverUUID", serverUUID); -+ -+ data.put("osName", osName); -+ data.put("osArch", osArch); -+ data.put("osVersion", osVersion); -+ data.put("coreCount", coreCount); -+ -+ return data; -+ } -+ -+ /** -+ * Collects the data and sends it afterwards. -+ */ -+ private void submitData() { -+ final JSONObject data = getServerData(); -+ -+ JSONArray pluginData = new JSONArray(); -+ pluginData.add(getPluginData()); -+ data.put("plugins", pluginData); -+ -+ try { -+ // We are still in the Thread of the timer, so nothing get blocked :) -+ sendData(data); -+ } catch (Exception e) { -+ // Something went wrong! :( -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Could not submit stats of " + name, e); -+ } -+ } -+ } -+ -+ /** -+ * Sends the data to the bStats server. -+ * -+ * @param data The data to send. -+ * @throws Exception If the request failed. -+ */ -+ private static void sendData(JSONObject data) throws Exception { -+ if (data == null) { -+ throw new IllegalArgumentException("Data cannot be null!"); -+ } -+ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); -+ -+ // Compress the data to save bandwidth -+ byte[] compressedData = compress(data.toString()); -+ -+ // Add headers -+ connection.setRequestMethod("POST"); -+ connection.addRequestProperty("Accept", "application/json"); -+ connection.addRequestProperty("Connection", "close"); -+ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request -+ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); -+ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format -+ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); -+ -+ // Send data -+ connection.setDoOutput(true); -+ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); -+ outputStream.write(compressedData); -+ outputStream.flush(); -+ outputStream.close(); -+ -+ connection.getInputStream().close(); // We don't care about the response - Just send our data :) -+ } -+ -+ /** -+ * Gzips the given String. -+ * -+ * @param str The string to gzip. -+ * @return The gzipped String. -+ * @throws IOException If the compression failed. -+ */ -+ private static byte[] compress(final String str) throws IOException { -+ if (str == null) { -+ return null; -+ } -+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); -+ GZIPOutputStream gzip = new GZIPOutputStream(outputStream); -+ gzip.write(str.getBytes("UTF-8")); -+ gzip.close(); -+ return outputStream.toByteArray(); -+ } -+ -+ /** -+ * Represents a custom chart. -+ */ -+ public static abstract class CustomChart { -+ -+ // The id of the chart -+ final String chartId; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ */ -+ CustomChart(String chartId) { -+ if (chartId == null || chartId.isEmpty()) { -+ throw new IllegalArgumentException("ChartId cannot be null or empty!"); -+ } -+ this.chartId = chartId; -+ } -+ -+ private JSONObject getRequestJsonObject() { -+ JSONObject chart = new JSONObject(); -+ chart.put("chartId", chartId); -+ try { -+ JSONObject data = getChartData(); -+ if (data == null) { -+ // If the data is null we don't send the chart. -+ return null; -+ } -+ chart.put("data", data); -+ } catch (Throwable t) { -+ if (logFailedRequests) { -+ logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t); -+ } -+ return null; -+ } -+ return chart; -+ } -+ -+ protected abstract JSONObject getChartData() throws Exception; -+ -+ } -+ -+ /** -+ * Represents a custom simple pie. -+ */ -+ public static class SimplePie extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimplePie(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ String value = callable.call(); -+ if (value == null || value.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom advanced pie. -+ */ -+ public static class AdvancedPie extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedPie(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom drilldown pie. -+ */ -+ public static class DrilldownPie extends CustomChart { -+ -+ private final Callable>> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public DrilldownPie(String chartId, Callable>> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ public JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map> map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean reallyAllSkipped = true; -+ for (Map.Entry> entryValues : map.entrySet()) { -+ JSONObject value = new JSONObject(); -+ boolean allSkipped = true; -+ for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { -+ value.put(valueEntry.getKey(), valueEntry.getValue()); -+ allSkipped = false; -+ } -+ if (!allSkipped) { -+ reallyAllSkipped = false; -+ values.put(entryValues.getKey(), value); -+ } -+ } -+ if (reallyAllSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ } -+ -+ /** -+ * Represents a custom single line chart. -+ */ -+ public static class SingleLineChart extends CustomChart { -+ -+ private final Callable callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SingleLineChart(String chartId, Callable callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ int value = callable.call(); -+ if (value == 0) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("value", value); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom multi line chart. -+ */ -+ public static class MultiLineChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public MultiLineChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue() == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ values.put(entry.getKey(), entry.getValue()); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom simple bar chart. -+ */ -+ public static class SimpleBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public SimpleBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ for (Map.Entry entry : map.entrySet()) { -+ JSONArray categoryValues = new JSONArray(); -+ categoryValues.add(entry.getValue()); -+ values.put(entry.getKey(), categoryValues); -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ /** -+ * Represents a custom advanced bar chart. -+ */ -+ public static class AdvancedBarChart extends CustomChart { -+ -+ private final Callable> callable; -+ -+ /** -+ * Class constructor. -+ * -+ * @param chartId The id of the chart. -+ * @param callable The callable which is used to request the chart data. -+ */ -+ public AdvancedBarChart(String chartId, Callable> callable) { -+ super(chartId); -+ this.callable = callable; -+ } -+ -+ @Override -+ protected JSONObject getChartData() throws Exception { -+ JSONObject data = new JSONObject(); -+ JSONObject values = new JSONObject(); -+ Map map = callable.call(); -+ if (map == null || map.isEmpty()) { -+ // Null = skip the chart -+ return null; -+ } -+ boolean allSkipped = true; -+ for (Map.Entry entry : map.entrySet()) { -+ if (entry.getValue().length == 0) { -+ continue; // Skip this invalid -+ } -+ allSkipped = false; -+ JSONArray categoryValues = new JSONArray(); -+ for (int categoryValue : entry.getValue()) { -+ categoryValues.add(categoryValue); -+ } -+ values.put(entry.getKey(), categoryValues); -+ } -+ if (allSkipped) { -+ // Null = skip the chart -+ return null; -+ } -+ data.put("values", values); -+ return data; -+ } -+ -+ } -+ -+ static class PaperMetrics { -+ static void startMetrics() { -+ // Get the config file -+ File configFile = new File(new File((File) MinecraftServer.getServer().options.valueOf("plugins"), "bStats"), "config.yml"); -+ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); -+ -+ // Check if the config file exists -+ if (!config.isSet("serverUuid")) { -+ -+ // Add default values -+ config.addDefault("enabled", true); -+ // Every server gets it's unique random id. -+ config.addDefault("serverUuid", UUID.randomUUID().toString()); -+ // Should failed request be logged? -+ config.addDefault("logFailedRequests", false); -+ -+ // Inform the server owners about bStats -+ config.options().header( -+ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + -+ "To honor their work, you should not disable it.\n" + -+ "This has nearly no effect on the server performance!\n" + -+ "Check out https://bStats.org/ to learn more :)" -+ ).copyDefaults(true); -+ try { -+ config.save(configFile); -+ } catch (IOException ignored) { -+ } -+ } -+ // Load the data -+ String serverUUID = config.getString("serverUuid"); -+ boolean logFailedRequests = config.getBoolean("logFailedRequests", false); -+ // Only start Metrics, if it's enabled in the config -+ if (config.getBoolean("enabled", true)) { -+ Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); -+ -+ metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { -+ String minecraftVersion = Bukkit.getVersion(); -+ minecraftVersion = minecraftVersion.substring(minecraftVersion.indexOf("MC: ") + 4, minecraftVersion.length() - 1); -+ return minecraftVersion; -+ })); -+ -+ metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); -+ metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() || PaperConfig.isProxyOnlineMode() ? "online" : "offline")); -+ metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> (Metrics.class.getPackage().getImplementationVersion() != null) ? Metrics.class.getPackage().getImplementationVersion() : "unknown")); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { -+ Map> map = new HashMap<>(); -+ String javaVersion = System.getProperty("java.version"); -+ Map entry = new HashMap<>(); -+ entry.put(javaVersion, 1); -+ -+ // http://openjdk.java.net/jeps/223 -+ // Java decided to change their versioning scheme and in doing so modified the java.version system -+ // property to return $major[.$minor][.$secuity][-ea], as opposed to 1.$major.0_$identifier -+ // we can handle pre-9 by checking if the "major" is equal to "1", otherwise, 9+ -+ String majorVersion = javaVersion.split("\\.")[0]; -+ String release; -+ -+ int indexOf = javaVersion.lastIndexOf('.'); -+ -+ if (majorVersion.equals("1")) { -+ release = "Java " + javaVersion.substring(0, indexOf); -+ } else { -+ // of course, it really wouldn't be all that simple if they didn't add a quirk, now would it -+ // valid strings for the major may potentially include values such as -ea to deannotate a pre release -+ Matcher versionMatcher = Pattern.compile("\\d+").matcher(majorVersion); -+ if (versionMatcher.find()) { -+ majorVersion = versionMatcher.group(0); -+ } -+ release = "Java " + majorVersion; -+ } -+ map.put(release, entry); -+ -+ return map; -+ })); -+ -+ metrics.addCustomChart(new Metrics.DrilldownPie("legacy_plugins", () -> { -+ Map> map = new HashMap<>(); -+ -+ // count legacy plugins -+ int legacy = 0; -+ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { -+ if (CraftMagicNumbers.isLegacy(plugin.getDescription())) { -+ legacy++; -+ } -+ } -+ -+ // insert real value as lower dimension -+ Map entry = new HashMap<>(); -+ entry.put(String.valueOf(legacy), 1); -+ -+ // create buckets as higher dimension -+ if (legacy == 0) { -+ map.put("0 \uD83D\uDE0E", entry); // :sunglasses: -+ } else if (legacy <= 5) { -+ map.put("1-5", entry); -+ } else if (legacy <= 10) { -+ map.put("6-10", entry); -+ } else if (legacy <= 25) { -+ map.put("11-25", entry); -+ } else if (legacy <= 50) { -+ map.put("26-50", entry); -+ } else { -+ map.put("50+ \uD83D\uDE2D", entry); // :cry: -+ } -+ -+ return map; -+ })); -+ } -+ -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static boolean verbose; - private static boolean fatalError; - /*========================================================================*/ -+ private static boolean metricsStarted; - - public static void init(File configFile) { - CONFIG_FILE = configFile; -@@ -0,0 +0,0 @@ public class PaperConfig { - for (Map.Entry entry : commands.entrySet()) { - MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); - } -+ -+ if (!metricsStarted) { -+ Metrics.PaperMetrics.startMetrics(); -+ metricsStarted = true; -+ } - } - - static void readConfig(Class clazz, Object instance) { -diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotConfig.java -+++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -0,0 +0,0 @@ public class SpigotConfig - MinecraftServer.getServer().server.getCommandMap().register( entry.getKey(), "Spigot", entry.getValue() ); - } - -+ /* // Paper - Replace with our own - if ( metrics == null ) - { - try -@@ -0,0 +0,0 @@ public class SpigotConfig - Bukkit.getServer().getLogger().log( Level.SEVERE, "Could not start metrics service", ex ); - } - } -+ */ // Paper end - } - - static void readConfig(Class clazz, Object instance) diff --git a/Spigot-Server-Patches/Paper-config-files.patch b/Spigot-Server-Patches/Paper-config-files.patch deleted file mode 100644 index 80abac900e..0000000000 --- a/Spigot-Server-Patches/Paper-config-files.patch +++ /dev/null @@ -1,820 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Mon, 29 Feb 2016 21:02:09 -0600 -Subject: [PATCH] Paper config files - -Loads each yml file for early init too so it can be used for early options - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Functions; -+import com.google.common.base.Joiner; -+import com.google.common.collect.ImmutableSet; -+import com.google.common.collect.Iterables; -+import com.google.common.collect.Lists; -+import com.google.common.collect.Maps; -+import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import org.apache.commons.lang3.tuple.MutablePair; -+import org.apache.commons.lang3.tuple.Pair; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Location; -+import org.bukkit.World; -+import org.bukkit.command.Command; -+import org.bukkit.command.CommandSender; -+import org.bukkit.craftbukkit.CraftServer; -+import org.bukkit.craftbukkit.CraftWorld; -+import org.bukkit.entity.Player; -+ -+import java.io.File; -+import java.time.LocalDateTime; -+import java.time.format.DateTimeFormatter; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.Collections; -+import java.util.Iterator; -+import java.util.List; -+import java.util.Locale; -+import java.util.Map; -+import java.util.Set; -+import java.util.stream.Collectors; -+ -+public class PaperCommand extends Command { -+ private static final String BASE_PERM = "bukkit.command.paper."; -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version").build(); -+ -+ public PaperCommand(String name) { -+ super(name); -+ this.description = "Paper related commands"; -+ this.usageMessage = "/paper [" + Joiner.on(" | ").join(SUBCOMMANDS) + "]"; -+ this.setPermission("bukkit.command.paper;" + Joiner.on(';').join(SUBCOMMANDS.stream().map(s -> BASE_PERM + s).collect(Collectors.toSet()))); -+ } -+ -+ private static boolean testPermission(CommandSender commandSender, String permission) { -+ if (commandSender.hasPermission(BASE_PERM + permission) || commandSender.hasPermission("bukkit.command.paper")) return true; -+ commandSender.sendMessage(Bukkit.getPermissionMessage()); -+ return false; -+ } -+ -+ @Override -+ public List tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException { -+ if (args.length <= 1) -+ return getListMatchingLast(sender, args, SUBCOMMANDS); -+ -+ switch (args[0].toLowerCase(Locale.ENGLISH)) -+ { -+ case "entity": -+ if (args.length == 2) -+ return getListMatchingLast(sender, args, "help", "list"); -+ if (args.length == 3) -+ return getListMatchingLast(sender, args, EntityTypes.getEntityNameList().stream().map(MinecraftKey::toString).sorted().toArray(String[]::new)); -+ break; -+ } -+ return Collections.emptyList(); -+ } -+ -+ // Code from Mojang - copyright them -+ public static List getListMatchingLast(CommandSender sender, String[] args, String... matches) { -+ return getListMatchingLast(sender, args, (Collection) Arrays.asList(matches)); -+ } -+ -+ public static boolean matches(String s, String s1) { -+ return s1.regionMatches(true, 0, s, 0, s.length()); -+ } -+ -+ public static List getListMatchingLast(CommandSender sender, String[] strings, Collection collection) { -+ String last = strings[strings.length - 1]; -+ ArrayList results = Lists.newArrayList(); -+ -+ if (!collection.isEmpty()) { -+ Iterator iterator = Iterables.transform(collection, Functions.toStringFunction()).iterator(); -+ -+ while (iterator.hasNext()) { -+ String s1 = (String) iterator.next(); -+ -+ if (matches(last, s1) && (sender.hasPermission(BASE_PERM + s1) || sender.hasPermission("bukkit.command.paper"))) { -+ results.add(s1); -+ } -+ } -+ -+ if (results.isEmpty()) { -+ iterator = collection.iterator(); -+ -+ while (iterator.hasNext()) { -+ Object object = iterator.next(); -+ -+ if (object instanceof MinecraftKey && matches(last, ((MinecraftKey) object).getKey())) { -+ results.add(String.valueOf(object)); -+ } -+ } -+ } -+ } -+ -+ return results; -+ } -+ // end copy stuff -+ -+ @Override -+ public boolean execute(CommandSender sender, String commandLabel, String[] args) { -+ if (!testPermission(sender)) return true; -+ -+ if (args.length == 0) { -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ if (SUBCOMMANDS.contains(args[0].toLowerCase(Locale.ENGLISH))) { -+ if (!testPermission(sender, args[0].toLowerCase(Locale.ENGLISH))) return true; -+ } -+ switch (args[0].toLowerCase(Locale.ENGLISH)) { -+ case "heap": -+ dumpHeap(sender); -+ break; -+ case "entity": -+ listEntities(sender, args); -+ break; -+ case "reload": -+ doReload(sender); -+ break; -+ case "ver": -+ if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) -+ case "version": -+ Command ver = org.bukkit.Bukkit.getServer().getCommandMap().getCommand("version"); -+ if (ver != null) { -+ ver.execute(sender, commandLabel, new String[0]); -+ break; -+ } -+ // else - fall through to default -+ default: -+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); -+ return false; -+ } -+ -+ return true; -+ } -+ -+ /* -+ * Ported from MinecraftForge - author: LexManos - License: LGPLv2.1 -+ */ -+ private void listEntities(CommandSender sender, String[] args) { -+ if (args.length < 2 || args[1].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity [list] help for more information on a specific command."); -+ return; -+ } -+ -+ switch (args[1].toLowerCase(Locale.ENGLISH)) { -+ case "list": -+ String filter = "*"; -+ if (args.length > 2) { -+ if (args[2].toLowerCase(Locale.ENGLISH).equals("help")) { -+ sender.sendMessage(ChatColor.RED + "Use /paper entity list [filter] [worldName] to get entity info that matches the optional filter."); -+ return; -+ } -+ filter = args[2]; -+ } -+ final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); -+ Set names = EntityTypes.getEntityNameList().stream() -+ .filter(n -> n.toString().matches(cleanfilter)) -+ .collect(Collectors.toSet()); -+ -+ if (names.isEmpty()) { -+ sender.sendMessage(ChatColor.RED + "Invalid filter, does not match any entities. Use /paper entity list for a proper list"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ String worldName; -+ if (args.length > 3) { -+ worldName = args[3]; -+ } else if (sender instanceof Player) { -+ worldName = ((Player) sender).getWorld().getName(); -+ } else { -+ sender.sendMessage(ChatColor.RED + "Please specify the name of a world"); -+ sender.sendMessage(ChatColor.RED + "To do so without a filter, specify '*' as the filter"); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ -+ Map>> list = Maps.newHashMap(); -+ World bukkitWorld = Bukkit.getWorld(worldName); -+ if (bukkitWorld == null) { -+ sender.sendMessage(ChatColor.RED + "Could not load world for " + worldName + ". Please select a valid world."); -+ sender.sendMessage(ChatColor.RED + "Usage: /paper entity list [filter] [worldName]"); -+ return; -+ } -+ WorldServer world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); -+ -+ Map nonEntityTicking = Maps.newHashMap(); -+ ChunkProviderServer chunkProviderServer = world.getChunkProvider(); -+ -+ Collection entities = world.entitiesById.values(); -+ entities.forEach(e -> { -+ MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch -+ -+ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); -+ ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); -+ info.left++; -+ info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); -+ if (!chunkProviderServer.isInEntityTickingChunk(e)) { -+ nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); -+ } -+ }); -+ -+ if (names.size() == 1) { -+ MinecraftKey name = names.iterator().next(); -+ Pair> info = list.get(name); -+ int nonTicking = nonEntityTicking.getOrDefault(name, Integer.valueOf(0)).intValue(); -+ if (info == null) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ sender.sendMessage("Entity: " + name + " Total Ticking: " + (info.getLeft() - nonTicking) + ", Total Non-Ticking: " + nonTicking); -+ info.getRight().entrySet().stream() -+ .sorted((a, b) -> !a.getValue().equals(b.getValue()) ? b.getValue() - a.getValue() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isEntityTickingChunk(e.getKey()) ? " (Ticking)" : " (Non-Ticking)"))); -+ } else { -+ List> info = list.entrySet().stream() -+ .filter(e -> names.contains(e.getKey())) -+ .map(e -> Pair.of(e.getKey(), e.getValue().left)) -+ .sorted((a, b) -> !a.getRight().equals(b.getRight()) ? b.getRight() - a.getRight() : a.getKey().toString().compareTo(b.getKey().toString())) -+ .collect(Collectors.toList()); -+ -+ if (info == null || info.size() == 0) { -+ sender.sendMessage(ChatColor.RED + "No entities found."); -+ return; -+ } -+ -+ int count = info.stream().mapToInt(Pair::getRight).sum(); -+ int nonTickingCount = nonEntityTicking.values().stream().mapToInt(Integer::intValue).sum(); -+ sender.sendMessage("Total Ticking: " + (count - nonTickingCount) + ", Total Non-Ticking: " + nonTickingCount); -+ info.forEach(e -> { -+ int nonTicking = nonEntityTicking.getOrDefault(e.getKey(), Integer.valueOf(0)).intValue(); -+ sender.sendMessage(" " + (e.getValue() - nonTicking) + " (" + nonTicking + ") " + ": " + e.getKey()); -+ }); -+ sender.sendMessage("* First number is ticking entities, second number is non-ticking entities"); -+ } -+ break; -+ } -+ } -+ -+ private void dumpHeap(CommandSender sender) { -+ java.nio.file.Path dir = java.nio.file.Paths.get("./dumps"); -+ String name = "heap-dump-" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()); -+ -+ Command.broadcastCommandMessage(sender, ChatColor.YELLOW + "Writing JVM heap data..."); -+ -+ java.nio.file.Path file = CraftServer.dumpHeap(dir, name); -+ if (file != null) { -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Heap dump saved to " + file); -+ } else { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Failed to write heap dump, see sever log for details"); -+ } -+ } -+ -+ private void doReload(CommandSender sender) { -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "Please note that this command is not supported and may cause issues."); -+ Command.broadcastCommandMessage(sender, ChatColor.RED + "If you encounter any issues please use the /stop command to restart your server."); -+ -+ MinecraftServer console = MinecraftServer.getServer(); -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); -+ for (WorldServer world : console.getWorlds()) { -+ world.paperConfig.init(); -+ } -+ console.server.reloadCount++; -+ -+ Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import com.google.common.base.Throwables; -+ -+import java.io.File; -+import java.io.IOException; -+import java.lang.reflect.InvocationTargetException; -+import java.lang.reflect.Method; -+import java.lang.reflect.Modifier; -+import java.util.HashMap; -+import java.util.List; -+import java.util.Map; -+import java.util.concurrent.TimeUnit; -+import java.util.logging.Level; -+import java.util.regex.Pattern; -+ -+import net.minecraft.server.MinecraftServer; -+import org.bukkit.Bukkit; -+import org.bukkit.command.Command; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.InvalidConfigurationException; -+import org.bukkit.configuration.file.YamlConfiguration; -+ -+public class PaperConfig { -+ -+ private static File CONFIG_FILE; -+ private static final String HEADER = "This is the main configuration file for Paper.\n" -+ + "As you can see, there's tons to configure. Some options may impact gameplay, so use\n" -+ + "with caution, and make sure you know what each option does before configuring.\n" -+ + "\n" -+ + "If you need help with the configuration or have any questions related to Paper,\n" -+ + "join us in our Discord or IRC channel.\n" -+ + "\n" -+ + "Discord: https://discord.gg/papermc\n" -+ + "IRC: #paper @ irc.esper.net ( https://webchat.esper.net/?channels=paper ) \n" -+ + "Website: https://papermc.io/ \n" -+ + "Docs: https://paper.readthedocs.org/ \n"; -+ /*========================================================================*/ -+ public static YamlConfiguration config; -+ static int version; -+ static Map commands; -+ private static boolean verbose; -+ private static boolean fatalError; -+ /*========================================================================*/ -+ -+ public static void init(File configFile) { -+ CONFIG_FILE = configFile; -+ config = new YamlConfiguration(); -+ try { -+ config.load(CONFIG_FILE); -+ } catch (IOException ex) { -+ } catch (InvalidConfigurationException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not load paper.yml, please correct your syntax errors", ex); -+ throw Throwables.propagate(ex); -+ } -+ config.options().header(HEADER); -+ config.options().copyDefaults(true); -+ verbose = getBoolean("verbose", false); -+ -+ commands = new HashMap(); -+ commands.put("paper", new PaperCommand("paper")); -+ -+ version = getInt("config-version", 20); -+ set("config-version", 20); -+ readConfig(PaperConfig.class, null); -+ } -+ -+ protected static void logError(String s) { -+ Bukkit.getLogger().severe(s); -+ } -+ -+ protected static void fatal(String s) { -+ fatalError = true; -+ throw new RuntimeException("Fatal paper.yml config error: " + s); -+ } -+ -+ protected static void log(String s) { -+ if (verbose) { -+ Bukkit.getLogger().info(s); -+ } -+ } -+ -+ public static void registerCommands() { -+ for (Map.Entry entry : commands.entrySet()) { -+ MinecraftServer.getServer().server.getCommandMap().register(entry.getKey(), "Paper", entry.getValue()); -+ } -+ } -+ -+ static void readConfig(Class clazz, Object instance) { -+ for (Method method : clazz.getDeclaredMethods()) { -+ if (Modifier.isPrivate(method.getModifiers())) { -+ if (method.getParameterTypes().length == 0 && method.getReturnType() == Void.TYPE) { -+ try { -+ method.setAccessible(true); -+ method.invoke(instance); -+ } catch (InvocationTargetException ex) { -+ throw Throwables.propagate(ex.getCause()); -+ } catch (Exception ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Error invoking " + method, ex); -+ } -+ } -+ } -+ } -+ -+ try { -+ config.save(CONFIG_FILE); -+ } catch (IOException ex) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not save " + CONFIG_FILE, ex); -+ } -+ } -+ -+ private static final Pattern SPACE = Pattern.compile(" "); -+ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]"); -+ public static int getSeconds(String str) { -+ str = SPACE.matcher(str).replaceAll(""); -+ final char unit = str.charAt(str.length() - 1); -+ str = NOT_NUMERIC.matcher(str).replaceAll(""); -+ double num; -+ try { -+ num = Double.parseDouble(str); -+ } catch (Exception e) { -+ num = 0D; -+ } -+ switch (unit) { -+ case 'd': num *= (double) 60*60*24; break; -+ case 'h': num *= (double) 60*60; break; -+ case 'm': num *= (double) 60; break; -+ default: case 's': break; -+ } -+ return (int) num; -+ } -+ -+ protected static String timeSummary(int seconds) { -+ String time = ""; -+ -+ if (seconds > 60 * 60 * 24) { -+ time += TimeUnit.SECONDS.toDays(seconds) + "d"; -+ seconds %= 60 * 60 * 24; -+ } -+ -+ if (seconds > 60 * 60) { -+ time += TimeUnit.SECONDS.toHours(seconds) + "h"; -+ seconds %= 60 * 60; -+ } -+ -+ if (seconds > 0) { -+ time += TimeUnit.SECONDS.toMinutes(seconds) + "m"; -+ } -+ return time; -+ } -+ -+ private static void set(String path, Object val) { -+ config.set(path, val); -+ } -+ -+ private static boolean getBoolean(String path, boolean def) { -+ config.addDefault(path, def); -+ return config.getBoolean(path, config.getBoolean(path)); -+ } -+ -+ private static double getDouble(String path, double def) { -+ config.addDefault(path, def); -+ return config.getDouble(path, config.getDouble(path)); -+ } -+ -+ private static float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private static int getInt(String path, int def) { -+ config.addDefault(path, def); -+ return config.getInt(path, config.getInt(path)); -+ } -+ -+ private static List getList(String path, T def) { -+ config.addDefault(path, def); -+ return (List) config.getList(path, config.getList(path)); -+ } -+ -+ private static String getString(String path, String def) { -+ config.addDefault(path, def); -+ return config.getString(path, config.getString(path)); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper; -+ -+import java.util.List; -+ -+import org.bukkit.Bukkit; -+import org.bukkit.configuration.file.YamlConfiguration; -+import org.spigotmc.SpigotWorldConfig; -+ -+import static com.destroystokyo.paper.PaperConfig.log; -+import static com.destroystokyo.paper.PaperConfig.logError; -+ -+public class PaperWorldConfig { -+ -+ private final String worldName; -+ private final SpigotWorldConfig spigotConfig; -+ private YamlConfiguration config; -+ private boolean verbose; -+ -+ public PaperWorldConfig(String worldName, SpigotWorldConfig spigotConfig) { -+ this.worldName = worldName; -+ this.spigotConfig = spigotConfig; -+ this.config = PaperConfig.config; -+ init(); -+ } -+ -+ public void init() { -+ this.config = PaperConfig.config; // grab updated reference -+ log("-------- World Settings For [" + worldName + "] --------"); -+ PaperConfig.readConfig(PaperWorldConfig.class, this); -+ } -+ -+ private void set(String path, Object val) { -+ config.set("world-settings.default." + path, val); -+ if (config.get("world-settings." + worldName + "." + path) != null) { -+ config.set("world-settings." + worldName + "." + path, val); -+ } -+ } -+ -+ private boolean getBoolean(String path, boolean def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getBoolean("world-settings." + worldName + "." + path, config.getBoolean("world-settings.default." + path)); -+ } -+ -+ private double getDouble(String path, double def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getDouble("world-settings." + worldName + "." + path, config.getDouble("world-settings.default." + path)); -+ } -+ -+ private int getInt(String path, int def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getInt("world-settings." + worldName + "." + path, config.getInt("world-settings.default." + path)); -+ } -+ -+ private float getFloat(String path, float def) { -+ // TODO: Figure out why getFloat() always returns the default value. -+ return (float) getDouble(path, (double) def); -+ } -+ -+ private List getList(String path, List def) { -+ config.addDefault("world-settings.default." + path, def); -+ return (List) config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)); -+ } -+ -+ private String getString(String path, String def) { -+ config.addDefault("world-settings.default." + path, def); -+ return config.getString("world-settings." + worldName + "." + path, config.getString("world-settings.default." + path)); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ public class Main { - DedicatedServerSettings dedicatedserversettings = new DedicatedServerSettings(iregistrycustom_dimension, optionset); // CraftBukkit - CLI argument support - - dedicatedserversettings.save(); -+ // Paper start - load config files for access below if needed -+ org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = loadConfigFile((File) optionset.valueOf("bukkit-settings")); -+ org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = loadConfigFile((File) optionset.valueOf("spigot-settings")); -+ org.bukkit.configuration.file.YamlConfiguration paperConfiguration = loadConfigFile((File) optionset.valueOf("paper-settings")); -+ // Paper end -+ - java.nio.file.Path java_nio_file_path1 = Paths.get("eula.txt"); - EULA eula = new EULA(java_nio_file_path1); - -@@ -0,0 +0,0 @@ public class Main { - - } - -+ // Paper start - load config files -+ private static org.bukkit.configuration.file.YamlConfiguration loadConfigFile(File configFile) throws Exception { -+ org.bukkit.configuration.file.YamlConfiguration config = new org.bukkit.configuration.file.YamlConfiguration(); -+ if (configFile.exists()) { -+ try { -+ config.load(configFile); -+ } catch (Exception ex) { -+ throw new Exception("Failed to load configuration file: " + configFile.getName(), ex); -+ } -+ } -+ return config; -+ } -+ // Paper end -+ - public static void convertWorld(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, boolean flag, BooleanSupplier booleansupplier, ImmutableSet> immutableset) { // CraftBukkit - Main.LOGGER.info("Forcing world upgrade! {}", convertable_conversionsession.getLevelName()); // CraftBukkit - WorldUpgrader worldupgrader = new WorldUpgrader(convertable_conversionsession, datafixer, immutableset, flag); -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 IMinecraftServer - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start -+ try { -+ com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -+ } catch (Exception e) { -+ DedicatedServer.LOGGER.error("Unable to load server configuration", e); -+ return false; -+ } -+ com.destroystokyo.paper.PaperConfig.registerCommands(); -+ // Paper end - - this.setPVP(dedicatedserverproperties.pvp); - this.setAllowFlight(dedicatedserverproperties.allowFlight); -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } - } - -- @Override -- public boolean a(Entity entity) { -+ public final boolean isInEntityTickingChunk(Entity entity) { return this.a(entity); } // Paper - OBFHELPER -+ @Override public boolean a(Entity entity) { - long i = ChunkCoordIntPair.pair(MathHelper.floor(entity.locX()) >> 4, MathHelper.floor(entity.locZ()) >> 4); - - return this.a(i, (Function>>) PlayerChunk::b); // CraftBukkit - decompile error - } - -- @Override -- public boolean a(ChunkCoordIntPair chunkcoordintpair) { -+ public final boolean isEntityTickingChunk(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } // Paper - OBFHELPER -+ @Override public boolean a(ChunkCoordIntPair chunkcoordintpair) { - return this.a(chunkcoordintpair.pair(), (Function>>) PlayerChunk::b); // CraftBukkit - decompile error - } - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ package net.minecraft.world.entity; - - import com.google.common.collect.ImmutableSet; - import java.util.Optional; -+import java.util.Set; // Paper - import java.util.UUID; - import java.util.function.Function; - import java.util.stream.Stream; -@@ -0,0 +0,0 @@ public class EntityTypes { - return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); - } - } -+ -+ // Paper start -+ public static Set getEntityNameList() { -+ return IRegistry.ENTITY_TYPE.keySet(); -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean populating; - public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot - -+ public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper -+ - public final SpigotTimings.WorldTimingsHandler timings; // Spigot - public static BlockPosition lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - protected World(WorldDataMutable worlddatamutable, ResourceKey resourcekey, final DimensionManager dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName()); // Spigot -+ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.WorldDataServer) worlddatamutable).getName(), this.spigotConfig); // Paper - this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } - - org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot -+ com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper - for (WorldServer world : console.getWorlds()) { - world.worldDataServer.setDifficulty(config.difficulty); - world.setSpawnFlags(config.spawnMonsters, config.spawnAnimals); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); - } - world.spigotConfig.init(); // Spigot -+ world.paperConfig.init(); // Paper - } - - pluginManager.clearPlugins(); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot -+ com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper - overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*"); - ignoreVanillaPermissions = commandsConfiguration.getBoolean("ignore-vanilla-permissions"); - -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return spigot; - } - // Spigot end -+ -+ // Paper start -+ @SuppressWarnings({"rawtypes", "unchecked"}) -+ public static java.nio.file.Path dumpHeap(java.nio.file.Path dir, String name) { -+ try { -+ java.nio.file.Files.createDirectories(dir); -+ -+ javax.management.MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); -+ java.nio.file.Path file; -+ -+ try { -+ Class clazz = Class.forName("openj9.lang.management.OpenJ9DiagnosticsMXBean"); -+ Object openj9Mbean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "openj9.lang.management:type=OpenJ9Diagnostics", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("triggerDumpToFile", String.class, String.class); -+ file = dir.resolve(name + ".phd"); -+ m.invoke(openj9Mbean, "heap", file.toString()); -+ } catch (ClassNotFoundException e) { -+ Class clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean"); -+ Object hotspotMBean = java.lang.management.ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", clazz); -+ java.lang.reflect.Method m = clazz.getMethod("dumpHeap", String.class, boolean.class); -+ file = dir.resolve(name + ".hprof"); -+ m.invoke(hotspotMBean, file.toString(), true); -+ } -+ -+ return file; -+ } catch (Throwable t) { -+ Bukkit.getLogger().log(Level.SEVERE, "Could not write heap", t); -+ return null; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - .defaultsTo(new File("spigot.yml")) - .describedAs("Yml file"); - // Spigot End -+ -+ // Paper Start -+ acceptsAll(asList("paper", "paper-settings"), "File for paper settings") -+ .withRequiredArg() -+ .ofType(File.class) -+ .defaultsTo(new File("paper.yml")) -+ .describedAs("Yml file"); -+ // Paper end - } - }; - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -0,0 +0,0 @@ public class SpigotWorldConfig - config.set( "world-settings.default." + path, val ); - } - -- private boolean getBoolean(String path, boolean def) -+ public boolean getBoolean(String path, boolean def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getBoolean( "world-settings." + worldName + "." + path, config.getBoolean( "world-settings.default." + path ) ); - } - -- private double getDouble(String path, double def) -+ public double getDouble(String path, double def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getDouble( "world-settings." + worldName + "." + path, config.getDouble( "world-settings.default." + path ) ); - } - -- private int getInt(String path) -+ public int getInt(String path) // Paper - private -> public - { - return config.getInt( "world-settings." + worldName + "." + path ); - } - -- private int getInt(String path, int def) -+ public int getInt(String path, int def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getInt( "world-settings." + worldName + "." + path, config.getInt( "world-settings.default." + path ) ); - } - -- private List getList(String path, T def) -+ public List getList(String path, T def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return (List) config.getList( "world-settings." + worldName + "." + path, config.getList( "world-settings.default." + path ) ); - } - -- private String getString(String path, String def) -+ public String getString(String path, String def) // Paper - private -> public - { - config.addDefault( "world-settings.default." + path, def ); - return config.getString( "world-settings." + worldName + "." + path, config.getString( "world-settings.default." + path ) ); diff --git a/Spigot-Server-Patches/Paper-dumpitem-command.patch b/Spigot-Server-Patches/Paper-dumpitem-command.patch deleted file mode 100644 index 60e484616c..0000000000 --- a/Spigot-Server-Patches/Paper-dumpitem-command.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 28 Jun 2020 19:27:20 -0400 -Subject: [PATCH] Paper dumpitem command - -Let's you quickly view the item in your hands NBT data - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import net.minecraft.core.BlockPosition; -+import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.game.PacketPlayOutLightUpdate; - import net.minecraft.resources.MinecraftKey; - import com.google.gson.JsonObject; -@@ -0,0 +0,0 @@ import org.bukkit.command.CommandSender; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; - import org.bukkit.entity.Player; -+import org.bukkit.inventory.ItemStack; - - import java.io.File; - import java.io.FileOutputStream; -@@ -0,0 +0,0 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight", "dumpitem").build(); - - public PaperCommand(String name) { - super(name); -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - case "reload": - doReload(sender); - break; -+ case "dumpitem": -+ doDumpItem(sender); -+ break; - case "debug": - doDebug(sender, args); - break; -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doDumpItem(CommandSender sender) { -+ ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); -+ net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); -+ NBTTagCompound tag = itemStack.getTag(); -+ if (tag != null) { -+ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); -+ Bukkit.getConsoleSender().sendMessage(nbt); -+ sender.sendMessage(nbt); -+ } else { -+ sender.sendMessage("Item does not have NBT"); -+ } -+ } -+ - private void doFixLight(CommandSender sender, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage("Only players can use this command"); -diff --git a/src/main/java/net/minecraft/nbt/NBTBase.java b/src/main/java/net/minecraft/nbt/NBTBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTBase.java -+++ b/src/main/java/net/minecraft/nbt/NBTBase.java -@@ -0,0 +0,0 @@ public interface NBTBase { - return this.toString(); - } - -+ default IChatBaseComponent getNbtPrettyComponent() { return this.l(); } // Paper - OBFHELPER - default IChatBaseComponent l() { - return this.a("", 0); - } diff --git a/Spigot-Server-Patches/Per-Player-View-Distance-API-placeholders.patch b/Spigot-Server-Patches/Per-Player-View-Distance-API-placeholders.patch deleted file mode 100644 index 361b134c93..0000000000 --- a/Spigot-Server-Patches/Per-Player-View-Distance-API-placeholders.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Mon, 6 May 2019 01:29:25 -0400 -Subject: [PATCH] Per-Player View Distance API placeholders - -I hope to look at this more in-depth soon. It appears doable. -However this should not block the update. - -diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EntityEnderDragon.java -@@ -0,0 +0,0 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster { - if (this.deathAnimationTicks == 1 && !this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1028, this.getChunkCoordinates(), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // Paper end - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - if (!this.isSilent()) { - // CraftBukkit start - Use relative location for far away sounds - // this.world.b(1023, new BlockPosition(this), 0); -- //int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API -+ int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16; // Paper - updated to use worlds actual view distance incase we have to uncomment this due to removal of player view distance API - for (EntityPlayer player : (List)this.world.getPlayers()) { -- final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch -+ // final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); - double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - super.remove(); - } - } -+ -+ @Override -+ public int getViewDistance() { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } -+ -+ @Override -+ public void setViewDistance(int viewDistance) { -+ throw new NotImplementedException("Per-Player View Distance APIs need further understanding to properly implement (There are per world view distances though!)"); // TODO -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/Performance-improvement-for-Chunk.getEntities.patch b/Spigot-Server-Patches/Performance-improvement-for-Chunk.getEntities.patch deleted file mode 100644 index fd67b133dc..0000000000 --- a/Spigot-Server-Patches/Performance-improvement-for-Chunk.getEntities.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: wea_ondara -Date: Thu, 10 Oct 2019 11:29:42 +0200 -Subject: [PATCH] Performance improvement for Chunk.getEntities - -This patch aims to reduce performance cost used by collecting the -entities of a chunk. Previously the entitySlices were copied into an -extra array with List.toArray() with is a costly and unneccessary -operation. This patch will reduce the load of plugins which for example -implement custom moblimits and depend on Chunk.getEntities(). - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { - Entity[] entities = new Entity[count]; - - for (int i = 0; i < 16; i++) { -- -- for (Object obj : chunk.entitySlices[i].toArray()) { -- if (!(obj instanceof net.minecraft.world.entity.Entity)) { -+ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) -+ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { -+ if (entity == null) { - continue; - } -- -- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); -+ entities[index++] = entity.getBukkitEntity(); - } -+ // Paper end - } - - return entities; diff --git a/Spigot-Server-Patches/Pillager-patrol-spawn-settings-and-per-player-option.patch b/Spigot-Server-Patches/Pillager-patrol-spawn-settings-and-per-player-option.patch deleted file mode 100644 index 36bcdaeed7..0000000000 --- a/Spigot-Server-Patches/Pillager-patrol-spawn-settings-and-per-player-option.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Sat, 1 Feb 2020 16:50:39 +0100 -Subject: [PATCH] Pillager patrol spawn settings and per player options - -This adds config options for defining the spawn chance, spawn delay and -spawn start day as well as toggles for handling the spawn delay and -start day per player. (Based on the time played statistic) -When not per player it will use the Vanilla mechanic of one delay per -world and the world age for the start day. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - } - - public boolean disablePillagerPatrols = false; -+ public double patrolSpawnChance = 0.2; -+ public boolean patrolPerPlayerDelay = false; -+ public int patrolDelay = 12000; -+ public boolean patrolPerPlayerStart = false; -+ public int patrolStartDay = 5; - private void pillagerSettings() { - disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); -+ patrolSpawnChance = getDouble("game-mechanics.pillager-patrols.spawn-chance", patrolSpawnChance); -+ patrolPerPlayerDelay = getBoolean("game-mechanics.pillager-patrols.spawn-delay.per-player", patrolPerPlayerDelay); -+ patrolDelay = getInt("game-mechanics.pillager-patrols.spawn-delay.ticks", patrolDelay); -+ patrolPerPlayerStart = getBoolean("game-mechanics.pillager-patrols.start.per-player", patrolPerPlayerStart); -+ patrolStartDay = getInt("game-mechanics.pillager-patrols.start.day", patrolStartDay); - } - -+ - public boolean entitiesTargetWithFollowRange = false; - private void entitiesTargetWithFollowRange() { - entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean viewingCredits; - private int containerUpdateDelay; // Paper - public long loginTime; // Paper -+ public int patrolSpawnDelay; // Paper - per player patrol spawns - // Paper start - cancellable death event - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; -diff --git a/src/main/java/net/minecraft/stats/StatisticWrapper.java b/src/main/java/net/minecraft/stats/StatisticWrapper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/stats/StatisticWrapper.java -+++ b/src/main/java/net/minecraft/stats/StatisticWrapper.java -@@ -0,0 +0,0 @@ public class StatisticWrapper implements Iterable> { - return this.b.values().iterator(); - } - -+ public final Statistic get(T t) { return this.b(t); }; // Paper - OBFHELPER - public Statistic b(T t0) { - return this.a(t0, Counter.DEFAULT); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/MobSpawnerPatrol.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.levelgen; - import java.util.Random; - import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; -+import net.minecraft.stats.StatisticList; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.entity.EnumMobSpawn; - import net.minecraft.world.entity.GroupDataEntity; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.IBlockData; - - public class MobSpawnerPatrol implements MobSpawner { - -- private int a; -+ private int a;private int getSpawnDelay() { return a; } private void setSpawnDelay(int spawnDelay) { this.a = spawnDelay; } // Paper - OBFHELPER - - public MobSpawnerPatrol() {} - - @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -- if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper -+ if (worldserver.paperConfig.disablePillagerPatrols || worldserver.paperConfig.patrolSpawnChance == 0) return 0; // Paper - if (!flag) { - return 0; - } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { -@@ -0,0 +0,0 @@ public class MobSpawnerPatrol implements MobSpawner { - } else { - Random random = worldserver.random; - -- --this.a; -- if (this.a > 0) { -+ // Paper start - Patrol settings -+ // Random player selection moved up for per player spawning and configuration -+ int j = worldserver.getPlayers().size(); -+ if (j < 1) { - return 0; -+ } -+ -+ EntityPlayer entityhuman = worldserver.getPlayers().get(random.nextInt(j)); -+ if (entityhuman.isSpectator()) { -+ return 0; -+ } -+ -+ int patrolSpawnDelay; -+ if (worldserver.paperConfig.patrolPerPlayerDelay) { -+ --entityhuman.patrolSpawnDelay; -+ patrolSpawnDelay = entityhuman.patrolSpawnDelay; - } else { -- this.a += 12000 + random.nextInt(1200); -- long i = worldserver.getDayTime() / 24000L; -+ setSpawnDelay(getSpawnDelay() - 1); -+ patrolSpawnDelay = getSpawnDelay(); -+ } -+ -+ if (patrolSpawnDelay > 0) { -+ return 0; -+ } else { -+ long days; -+ if (worldserver.paperConfig.patrolPerPlayerStart) { -+ days = entityhuman.getStatisticManager().getStatisticValue(StatisticList.CUSTOM.get(StatisticList.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang -+ } else { -+ days = worldserver.getDayTime() / 24000L; -+ } -+ if (worldserver.paperConfig.patrolPerPlayerDelay) { -+ entityhuman.patrolSpawnDelay += worldserver.paperConfig.patrolDelay + random.nextInt(1200); -+ } else { -+ setSpawnDelay(getSpawnDelay() + worldserver.paperConfig.patrolDelay + random.nextInt(1200)); -+ } - -- if (i >= 5L && worldserver.isDay()) { -- if (random.nextInt(5) != 0) { -+ if (days >= worldserver.paperConfig.patrolStartDay && worldserver.isDay()) { -+ if (random.nextDouble() >= worldserver.paperConfig.patrolSpawnChance) { -+ // Paper end - return 0; - } else { -- int j = worldserver.getPlayers().size(); - - if (j < 1) { - return 0; - } else { -- EntityHuman entityhuman = (EntityHuman) worldserver.getPlayers().get(random.nextInt(j)); - - if (entityhuman.isSpectator()) { - return 0; diff --git a/Spigot-Server-Patches/Player-Chunk-Load-Unload-Events.patch b/Spigot-Server-Patches/Player-Chunk-Load-Unload-Events.patch deleted file mode 100644 index 6f8354cd9e..0000000000 --- a/Spigot-Server-Patches/Player-Chunk-Load-Unload-Events.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Mon, 5 Oct 2020 21:25:16 +0200 -Subject: [PATCH] Player Chunk Load/Unload Events - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.world.scores.ScoreboardScore; - import net.minecraft.world.scores.ScoreboardTeam; - import net.minecraft.world.scores.ScoreboardTeamBase; - import net.minecraft.world.scores.criteria.IScoreboardCriteria; -+import io.papermc.paper.event.packet.PlayerChunkLoadEvent; // Paper -+import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public void a(ChunkCoordIntPair chunkcoordintpair, Packet packet, Packet packet1) { - this.playerConnection.sendPacket(packet1); - this.playerConnection.sendPacket(packet); -+ // Paper start -+ if(PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - public void a(ChunkCoordIntPair chunkcoordintpair) { - if (this.isAlive()) { - this.playerConnection.sendPacket(new PacketPlayOutUnloadChunk(chunkcoordintpair.x, chunkcoordintpair.z)); -+ // Paper start -+ if(PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ -+ new PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); -+ } -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/Player-Tab-List-and-Title-APIs.patch b/Spigot-Server-Patches/Player-Tab-List-and-Title-APIs.patch deleted file mode 100644 index de205d3627..0000000000 --- a/Spigot-Server-Patches/Player-Tab-List-and-Title-APIs.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Thu, 3 Mar 2016 02:32:10 -0600 -Subject: [PATCH] Player Tab List and Title APIs - - -diff --git a/src/main/java/net/minecraft/network/PacketDataSerializer.java b/src/main/java/net/minecraft/network/PacketDataSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/PacketDataSerializer.java -+++ b/src/main/java/net/minecraft/network/PacketDataSerializer.java -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { - return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144); - } -+ -+ @Deprecated -+ public PacketDataSerializer writeComponent(final net.md_5.bungee.api.chat.BaseComponent[] component) { -+ return this.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(component), 262144); -+ } - // Paper end - - public PacketDataSerializer a(IChatBaseComponent ichatbasecomponent) { -diff --git a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -+++ b/src/main/java/net/minecraft/network/chat/IChatBaseComponent.java -@@ -0,0 +0,0 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable -Date: Tue, 1 Mar 2016 14:47:52 -0600 -Subject: [PATCH] Player affects spawning API - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return MathHelper.c(f * f + f1 * f1 + f2 * f2); - } - -+ public double getDistanceSquared(double x, double y, double z) { return h(x, y, z); } // Paper - OBFHELPER - public double h(double d0, double d1, double d2) { - double d3 = this.locX() - d0; - double d4 = this.locY() - d1; -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.L()) { - this.die(); - } else if (!this.isPersistent() && !this.isSpecialPersistence()) { -- EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D); -+ EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D, IEntitySelector.affectsSpawning); // Paper - - if (entityhuman != null) { - double d0 = entityhuman.h((Entity) this); // CraftBukkit - decompile error -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -0,0 +0,0 @@ public final class IEntitySelector { - return !entity.isSpectator(); - }; - -+ // Paper start -+ public static final Predicate affectsSpawning = (entity) -> { -+ return !entity.isSpectator() && entity.isAlive() && (entity instanceof EntityPlayer) && ((EntityPlayer) entity).affectsSpawning; -+ }; -+ // Paper end -+ - public static Predicate a(double d0, double d1, double d2, double d3) { - double d4 = d3 * d3; - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySilverfish.java -@@ -0,0 +0,0 @@ public class EntitySilverfish extends EntityMonster { - if (c(entitytypes, generatoraccess, enummobspawn, blockposition, random)) { - EntityHuman entityhuman = generatoraccess.a((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, 5.0D, true); - -- return entityhuman == null; -+ return !(entityhuman != null && !entityhuman.affectsSpawning) && entityhuman == null; // Paper - Affects Spawning API - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - private final ItemCooldown bM; - @Nullable - public EntityFishingHook hookedFish; -+ // Paper start -+ public boolean affectsSpawning = true; -+ // Paper end - - // CraftBukkit start - public boolean fauxSleeping; -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -0,0 +0,0 @@ public interface IEntityAccess { - } - } - -- @Nullable -- default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { -+ default EntityHuman findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.findNearbyPlayer(entity.locX(), entity.locY(), entity.locZ(), d0, predicate); } // Paper -+ @Nullable default EntityHuman findNearbyPlayer(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { return a(d0, d1, d2, d3, predicate); } // Paper - OBFHELPER -+ @Nullable default EntityHuman a(double d0, double d1, double d2, double d3, @Nullable Predicate predicate) { // Paper - double d4 = -1.0D; - EntityHuman entityhuman = null; - Iterator iterator = this.getPlayers().iterator(); -@@ -0,0 +0,0 @@ public interface IEntityAccess { - return this.a(d0, d1, d2, d3, predicate); - } - -+ // Paper end -+ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { -+ Iterator iterator = this.getPlayers().iterator(); -+ double d4; -+ do { -+ EntityHuman entityhuman; -+ do { -+ if (!iterator.hasNext()) { -+ return false; -+ } -+ -+ entityhuman = (EntityHuman) iterator.next(); -+ } while (!IEntitySelector.affectsSpawning.test(entityhuman)); -+ -+ d4 = entityhuman.getDistanceSquared(d0, d1, d2); -+ } while (d3 >= 0.0D && d4 >= d3 * d3); -+ -+ return true; -+ } -+ // Paper end -+ - default boolean isPlayerNearby(double d0, double d1, double d2, double d3) { - Iterator iterator = this.getPlayers().iterator(); - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - private boolean h() { - BlockPosition blockposition = this.b(); - -- return this.a().isPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); -+ return this.a().isAffectsSpawningPlayerNearby((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper - } - - public void c() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - @Override - public String getLocale() { - return getHandle().locale; -+ -+ } -+ -+ // Paper start -+ public void setAffectsSpawning(boolean affects) { -+ this.getHandle().affectsSpawning = affects; - } - -+ @Override -+ public boolean getAffectsSpawning() { -+ return this.getHandle().affectsSpawning; -+ } -+ // Paper end -+ - @Override - public void updateCommands() { - if (getHandle().playerConnection == null) return; diff --git a/Spigot-Server-Patches/Player-elytra-boost-API.patch b/Spigot-Server-Patches/Player-elytra-boost-API.patch deleted file mode 100644 index 5b5a7579a1..0000000000 --- a/Spigot-Server-Patches/Player-elytra-boost-API.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 14 Apr 2020 12:05:22 +0200 -Subject: [PATCH] Player elytra boost API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.ai.attributes.AttributeMapBase; - import net.minecraft.world.entity.ai.attributes.AttributeModifiable; - import net.minecraft.world.entity.ai.attributes.GenericAttributes; - import net.minecraft.world.entity.player.EntityHuman; -+import net.minecraft.world.entity.projectile.EntityFireworks; - import net.minecraft.world.inventory.Container; - import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.EnumGamemode; -+import net.minecraft.world.level.World; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - throw new RuntimeException("Unknown settings type"); - } -+ -+ @Override -+ public org.bukkit.entity.Firework boostElytra(ItemStack firework) { -+ Validate.isTrue(isGliding(), "Player must be gliding"); -+ Validate.isTrue(firework != null, "firework == null"); -+ Validate.isTrue(firework.getType() == Material.FIREWORK_ROCKET, "Firework must be Material.FIREWORK_ROCKET"); -+ -+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(firework); -+ World world = ((CraftWorld) getWorld()).getHandle(); -+ EntityFireworks entity = new EntityFireworks(world, item, getHandle()); -+ return world.addEntity(entity) -+ ? (org.bukkit.entity.Firework) entity.getBukkitEntity() -+ : null; -+ } - // Paper end - - // Spigot start diff --git a/Spigot-Server-Patches/Player.setPlayerProfile-API.patch b/Spigot-Server-Patches/Player.setPlayerProfile-API.patch deleted file mode 100644 index c9c2661e70..0000000000 --- a/Spigot-Server-Patches/Player.setPlayerProfile-API.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 18 Mar 2018 12:29:48 -0400 -Subject: [PATCH] Player.setPlayerProfile API - -This can be useful for changing name or skins after a player has logged in. - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - public final NetworkManager networkManager; - private LoginListener.EnumProtocolState g; - private int h; -- private GameProfile i; -+ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER - private final String j; - private SecretKey loginKey; - private EntityPlayer l; -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - final org.bukkit.craftbukkit.CraftServer server = LoginListener.this.server.server; - - // Paper start -- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); -+ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); - server.getPluginManager().callEvent(asyncEvent); - profile = asyncEvent.getPlayerProfile(); -- profile.complete(); -- i = CraftPlayerProfile.asAuthlibCopy(profile); -+ profile.complete(true); -+ setGameProfile(CraftPlayerProfile.asAuthlib(profile)); - playerName = i.getName(); - uniqueId = i.getId(); - // Paper end -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - protected int bG; - protected final float bH = 0.02F; - private int g; -- private final GameProfile bJ; -+ private GameProfile bJ; public final void setProfile(final GameProfile profile) { this.bJ = profile; } // Paper - OBFHELPER - private ItemStack bL; - private final ItemCooldown bM; - @Nullable -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.item.enchantment.Enchantments; - import net.minecraft.world.level.EnumGamemode; -+import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.block.entity.TileEntitySign; - import net.minecraft.world.level.saveddata.maps.MapIcon; - import net.minecraft.world.phys.Vec3D; -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - hiddenPlayers.put(player.getUniqueId(), hidingPlugins); - - // Remove this player from the hidden player's EntityTrackerEntry -- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper start - EntityPlayer other = ((CraftPlayer) player).getHandle(); -+ unregisterPlayer(other); -+ } -+ private void unregisterPlayer(EntityPlayer other) { -+ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper end - PlayerChunkMap.EntityTracker entry = tracker.trackedEntities.get(other.getId()); - if (entry != null) { - entry.clear(getHandle()); -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - hiddenPlayers.remove(player.getUniqueId()); - -- PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper start - EntityPlayer other = ((CraftPlayer) player).getHandle(); -+ registerPlayer(other); -+ } -+ private void registerPlayer(EntityPlayer other) { -+ PlayerChunkMap tracker = ((WorldServer) entity.world).getChunkProvider().playerChunkMap; -+ // Paper end - - getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, other)); - -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - entry.updatePlayer(getHandle()); - } - } -+ // Paper start -+ private void reregisterPlayer(EntityPlayer player) { -+ if (!hiddenPlayers.containsKey(player.getUniqueID())) { -+ unregisterPlayer(player); -+ registerPlayer(player); -+ } -+ } -+ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { -+ EntityPlayer self = getHandle(); -+ self.setProfile(com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile)); -+ if (!self.sentListPacket) { -+ return; -+ } -+ List players = server.getServer().getPlayerList().players; -+ for (EntityPlayer player : players) { -+ player.getBukkitEntity().reregisterPlayer(self); -+ } -+ refreshPlayer(); -+ } -+ public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { -+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this).clone(); -+ } -+ -+ private void refreshPlayer() { -+ EntityPlayer handle = getHandle(); -+ -+ Location loc = getLocation(); -+ -+ PlayerConnection connection = handle.playerConnection; -+ reregisterPlayer(handle); -+ -+ //Respawn the player then update their position and selected slot -+ WorldServer worldserver = handle.getWorldServer(); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutRespawn(worldserver.getDimensionManager(), worldserver.getDimensionKey(), BiomeManager.a(worldserver.getSeed()), handle.playerInteractManager.getGameMode(), handle.playerInteractManager.c(), worldserver.isDebugWorld(), worldserver.isFlatWorld(), true)); -+ handle.updateAbilities(); -+ connection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), new HashSet<>(), 0)); -+ net.minecraft.server.MinecraftServer.getServer().getPlayerList().updateClient(handle); -+ -+ if (this.isOp()) { -+ this.setOp(false); -+ this.setOp(true); -+ } -+ } -+ // Paper end - - public void removeDisconnectingPlayer(Player player) { - hiddenPlayers.remove(player.getUniqueId()); diff --git a/Spigot-Server-Patches/PlayerAdvancementCriterionGrantEvent.patch b/Spigot-Server-Patches/PlayerAdvancementCriterionGrantEvent.patch deleted file mode 100644 index 42595d86d6..0000000000 --- a/Spigot-Server-Patches/PlayerAdvancementCriterionGrantEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 19 Jan 2018 08:15:29 -0600 -Subject: [PATCH] PlayerAdvancementCriterionGrantEvent - - -diff --git a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -+++ b/src/main/java/net/minecraft/server/AdvancementDataPlayer.java -@@ -0,0 +0,0 @@ public class AdvancementDataPlayer { - boolean flag1 = advancementprogress.isDone(); - - if (advancementprogress.a(s)) { -+ // Paper start -+ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, s).callEvent()) { -+ advancementprogress.b(s); -+ return false; -+ } -+ // Paper end - this.d(advancement); - this.j.add(advancement); - flag = true; diff --git a/Spigot-Server-Patches/PlayerAttemptPickupItemEvent.patch b/Spigot-Server-Patches/PlayerAttemptPickupItemEvent.patch deleted file mode 100644 index 0ca1f099ec..0000000000 --- a/Spigot-Server-Patches/PlayerAttemptPickupItemEvent.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 11 Jun 2017 16:30:30 -0500 -Subject: [PATCH] PlayerAttemptPickupItemEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer; - import org.bukkit.event.entity.EntityPickupItemEvent; - import org.bukkit.event.player.PlayerPickupItemEvent; - // CraftBukkit end -+import org.bukkit.event.player.PlayerAttemptPickupItemEvent; // Paper - - public class EntityItem extends Entity { - -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - int remaining = i - canHold; - boolean flyAtPlayer = false; // Paper - -+ // Paper start -+ if (this.pickupDelay <= 0) { -+ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); -+ this.world.getServer().getPluginManager().callEvent(attemptEvent); -+ -+ flyAtPlayer = attemptEvent.getFlyAtPlayer(); -+ if (attemptEvent.isCancelled()) { -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ -+ return; -+ } -+ } -+ // Paper end -+ - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); - // Call legacy event diff --git a/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch b/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch deleted file mode 100644 index bd0e0794fc..0000000000 --- a/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Mar 2019 23:01:33 -0400 -Subject: [PATCH] PlayerDeathEvent#getItemsToKeep - -Exposes a mutable array on items a player should keep on death - -Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - }); - } - -+ // Paper start - process inventory -+ private static void processKeep(org.bukkit.event.entity.PlayerDeathEvent event, NonNullList inv) { -+ List itemsToKeep = event.getItemsToKeep(); -+ if (inv == null) { -+ // remainder of items left in toKeep - plugin added stuff on death that wasn't in the initial loot? -+ if (!itemsToKeep.isEmpty()) { -+ for (org.bukkit.inventory.ItemStack itemStack : itemsToKeep) { -+ event.getEntity().getInventory().addItem(itemStack); -+ } -+ } -+ -+ return; -+ } -+ -+ for (int i = 0; i < inv.size(); ++i) { -+ ItemStack item = inv.get(i); -+ if (EnchantmentManager.shouldNotDrop(item) || itemsToKeep.isEmpty() || item.isEmpty()) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ continue; -+ } -+ -+ final org.bukkit.inventory.ItemStack bukkitStack = item.getBukkitStack(); -+ boolean keep = false; -+ final Iterator iterator = itemsToKeep.iterator(); -+ while (iterator.hasNext()) { -+ final org.bukkit.inventory.ItemStack itemStack = iterator.next(); -+ if (bukkitStack.equals(itemStack)) { -+ iterator.remove(); -+ keep = true; -+ break; -+ } -+ } -+ -+ if (!keep) { -+ inv.set(i, ItemStack.NULL_ITEM); -+ } -+ } -+ } -+ // Paper end -+ - @Override - public void die(DamageSource damagesource) { - boolean flag = this.world.getGameRules().getBoolean(GameRules.SHOW_DEATH_MESSAGES); -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.dropExperience(); - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { -- this.inventory.clear(); -+ // Paper start - replace logic -+ for (NonNullList inv : this.inventory.getComponents()) { -+ processKeep(event, inv); -+ } -+ processKeep(event, null); -+ // Paper end - } - - this.setSpectatorTarget(this); // Remove spectated target diff --git a/Spigot-Server-Patches/PlayerDeathEvent-shouldDropExperience.patch b/Spigot-Server-Patches/PlayerDeathEvent-shouldDropExperience.patch deleted file mode 100644 index 1b7c30e2a7..0000000000 --- a/Spigot-Server-Patches/PlayerDeathEvent-shouldDropExperience.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 24 Dec 2019 00:35:42 +0000 -Subject: [PATCH] PlayerDeathEvent#shouldDropExperience - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.eW(); - } - // SPIGOT-5478 must be called manually now -- this.dropExperience(); -+ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event - // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. - if (!event.getKeepInventory()) { - // Paper start - replace logic diff --git a/Spigot-Server-Patches/PlayerElytraBoostEvent.patch b/Spigot-Server-Patches/PlayerElytraBoostEvent.patch deleted file mode 100644 index 74483a7f8b..0000000000 --- a/Spigot-Server-Patches/PlayerElytraBoostEvent.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 01:59:59 -0500 -Subject: [PATCH] PlayerElytraBoostEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -0,0 +0,0 @@ public class ItemFireworks extends Item { - // Paper start - final EntityFireworks entityfireworks = new EntityFireworks(world, itemstack, entityhuman); - entityfireworks.spawningEntity = entityhuman.getUniqueID(); -- world.addEntity(entityfireworks); -- // Paper end -- if (!entityhuman.abilities.canInstantlyBuild) { -- itemstack.subtract(1); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityfireworks)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -+ // Paper end - } - - return InteractionResultWrapper.a(entityhuman.b(enumhand), world.s_()); diff --git a/Spigot-Server-Patches/PlayerLaunchProjectileEvent.patch b/Spigot-Server-Patches/PlayerLaunchProjectileEvent.patch deleted file mode 100644 index 9148d213c7..0000000000 --- a/Spigot-Server-Patches/PlayerLaunchProjectileEvent.patch +++ /dev/null @@ -1,329 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 21 Jul 2018 03:11:03 -0500 -Subject: [PATCH] PlayerLaunchProjectileEvent - - -diff --git a/src/main/java/net/minecraft/world/InteractionResultWrapper.java b/src/main/java/net/minecraft/world/InteractionResultWrapper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/InteractionResultWrapper.java -+++ b/src/main/java/net/minecraft/world/InteractionResultWrapper.java -@@ -0,0 +0,0 @@ public class InteractionResultWrapper { - this.b = t0; - } - -+ public EnumInteractionResult getResult() { return this.a(); } // Paper - OBFHELPER - public EnumInteractionResult a() { - return this.a; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemEgg.java b/src/main/java/net/minecraft/world/item/ItemEgg.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemEgg.java -+++ b/src/main/java/net/minecraft/world/item/ItemEgg.java -@@ -0,0 +0,0 @@ public class ItemEgg extends Item { - - entityegg.setItem(itemstack); - entityegg.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- // CraftBukkit start -- if (!world.addEntity(entityegg)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityegg)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { - if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { - ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -- return InteractionResultWrapper.fail(itemstack); -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); - } -- // CraftBukkit end -+ // Paper end -+ -+ - } - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemEgg.RANDOM.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -+++ b/src/main/java/net/minecraft/world/item/ItemEnderPearl.java -@@ -0,0 +0,0 @@ public class ItemEnderPearl extends Item { - - entityenderpearl.setItem(itemstack); - entityenderpearl.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- if (!world.addEntity(entityenderpearl)) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entityenderpearl)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ entityhuman.getCooldownTracker().setCooldown(this, 20); -+ } else { -+ // Paper end - if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { - ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - } -- return InteractionResultWrapper.fail(itemstack); -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); - } - } - -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -- entityhuman.getCooldownTracker().setCooldown(this, 20); -- // CraftBukkit end -- -- entityhuman.b(StatisticList.ITEM_USED.b(this)); -- if (!entityhuman.abilities.canInstantlyBuild) { -- itemstack.subtract(1); -- } -+ // Paper start - moved up -+// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F)); -+// entityhuman.getCooldownTracker().setCooldown(this, 20); -+// // CraftBukkit end -+// -+// entityhuman.b(StatisticList.ITEM_USED.b(this)); -+// if (!entityhuman.abilities.canInstantlyBuild) { -+// itemstack.subtract(1); -+// } -+ // Paper end - moved up - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemExpBottle.java b/src/main/java/net/minecraft/world/item/ItemExpBottle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemExpBottle.java -+++ b/src/main/java/net/minecraft/world/item/ItemExpBottle.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.stats.StatisticList; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; -+import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityThrownExpBottle; - import net.minecraft.world.level.World; -@@ -0,0 +0,0 @@ public class ItemExpBottle extends Item { - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { - ItemStack itemstack = entityhuman.b(enumhand); - -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); -+ //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down - if (!world.isClientSide) { - EntityThrownExpBottle entitythrownexpbottle = new EntityThrownExpBottle(world, entityhuman); - - entitythrownexpbottle.setItem(itemstack); - entitythrownexpbottle.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.7F, 1.0F); -- world.addEntity(entitythrownexpbottle); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitythrownexpbottle.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitythrownexpbottle)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { -+ if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemFireworks.java b/src/main/java/net/minecraft/world/item/ItemFireworks.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemFireworks.java -+++ b/src/main/java/net/minecraft/world/item/ItemFireworks.java -@@ -0,0 +0,0 @@ package net.minecraft.world.item; - import java.util.Arrays; - import java.util.Comparator; - import net.minecraft.core.EnumDirection; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; -@@ -0,0 +0,0 @@ public class ItemFireworks extends Item { - EntityFireworks entityfireworks = new EntityFireworks(world, itemactioncontext.getEntity(), vec3d.x + (double) enumdirection.getAdjacentX() * 0.15D, vec3d.y + (double) enumdirection.getAdjacentY() * 0.15D, vec3d.z + (double) enumdirection.getAdjacentZ() * 0.15D, itemstack); - entityfireworks.spawningEntity = itemactioncontext.getEntity().getUniqueID(); // Paper - -- world.addEntity(entityfireworks); -- itemstack.subtract(1); -+ // Paper start - PlayerLaunchProjectileEvent -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) itemactioncontext.getEntity().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Firework) entityfireworks.getBukkitEntity()); -+ if (!event.callEvent() || !world.addEntity(entityfireworks)) return EnumInteractionResult.PASS; -+ if (event.shouldConsume() && !itemactioncontext.getEntity().abilities.canInstantlyBuild) itemstack.subtract(1); -+ else if (itemactioncontext.getEntity() instanceof EntityPlayer) ((EntityPlayer) itemactioncontext.getEntity()).getBukkitEntity().updateInventory(); -+ // Paper end - } - - return EnumInteractionResult.a(world.isClientSide); -diff --git a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemLingeringPotion.java -@@ -0,0 +0,0 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.World; -@@ -0,0 +0,0 @@ public class ItemLingeringPotion extends ItemPotionThrowable { - - @Override - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { -- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -- return super.a(world, entityhuman, enumhand); -+ // Paper start -+ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); -+ if (wrapper.getResult() != EnumInteractionResult.FAIL) { -+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -+ } -+ return wrapper; -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -+++ b/src/main/java/net/minecraft/world/item/ItemPotionThrowable.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.stats.StatisticList; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.entity.projectile.EntityPotion; -@@ -0,0 +0,0 @@ public class ItemPotionThrowable extends ItemPotion { - - entitypotion.setItem(itemstack); - entitypotion.a(entityhuman, entityhuman.pitch, entityhuman.yaw, -20.0F, 0.5F, 1.0F); -- world.addEntity(entitypotion); -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitypotion.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitypotion)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ itemstack.subtract(1); -+ } else if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ -+ entityhuman.b(StatisticList.ITEM_USED.b(this)); -+ } else { -+ if (entityhuman instanceof EntityPlayer) { -+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } -+ return new InteractionResultWrapper(EnumInteractionResult.FAIL, itemstack); -+ } -+ // Paper end - } - -+ /* // Paper start - moved up - entityhuman.b(StatisticList.ITEM_USED.b(this)); - if (!entityhuman.abilities.canInstantlyBuild) { - itemstack.subtract(1); - } -+ */ // Paper end - - return InteractionResultWrapper.a(itemstack, world.s_()); - } -diff --git a/src/main/java/net/minecraft/world/item/ItemSnowball.java b/src/main/java/net/minecraft/world/item/ItemSnowball.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSnowball.java -+++ b/src/main/java/net/minecraft/world/item/ItemSnowball.java -@@ -0,0 +0,0 @@ public class ItemSnowball extends Item { - - entitysnowball.setItem(itemstack); - entitysnowball.a(entityhuman, entityhuman.pitch, entityhuman.yaw, 0.0F, 1.5F, 1.0F); -- if (world.addEntity(entitysnowball)) { -- if (!entityhuman.abilities.canInstantlyBuild) { -+ // Paper start -+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); -+ if (event.callEvent() && world.addEntity(entitysnowball)) { -+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { -+ // Paper end - itemstack.subtract(1); -+ } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { // Paper -+ ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper - } - - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.RANDOM.nextFloat() * 0.4F + 0.8F)); -- } else if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) { -- ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); -+ } else { // Paper -+ if (entityhuman instanceof net.minecraft.server.level.EntityPlayer) ((net.minecraft.server.level.EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper -+ return new InteractionResultWrapper(net.minecraft.world.EnumInteractionResult.FAIL, itemstack); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -+++ b/src/main/java/net/minecraft/world/item/ItemSplashPotion.java -@@ -0,0 +0,0 @@ package net.minecraft.world.item; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.world.EnumHand; -+import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.InteractionResultWrapper; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.level.World; -@@ -0,0 +0,0 @@ public class ItemSplashPotion extends ItemPotionThrowable { - - @Override - public InteractionResultWrapper a(World world, EntityHuman entityhuman, EnumHand enumhand) { -+ // Paper start -+ InteractionResultWrapper wrapper = super.a(world, entityhuman, enumhand); -+ if (wrapper.getResult() != EnumInteractionResult.FAIL) { - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SPLASH_POTION_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemSplashPotion.RANDOM.nextFloat() * 0.4F + 0.8F)); -- return super.a(world, entityhuman, enumhand); -+ } -+ return wrapper; -+ // Paper end - } - } diff --git a/Spigot-Server-Patches/PlayerNaturallySpawnCreaturesEvent.patch b/Spigot-Server-Patches/PlayerNaturallySpawnCreaturesEvent.patch deleted file mode 100644 index ce5144dabf..0000000000 --- a/Spigot-Server-Patches/PlayerNaturallySpawnCreaturesEvent.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:36:02 -0500 -Subject: [PATCH] PlayerNaturallySpawnCreaturesEvent - -This event can be used for when you want to exclude a certain player -from triggering monster spawns on a server. - -Also a highly more effecient way to blanket block spawns in a world - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -+ //Paper start - call player naturally spawn event -+ int chunkRange = world.spigotConfig.mobSpawnRange; -+ chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; -+ chunkRange = Math.min(chunkRange, 8); -+ for (EntityPlayer entityPlayer : this.world.getPlayers()) { -+ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); -+ entityPlayer.playerNaturallySpawnedEvent.callEvent(); -+ }; -+ // Paper end - this.world.timings.chunkTicks.startTiming(); // Paper - this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.level; - -+import com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent; - import com.google.common.collect.Lists; - import com.mojang.authlib.GameProfile; - import com.mojang.datafixers.util.Either; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean sentListPacket = false; - public Integer clientViewDistance; - // CraftBukkit end -+ public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - - public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - chunkRange = (chunkRange > world.spigotConfig.viewDistance) ? (byte) world.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; - -- double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; -+ final int finalChunkRange = chunkRange; // Paper for lambda below -+ //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event - // Spigot end - long i = chunkcoordintpair.pair(); - - return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot -+ // Paper start - -+ com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; -+ double blockRange = 16384.0D; -+ if (reducedRange) { -+ event = entityplayer.playerNaturallySpawnedEvent; -+ if (event == null || event.isCancelled()) return false; -+ blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -+ } -+ -+ return (!entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange); // Spigot -+ // Paper end - }); - } - diff --git a/Spigot-Server-Patches/PlayerPickupExperienceEvent.patch b/Spigot-Server-Patches/PlayerPickupExperienceEvent.patch deleted file mode 100644 index c40dd0dde5..0000000000 --- a/Spigot-Server-Patches/PlayerPickupExperienceEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 19 Dec 2017 22:02:53 -0500 -Subject: [PATCH] PlayerPickupExperienceEvent - -Allows plugins to cancel a player picking up an experience orb - -diff --git a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -+++ b/src/main/java/net/minecraft/world/entity/EntityExperienceOrb.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPosition; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntityExperienceOrb; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.sounds.SoundEffects; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsFluid; -@@ -0,0 +0,0 @@ public class EntityExperienceOrb extends Entity { - @Override - public void pickup(EntityHuman entityhuman) { - if (!this.world.isClientSide) { -- if (this.d == 0 && entityhuman.bu == 0) { -+ if (this.d == 0 && entityhuman.bu == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((EntityPlayer) entityhuman).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - entityhuman.bu = 2; - entityhuman.receive(this, 1); - Entry entry = EnchantmentManager.a(Enchantments.MENDING, (EntityLiving) entityhuman, ItemStack::f); diff --git a/Spigot-Server-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch b/Spigot-Server-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch deleted file mode 100644 index 9a7db230fd..0000000000 --- a/Spigot-Server-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sun, 7 May 2017 06:26:09 -0500 -Subject: [PATCH] PlayerPickupItemEvent#setFlyAtPlayer - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - // CraftBukkit start - fire PlayerPickupItemEvent - int canHold = entityhuman.inventory.canHold(itemstack); - int remaining = i - canHold; -+ boolean flyAtPlayer = false; // Paper - - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); - playerEvent.setCancelled(!entityhuman.canPickUpLoot); - this.world.getServer().getPluginManager().callEvent(playerEvent); -+ flyAtPlayer = playerEvent.getFlyAtPlayer(); // Paper - if (playerEvent.isCancelled()) { - itemstack.setCount(i); // SPIGOT-5294 - restore count -+ // Paper Start -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ // Paper End - return; - } - -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - // CraftBukkit end - - if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(entityhuman.getUniqueID())) && entityhuman.inventory.pickup(itemstack)) { -- entityhuman.receive(this, i); -+ // Paper Start -+ if (flyAtPlayer) { -+ entityhuman.receive(this, i); -+ } -+ // Paper End - if (itemstack.isEmpty()) { - this.die(); - itemstack.setCount(i); diff --git a/Spigot-Server-Patches/PlayerReadyArrowEvent.patch b/Spigot-Server-Patches/PlayerReadyArrowEvent.patch deleted file mode 100644 index bf25e73e68..0000000000 --- a/Spigot-Server-Patches/PlayerReadyArrowEvent.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 18 Jun 2018 01:12:53 -0400 -Subject: [PATCH] PlayerReadyArrowEvent - -Called when a player is firing a bow and the server is choosing an arrow to use. -Plugins can skip selection of certain arrows and control which is used. - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - return ImmutableList.of(EntityPose.STANDING, EntityPose.CROUCHING, EntityPose.SWIMMING); - } - -+ // Paper start -+ protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { -+ return !(this instanceof EntityPlayer) || -+ new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( -+ ((EntityPlayer) this).getBukkitEntity(), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), -+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) -+ ).callEvent(); -+ // Paper end -+ } -+ - @Override - public ItemStack f(ItemStack itemstack) { - if (!(itemstack.getItem() instanceof ItemProjectileWeapon)) { -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - for (int i = 0; i < this.inventory.getSize(); ++i) { - ItemStack itemstack2 = this.inventory.getItem(i); - -- if (predicate.test(itemstack2)) { -+ if (predicate.test(itemstack2) && tryReadyArrow(itemstack, itemstack2)) { // Paper - return itemstack2; - } - } diff --git a/Spigot-Server-Patches/PlayerTeleportEndGatewayEvent.patch b/Spigot-Server-Patches/PlayerTeleportEndGatewayEvent.patch deleted file mode 100644 index e7ac1cca42..0000000000 --- a/Spigot-Server-Patches/PlayerTeleportEndGatewayEvent.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 31 Dec 2016 21:44:50 -0500 -Subject: [PATCH] PlayerTeleportEndGatewayEvent - -Allows you to access the Gateway being used in a teleport event - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityEndGateway.java -@@ -0,0 +0,0 @@ import net.minecraft.data.worldgen.BiomeDecoratorGroups; - import net.minecraft.nbt.GameProfileSerializer; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; -@@ -0,0 +0,0 @@ public class TileEntityEndGateway extends TileEntityEnderPortal implements ITick - location.setPitch(player.getLocation().getPitch()); - location.setYaw(player.getLocation().getYaw()); - -- PlayerTeleportEvent teleEvent = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); -+ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(MCUtil.toLocation(world, this.getPosition()).getBlock())); // Paper - Bukkit.getPluginManager().callEvent(teleEvent); - if (teleEvent.isCancelled()) { - return; diff --git a/Spigot-Server-Patches/PortalCreateEvent-needs-to-know-its-entity.patch b/Spigot-Server-Patches/PortalCreateEvent-needs-to-know-its-entity.patch deleted file mode 100644 index a94046cbb6..0000000000 --- a/Spigot-Server-Patches/PortalCreateEvent-needs-to-know-its-entity.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 21 Aug 2020 20:57:54 +0200 -Subject: [PATCH] PortalCreateEvent needs to know its entity - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - IBlockData block = world.getType(newblockposition); - - if (!(block.getBlock() instanceof BlockTileEntity)) { // Containers get placed automatically -- block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); -+ block.getBlock().onPlace(block, world, newblockposition, oldBlock, true, itemactioncontext); // Paper - pass itemactioncontext - } - - world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getType(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -0,0 +0,0 @@ import net.minecraft.core.EnumDirection; - import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GameRules; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - } - - @Override -- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { -- super.onPlace(iblockdata, world, blockposition, iblockdata1, flag); -+ // Paper start - ItemActionContext param -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); -+ // Paper end - world.getBlockTickList().a(blockposition, this, a(world.random)); - } - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFireAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.player.EntityHuman; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; - import net.minecraft.world.level.World; -@@ -0,0 +0,0 @@ public abstract class BlockFireAbstract extends Block { - super.a(iblockdata, world, blockposition, entity); - } - -+ // Paper start - ItemActionContext param -+ @Override public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { this.onPlace(iblockdata, world, blockposition, iblockdata1, flag, null); } - @Override -- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ // Paper end - if (!iblockdata1.a(iblockdata.getBlock())) { - if (a(world)) { - Optional optional = BlockPortalShape.a((GeneratorAccess) world, blockposition, EnumDirection.EnumAxis.X); - - if (optional.isPresent()) { -- ((BlockPortalShape) optional.get()).createPortal(); -+ ((BlockPortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param - return; - } - } -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -0,0 +0,0 @@ import net.minecraft.world.item.EnumColor; - import net.minecraft.world.item.Item; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.context.BlockActionContext; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.BlockAccessAir; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.IBlockAccess; -@@ -0,0 +0,0 @@ public abstract class BlockBase { - PacketDebug.a(world, blockposition); - } - -+ // Paper start - add ItemActionContext param -+ @Deprecated -+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag, ItemActionContext itemActionContext) { -+ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); -+ } -+ // Paper end - @Deprecated - public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) { - org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot -diff --git a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -+++ b/src/main/java/net/minecraft/world/level/portal/BlockPortalShape.java -@@ -0,0 +0,0 @@ import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.EntitySize; -+import net.minecraft.world.item.context.ItemActionContext; - import net.minecraft.world.level.GeneratorAccess; - import net.minecraft.world.level.block.BlockPortal; - import net.minecraft.world.level.block.Blocks; -@@ -0,0 +0,0 @@ public class BlockPortalShape { - } - - // CraftBukkit start - return boolean -- public boolean createPortal() { -+ // Paper start - ItemActionContext param -+ @Deprecated public boolean createPortal() { return this.createPortal(null); } -+ public boolean createPortal(ItemActionContext itemActionContext) { -+ // Paper end - org.bukkit.World bworld = this.b.getMinecraftWorld().getWorld(); - - // Copy below for loop -@@ -0,0 +0,0 @@ public class BlockPortalShape { - BlockPosition.a(this.position, this.position.shift(EnumDirection.UP, this.height - 1).shift(this.d, this.width - 1)).forEach((blockposition) -> { - blocks.setTypeAndData(blockposition, iblockdata, 18); - }); -- -- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); -+ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getEntity() == null ? null : itemActionContext.getEntity().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param - this.b.getMinecraftWorld().getMinecraftServer().server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/Potential-bed-API.patch b/Spigot-Server-Patches/Potential-bed-API.patch deleted file mode 100644 index efbe6e2113..0000000000 --- a/Spigot-Server-Patches/Potential-bed-API.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Josh Roy <10731363+JRoy@users.noreply.github.com> -Date: Sun, 10 May 2020 23:06:30 -0400 -Subject: [PATCH] Potential bed API - -Adds a new method to fetch the location of a player's bed without generating any sync loads. - -getPotentialBedLocation - Gets the last known location of a player's bed. This does not preform any check if the bed is still valid and does not load any chunks. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.game.PacketPlayInCloseWindow; - import net.minecraft.network.protocol.game.PacketPlayOutOpenWindow; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.world.ITileInventory; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return getHandle().sleepTicks; - } - -+ // Paper start - Potential bed api -+ @Override -+ public Location getPotentialBedLocation() { -+ EntityPlayer handle = (EntityPlayer) getHandle(); -+ BlockPosition bed = handle.getSpawn(); -+ if (bed == null) { -+ return null; -+ } -+ -+ WorldServer worldServer = handle.server.getWorldServer(handle.getSpawnDimension()); -+ if (worldServer == null) { -+ return null; -+ } -+ return new Location(worldServer.getWorld(), bed.getX(), bed.getY(), bed.getZ()); -+ } -+ // Paper end - @Override - public boolean sleep(Location location, boolean force) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Spigot-Server-Patches/PreCreatureSpawnEvent.patch b/Spigot-Server-Patches/PreCreatureSpawnEvent.patch deleted file mode 100644 index 232861a26b..0000000000 --- a/Spigot-Server-Patches/PreCreatureSpawnEvent.patch +++ /dev/null @@ -1,200 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 14 Jan 2018 17:01:31 -0500 -Subject: [PATCH] PreCreatureSpawnEvent - -Adds an event to fire before an Entity is created, so that plugins that need to cancel -CreatureSpawnEvent can do so from this event instead. - -Cancelling CreatureSpawnEvent rapidly causes a lot of garbage collection and CPU waste -as it's done after the Entity object has been fully created. - -Mob Limiting plugins and blanket "ban this type of monster" plugins should use this event -instead and save a lot of server resources. - -See: https://github.com/PaperMC/Paper/issues/917 - -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; -@@ -0,0 +0,0 @@ public class EntityTypes { - - @Nullable - public T spawnCreature(WorldServer worldserver, @Nullable NBTTagCompound nbttagcompound, @Nullable IChatBaseComponent ichatbasecomponent, @Nullable EntityHuman entityhuman, BlockPosition blockposition, EnumMobSpawn enummobspawn, boolean flag, boolean flag1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) { -+ // Paper start - Call PreCreatureSpawnEvent -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(this).getKey()); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition), -+ type, -+ spawnReason -+ ); -+ if (!event.callEvent()) { -+ return null; -+ } -+ } -+ // Paper end - T t0 = this.createCreature(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); - - if (t0 != null) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorGolemLastSeen.java -@@ -0,0 +0,0 @@ public class SensorGolemLastSeen extends Sensor { - Optional> optional = entityliving.getBehaviorController().getMemory(MemoryModuleType.MOBS); - - if (optional.isPresent()) { -- boolean flag = ((List) optional.get()).stream().anyMatch((entityliving1) -> { -+ boolean flag = optional.get().stream().anyMatch((entityliving1) -> { // Paper - decompile fixes - return entityliving1.getEntityType().equals(EntityTypes.IRON_GOLEM); - }); - -@@ -0,0 +0,0 @@ public class SensorGolemLastSeen extends Sensor { - } - } - -+ public static void setDetectedRecently(EntityLiving entityLiving) { b(entityLiving); } // Paper - OBFHELPER - public static void b(EntityLiving entityliving) { - entityliving.getBehaviorController().a(MemoryModuleType.GOLEM_DETECTED_RECENTLY, true, 600L); - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketDebug; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundEffect; -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - BlockPosition blockposition1 = this.a(blockposition, d0, d1); - - if (blockposition1 != null) { -+ // Paper start - Call PreCreatureSpawnEvent -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, blockposition1), -+ org.bukkit.entity.EntityType.IRON_GOLEM, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ SensorGolemLastSeen.b(this); // Set Golem Last Seen to stop it from spawning another one -+ return null; -+ } -+ break; -+ } -+ // Paper end - EntityIronGolem entityirongolem = (EntityIronGolem) EntityTypes.IRON_GOLEM.createCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition1, EnumMobSpawn.MOB_SUMMONED, false, false); - - if (entityirongolem != null) { -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.core.particles.Particles; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; - import net.minecraft.resources.MinecraftKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.UtilColor; - import net.minecraft.util.WeightedRandom; -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - WorldServer worldserver = (WorldServer) world; - - if (EntityPositionTypes.a((EntityTypes) optional.get(), worldserver, EnumMobSpawn.SPAWNER, new BlockPosition(d3, d4, d5), world.getRandom())) { -+ // Paper start -+ EntityTypes entityType = optional.get(); -+ String key = EntityTypes.getName(entityType).getKey(); -+ -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); -+ if (type != null) { -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(world, d3, d4, d5), -+ type, -+ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ ); -+ if (!event.callEvent()) { -+ flag = true; -+ if (event.shouldAbortSpawn()) { -+ break; -+ } -+ continue; -+ } -+ } -+ // Paper end - Entity entity = EntityTypes.a(nbttagcompound, world, (entity1) -> { - entity1.setPositionRotation(d3, d4, d5, entity1.yaw, entity1.pitch); - return entity1; -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -0,0 +0,0 @@ import net.minecraft.core.EnumDirection; - import net.minecraft.core.IPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - j1 = biomesettingsmobs_c.d + worldserver.random.nextInt(1 + biomesettingsmobs_c.e - biomesettingsmobs_c.d); - } - -- if (a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { -+ // Paper start -+ Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); -+ if (doSpawning == null) { -+ return; -+ } -+ if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { -+ // Paper end - EntityInsentient entityinsentient = a(worldserver, biomesettingsmobs_c.c); - -+ - if (entityinsentient == null) { - return; - } -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - } - } - -- private static boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { -+ private static Boolean a(WorldServer worldserver, EnumCreatureType enumcreaturetype, StructureManager structuremanager, ChunkGenerator chunkgenerator, BiomeSettingsMobs.c biomesettingsmobs_c, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { // Paper - EntityTypes entitytypes = biomesettingsmobs_c.c; -+ // Paper start -+ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -+ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityTypes.getName(entitytypes).getKey()); -+ if (type != null) { -+ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ MCUtil.toLocation(worldserver, blockposition_mutableblockposition), -+ type, SpawnReason.NATURAL -+ ); -+ if (!event.callEvent()) { -+ if (event.shouldAbortSpawn()) { -+ return null; -+ } -+ return false; -+ } -+ } -+ // Paper end - - if (entitytypes.e() == EnumCreatureType.MISC) { - return false; diff --git a/Spigot-Server-Patches/PreSpawnerSpawnEvent.patch b/Spigot-Server-Patches/PreSpawnerSpawnEvent.patch deleted file mode 100644 index 94237a3916..0000000000 --- a/Spigot-Server-Patches/PreSpawnerSpawnEvent.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Tue, 18 Sep 2018 23:53:23 +0100 -Subject: [PATCH] PreSpawnerSpawnEvent - -This adds a separate event before an entity is spawned by a spawner -which contains the location of the spawner too similarly to how the -SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for -spawners. - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - - org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(key); - if (type != null) { -- com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; -- event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( -+ com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent event; -+ event = new com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent( - MCUtil.toLocation(world, d3, d4, d5), - type, -- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER -+ MCUtil.toLocation(world, blockposition) - ); - if (!event.callEvent()) { - flag = true; diff --git a/Spigot-Server-Patches/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/Spigot-Server-Patches/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch deleted file mode 100644 index 02b5ece6c2..0000000000 --- a/Spigot-Server-Patches/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 2 Apr 2020 01:42:39 -0400 -Subject: [PATCH] Prevent Double PlayerChunkMap adds crashing server - -Suspected case would be around the technique used in .stopRiding -Stack will identify any causer of this and warn instead of crashing. - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - protected void addEntity(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot -+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server -+ if (!entity.valid || entity.world != this.world || this.trackedEntities.containsKey(entity.getId())) { -+ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.world.getWorld().getName() -+ + ": " + entity + (this.trackedEntities.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) -+ .printStackTrace(); -+ return; -+ } -+ // Paper end - if (!(entity instanceof EntityComplexPart)) { - EntityTypes entitytypes = entity.getEntityType(); - int i = entitytypes.getChunkRange() * 16; -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -- this.getChunkProvider().addEntity(entity); -+ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true - // CraftBukkit start - SPIGOT-5278 - if (entity instanceof EntityDrowned) { - this.navigators.add(((EntityDrowned) entity).navigationWater); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.navigators.add(((EntityInsentient) entity).getNavigation()); - } - entity.valid = true; // CraftBukkit -+ this.getChunkProvider().addEntity(entity); // Paper - from above to be below valid=true - // Paper start - Set origin location when the entity is being added to the world - if (entity.origin == null) { - entity.origin = entity.getBukkitEntity().getLocation(); diff --git a/Spigot-Server-Patches/Prevent-Enderman-from-loading-chunks.patch b/Spigot-Server-Patches/Prevent-Enderman-from-loading-chunks.patch deleted file mode 100644 index bab84959c8..0000000000 --- a/Spigot-Server-Patches/Prevent-Enderman-from-loading-chunks.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 18 Dec 2018 02:15:08 +0000 -Subject: [PATCH] Prevent Enderman from loading chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityEnderman.java -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - int j = MathHelper.floor(this.enderman.locY() + random.nextDouble() * 3.0D); - int k = MathHelper.floor(this.enderman.locZ() - 2.0D + random.nextDouble() * 4.0D); - BlockPosition blockposition = new BlockPosition(i, j, k); -- IBlockData iblockdata = world.getType(blockposition); -+ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - Block block = iblockdata.getBlock(); - Vec3D vec3d = new Vec3D((double) MathHelper.floor(this.enderman.locX()) + 0.5D, (double) j + 0.5D, (double) MathHelper.floor(this.enderman.locZ()) + 0.5D); - Vec3D vec3d1 = new Vec3D((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); -@@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster implements IEntityAngerable { - int j = MathHelper.floor(this.a.locY() + random.nextDouble() * 2.0D); - int k = MathHelper.floor(this.a.locZ() - 1.0D + random.nextDouble() * 2.0D); - BlockPosition blockposition = new BlockPosition(i, j, k); -- IBlockData iblockdata = world.getType(blockposition); -+ IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return; // Paper - BlockPosition blockposition1 = blockposition.down(); - IBlockData iblockdata1 = world.getType(blockposition1); - IBlockData iblockdata2 = this.a.getCarried(); diff --git a/Spigot-Server-Patches/Prevent-Fire-from-loading-chunks-wrongly-spread.patch b/Spigot-Server-Patches/Prevent-Fire-from-loading-chunks-wrongly-spread.patch deleted file mode 100644 index 1eb84b0a16..0000000000 --- a/Spigot-Server-Patches/Prevent-Fire-from-loading-chunks-wrongly-spread.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 17 Apr 2016 17:27:09 -0400 -Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread - -This causes the nether to spam unload/reload chunks, plus overall -bad behavior. - -This also stops fire from spreading to illegal locations. - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockFire.java b/src/main/java/net/minecraft/world/level/block/BlockFire.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockFire.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockFire.java -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - BlockStateBoolean blockstateboolean = (BlockStateBoolean) BlockFire.h.get(enumdirection); - - if (blockstateboolean != null) { -- iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getType(blockposition.shift(enumdirection)))); -+ iblockdata1 = (IBlockData) iblockdata1.set(blockstateboolean, this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))); // Paper - prevent chunk loads - } - } - -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - } - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, l, j1, i1); -+ if (blockposition_mutableblockposition.isInvalidYLocation() || !worldserver.isLoaded(blockposition_mutableblockposition)) continue; // Paper - int l1 = this.a((IWorldReader) worldserver, (BlockPosition) blockposition_mutableblockposition); - - if (l1 > 0) { -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - } - - private void trySpread(World world, BlockPosition blockposition, int i, Random random, int j, BlockPosition sourceposition) { // CraftBukkit add sourceposition -- int k = this.getBurnChance(world.getType(blockposition)); -+ // Paper start -+ final IBlockData iblockdata = world.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ return; -+ } -+ int k = this.getBurnChance(iblockdata); -+ // Paper end - - if (random.nextInt(i) < k) { -- IBlockData iblockdata = world.getType(blockposition); -+ //IBlockData iblockdata = world.getType(blockposition); // Paper - - // CraftBukkit start - org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - for (int j = 0; j < i; ++j) { - EnumDirection enumdirection = aenumdirection[j]; - -- if (this.e(iblockaccess.getType(blockposition.shift(enumdirection)))) { -+ if (this.e(iblockaccess.getTypeIfLoaded(blockposition.shift(enumdirection)))) { // Paper - prevent chunk loads - return true; - } - } -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - - for (int k = 0; k < j; ++k) { - EnumDirection enumdirection = aenumdirection[k]; -- IBlockData iblockdata = iworldreader.getType(blockposition.shift(enumdirection)); -+ // Paper start -+ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition.shift(enumdirection)); -+ if (iblockdata == null) { -+ continue; -+ } -+ // Paper end - - i = Math.max(this.getFlameChance(iblockdata), i); - } -@@ -0,0 +0,0 @@ public class BlockFire extends BlockFireAbstract { - - @Override - protected boolean e(IBlockData iblockdata) { -- return this.getFlameChance(iblockdata) > 0; -+ return iblockdata != null && this.getFlameChance(iblockdata) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now - } - - @Override diff --git a/Spigot-Server-Patches/Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/Spigot-Server-Patches/Prevent-Frosted-Ice-from-loading-holding-chunks.patch deleted file mode 100644 index 5d0f3bba85..0000000000 --- a/Spigot-Server-Patches/Prevent-Frosted-Ice-from-loading-holding-chunks.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 10 Mar 2018 16:33:15 -0500 -Subject: [PATCH] Prevent Frosted Ice from loading/holding chunks - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockIceFrost.java -@@ -0,0 +0,0 @@ public class BlockIceFrost extends BlockIce { - EnumDirection enumdirection = aenumdirection[j]; - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); -- IBlockData iblockdata1 = worldserver.getType(blockposition_mutableblockposition); -+ IBlockData iblockdata1 = worldserver.getTypeIfLoaded(blockposition_mutableblockposition); // Paper -+ if (iblockdata1 == null) { continue; } // Paper - - if (iblockdata1.a((Block) this) && !this.e(iblockdata1, (World) worldserver, blockposition_mutableblockposition)) { - worldserver.getBlockTickList().a(blockposition_mutableblockposition, this, MathHelper.nextInt(random, worldserver.paperConfig.frostedIceDelayMin, worldserver.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay -@@ -0,0 +0,0 @@ public class BlockIceFrost extends BlockIce { - EnumDirection enumdirection = aenumdirection[l]; - - blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, enumdirection); -- if (iblockaccess.getType(blockposition_mutableblockposition).a((Block) this)) { -+ // Paper start -+ IBlockData type = iblockaccess.getTypeIfLoaded(blockposition_mutableblockposition); -+ if (type != null && type.a((Block) this)) { // Paper end - ++j; - if (j >= i) { - return false; diff --git a/Spigot-Server-Patches/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/Spigot-Server-Patches/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch deleted file mode 100644 index cef8ca71cb..0000000000 --- a/Spigot-Server-Patches/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:56:36 -0400 -Subject: [PATCH] Prevent Mob AI Rules from Loading Chunks - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalRemoveBlock.java -@@ -0,0 +0,0 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - private final Block g; - private final EntityInsentient entity; - private int i; -+ private World world; // Paper - - public PathfinderGoalRemoveBlock(Block block, EntityCreature entitycreature, double d0, int i) { - super(entitycreature, d0, 24, i); - this.g = block; - this.entity = entitycreature; -+ this.world = entitycreature.world; // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - - @Nullable - private BlockPosition a(BlockPosition blockposition, IBlockAccess iblockaccess) { -- if (iblockaccess.getType(blockposition).a(this.g)) { -+ Block block = world.getBlockIfLoaded(blockposition); // Paper -+ if (block == null) return null; // Paper -+ if (block.a(this.g)) { // Paper - return blockposition; - } else { - BlockPosition[] ablockposition = new BlockPosition[]{blockposition.down(), blockposition.west(), blockposition.east(), blockposition.north(), blockposition.south(), blockposition.down().down()}; -@@ -0,0 +0,0 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - for (int j = 0; j < i; ++j) { - BlockPosition blockposition1 = ablockposition1[j]; - -- if (iblockaccess.getType(blockposition1).a(this.g)) { -+ if (iblockaccess.getBlockIfLoaded(blockposition1).a(this.g)) { // Paper - return blockposition1; - } - } -@@ -0,0 +0,0 @@ public class PathfinderGoalRemoveBlock extends PathfinderGoalGotoTarget { - - @Override - protected boolean a(IWorldReader iworldreader, BlockPosition blockposition) { -- IChunkAccess ichunkaccess = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); -+ IChunkAccess ichunkaccess = iworldreader.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a(this.g) && ichunkaccess.getType(blockposition.up()).isAir() && ichunkaccess.getType(blockposition.up(2)).isAir(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -+++ b/src/main/java/net/minecraft/world/entity/ai/util/RandomPositionGenerator.java -@@ -0,0 +0,0 @@ import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.EntityCreature; - import net.minecraft.world.entity.ai.navigation.NavigationAbstract; - import net.minecraft.world.level.IBlockAccess; -+import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.pathfinder.PathType; - import net.minecraft.world.level.pathfinder.PathfinderNormal; - import net.minecraft.world.phys.Vec3D; -@@ -0,0 +0,0 @@ public class RandomPositionGenerator { - } - - blockposition2 = new BlockPosition((double) k1 + entitycreature.locX(), (double) l1 + entitycreature.locY(), (double) i2 + entitycreature.locZ()); -+ if (!entitycreature.world.isLoaded(blockposition2)) continue; // Paper - if (blockposition2.getY() >= 0 && blockposition2.getY() <= entitycreature.world.getBuildHeight() && (!flag3 || entitycreature.a(blockposition2)) && (!flag2 || navigationabstract.a(blockposition2))) { - if (flag1) { - blockposition2 = a(blockposition2, random.nextInt(l + 1) + i1, entitycreature.world.getBuildHeight(), (blockposition3) -> { -@@ -0,0 +0,0 @@ public class RandomPositionGenerator { - }); - } - -- if (flag || !entitycreature.world.getFluid(blockposition2).a((Tag) TagsFluid.WATER)) { -+ Fluid fluid = entitycreature.world.getFluidIfLoaded(blockposition2); // Paper -+ if (flag || (fluid != null && !fluid.a((Tag) TagsFluid.WATER))) { // Paper - PathType pathtype = PathfinderNormal.a((IBlockAccess) entitycreature.world, blockposition2.i()); - - if (entitycreature.a(pathtype) == 0.0F) { diff --git a/Spigot-Server-Patches/Prevent-Pathfinding-out-of-World-Border.patch b/Spigot-Server-Patches/Prevent-Pathfinding-out-of-World-Border.patch deleted file mode 100644 index 7bdbb9ac65..0000000000 --- a/Spigot-Server-Patches/Prevent-Pathfinding-out-of-World-Border.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 19 Dec 2016 23:07:42 -0500 -Subject: [PATCH] Prevent Pathfinding out of World Border - -This prevents Entities from trying to run outside of the World Border - -diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/ai/navigation/NavigationAbstract.java -@@ -0,0 +0,0 @@ public abstract class NavigationAbstract { - // Paper start - Pathfind event - boolean copiedSet = false; - for (BlockPosition possibleTarget : set) { -- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), -+ if (!getEntity().getWorld().getWorldBorder().isInBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(getEntity().getBukkitEntity(), // Paper - don't path out of world border - MCUtil.toLocation(getEntity().world, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { - if (!copiedSet) { - copiedSet = true; diff --git a/Spigot-Server-Patches/Prevent-Saving-Bad-entities-to-chunks.patch b/Spigot-Server-Patches/Prevent-Saving-Bad-entities-to-chunks.patch deleted file mode 100644 index c710a65722..0000000000 --- a/Spigot-Server-Patches/Prevent-Saving-Bad-entities-to-chunks.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 26 Jul 2018 00:11:12 -0400 -Subject: [PATCH] Prevent Saving Bad entities to chunks - -See https://github.com/PaperMC/Paper/issues/1223 - -Minecraft is saving invalid entities to the chunk files. - -Avoid saving bad data, and also make improvements to handle -loading these chunks. Any invalid entity will be instant killed, -so lets avoid adding it to the world... - -This lets us be safer about the dupe UUID resolver too, as now -we can ignore instant killed entities and avoid risk of duplicating -an invalid entity. - -This should reduce log occurrences of dupe uuid messages. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - List[] aentityslice = chunk.getEntitySlices(); // Spigot - int i = aentityslice.length; - -+ java.util.List toMoveChunks = new java.util.ArrayList<>(); // Paper - for (int j = 0; j < i; ++j) { - List entityslice = aentityslice[j]; // Spigot - Iterator iterator = entityslice.iterator(); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!"))); - } - -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ if (!entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ toMoveChunks.add(entity); -+ continue; -+ } -+ // Paper end -+ - this.entitiesById.remove(entity.getId()); - this.unregisterEntity(entity); -+ -+ if (entity.dead) iterator.remove(); // Paper - don't save dead entities during unload - } - } - } -+ // Paper start - move out entities that shouldn't be in this chunk before it unloads -+ for (Entity entity : toMoveChunks) { -+ this.chunkCheck(entity); -+ } -+ // Paper end - - } - -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagList; - import net.minecraft.nbt.NBTTagLongArray; - import net.minecraft.nbt.NBTTagShort; - import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.LightEngineThreaded; - import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.Entity; -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - nbttagcompound1.set("TileEntities", nbttaglist1); - NBTTagList nbttaglist2 = new NBTTagList(); - -+ java.util.List toUpdate = new java.util.ArrayList<>(); // Paper - if (ichunkaccess.getChunkStatus().getType() == ChunkStatus.Type.LEVELCHUNK) { - Chunk chunk = (Chunk) ichunkaccess; - -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - while (iterator1.hasNext()) { - Entity entity = (Entity) iterator1.next(); - NBTTagCompound nbttagcompound4 = new NBTTagCompound(); -- -+ // Paper start -+ if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { -+ toUpdate.add(entity); -+ continue; -+ } -+ if (entity.dead || hasPlayerPassenger(entity)) { -+ continue; -+ } -+ // Paper end - if (entity.d(nbttagcompound4)) { - chunk.d(true); - nbttaglist2.add(nbttagcompound4); - } - } - } -+ -+ // Paper start - move entities to the correct chunk -+ for (Entity entity : toUpdate) { -+ worldserver.chunkCheck(entity); -+ } -+ // Paper end -+ - } else { - ProtoChunk protochunk = (ProtoChunk) ichunkaccess; - -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - nbttagcompound1.set("Structures", a(chunkcoordintpair, ichunkaccess.h(), ichunkaccess.v())); - return nbttagcompound; - } -+ // Paper start - this is saved with the player -+ private static boolean hasPlayerPassenger(Entity entity) { -+ for (Entity passenger : entity.passengers) { -+ if (passenger instanceof EntityPlayer) { -+ return true; -+ } -+ if (hasPlayerPassenger(passenger)) { -+ return true; -+ } -+ } -+ return false; -+ } -+ // Paper end - - public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { - if (nbttagcompound != null) { diff --git a/Spigot-Server-Patches/Prevent-bees-loading-chunks-checking-hive-position.patch b/Spigot-Server-Patches/Prevent-bees-loading-chunks-checking-hive-position.patch deleted file mode 100644 index 8a44e1a9a2..0000000000 --- a/Spigot-Server-Patches/Prevent-bees-loading-chunks-checking-hive-position.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Sun, 5 Jan 2020 17:24:34 -0600 -Subject: [PATCH] Prevent bees loading chunks checking hive position - - -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityBee.java -@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB - if (!this.hasHivePos()) { - return false; - } else { -+ if (world.getChunkIfLoadedImmediately(hivePos.getX() >> 4, hivePos.getZ() >> 4) == null) return true; // Paper - just assume the hive is still there, no need to load the chunk(s) - TileEntity tileentity = this.world.getTileEntity(this.hivePos); - - return tileentity != null && tileentity.getTileType() == TileEntityTypes.BEEHIVE; diff --git a/Spigot-Server-Patches/Prevent-chunk-loading-from-Fluid-Flowing.patch b/Spigot-Server-Patches/Prevent-chunk-loading-from-Fluid-Flowing.patch deleted file mode 100644 index cb1c5d32eb..0000000000 --- a/Spigot-Server-Patches/Prevent-chunk-loading-from-Fluid-Flowing.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 10 Sep 2018 23:36:16 -0400 -Subject: [PATCH] Prevent chunk loading from Fluid Flowing - - -diff --git a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -+++ b/src/main/java/net/minecraft/world/level/material/FluidTypeFlowing.java -@@ -0,0 +0,0 @@ public abstract class FluidTypeFlowing extends FluidType { - EnumDirection enumdirection = (EnumDirection) entry.getKey(); - Fluid fluid1 = (Fluid) entry.getValue(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); -- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); -+ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - - if (this.a(generatoraccess, blockposition, iblockdata, enumdirection, blockposition1, iblockdata1, generatoraccess.getFluid(blockposition1), fluid1.getType())) { - // CraftBukkit start -@@ -0,0 +0,0 @@ public abstract class FluidTypeFlowing extends FluidType { - while (iterator.hasNext()) { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); -- IBlockData iblockdata1 = iworldreader.getType(blockposition1); -+ IBlockData iblockdata1 = iworldreader.getTypeIfLoaded(blockposition1); // Paper -+ if (iblockdata1 == null) continue; // Paper - Fluid fluid = iblockdata1.getFluid(); - - if (fluid.getType().a((FluidType) this) && this.a(enumdirection, (IBlockAccess) iworldreader, blockposition, iblockdata, blockposition1, iblockdata1)) { -@@ -0,0 +0,0 @@ public abstract class FluidTypeFlowing extends FluidType { - if (enumdirection1 != enumdirection) { - BlockPosition blockposition2 = blockposition.shift(enumdirection1); - short short0 = a(blockposition1, blockposition2); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { -- IBlockData iblockdata1 = iworldreader.getType(blockposition2); -+ // Paper start - avoid loading chunks -+ Pair pair = short2objectmap.get(short0); -+ if (pair == null) { -+ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition2); -+ if (iblockdatax == null) { -+ continue; -+ } - -- return Pair.of(iblockdata1, iblockdata1.getFluid()); -- }); -+ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - IBlockData iblockdata1 = (IBlockData) pair.getFirst(); - Fluid fluid = (Fluid) pair.getSecond(); - -@@ -0,0 +0,0 @@ public abstract class FluidTypeFlowing extends FluidType { - EnumDirection enumdirection = (EnumDirection) iterator.next(); - BlockPosition blockposition1 = blockposition.shift(enumdirection); - short short0 = a(blockposition, blockposition1); -- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { -- IBlockData iblockdata1 = iworldreader.getType(blockposition1); -- -- return Pair.of(iblockdata1, iblockdata1.getFluid()); -- }); -+ // Paper start -+ Pair pair = (Pair) short2objectmap.get(short0); -+ if (pair == null) { -+ IBlockData iblockdatax = iworldreader.getTypeIfLoaded(blockposition1); -+ if (iblockdatax == null) continue; -+ -+ pair = Pair.of(iblockdatax, iblockdatax.getFluid()); -+ short2objectmap.put(short0, pair); -+ } -+ // Paper end - IBlockData iblockdata1 = (IBlockData) pair.getFirst(); - Fluid fluid = (Fluid) pair.getSecond(); - Fluid fluid1 = this.a(iworldreader, blockposition1, iblockdata1); diff --git a/Spigot-Server-Patches/Prevent-consuming-the-wrong-itemstack.patch b/Spigot-Server-Patches/Prevent-consuming-the-wrong-itemstack.patch deleted file mode 100644 index 30b5b05e1b..0000000000 --- a/Spigot-Server-Patches/Prevent-consuming-the-wrong-itemstack.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 19:42:35 +0500 -Subject: [PATCH] Prevent consuming the wrong itemstack - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.datawatcher.set(EntityLiving.ag, (byte) j); - } - -- public void c(EnumHand enumhand) { -+ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter -+ public void c(EnumHand enumhand) { this.updateActiveItem(enumhand, false); } -+ public void updateActiveItem(EnumHand enumhand, boolean forceUpdate) { -+ // Paper end - ItemStack itemstack = this.b(enumhand); - -- if (!itemstack.isEmpty() && !this.isHandRaised()) { -+ if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag - this.activeItem = itemstack; - this.bd = itemstack.k(); - if (!this.world.isClientSide) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.releaseActiveItem(); - } else { - if (!this.activeItem.isEmpty() && this.isHandRaised()) { -+ this.updateActiveItem(this.getRaisedHand(), true); // Paper - this.b(this.activeItem, 16); - // CraftBukkit start - fire PlayerItemConsumeEvent - ItemStack itemstack; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - this.clearActiveItem(); -- // Paper start - if the replacement is anything but the default, update the client inventory -- if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { -+ // Paper start -+ if (this instanceof EntityPlayer) { - ((EntityPlayer) this).getBukkitEntity().updateInventory(); - } - // Paper end diff --git a/Spigot-Server-Patches/Prevent-grindstones-from-overstacking-items.patch b/Spigot-Server-Patches/Prevent-grindstones-from-overstacking-items.patch deleted file mode 100644 index c3b1391c76..0000000000 --- a/Spigot-Server-Patches/Prevent-grindstones-from-overstacking-items.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Tue, 16 Feb 2021 21:37:51 -0600 -Subject: [PATCH] Prevent grindstones from overstacking items - - -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -+++ b/src/main/java/net/minecraft/world/inventory/ContainerGrindstone.java -@@ -0,0 +0,0 @@ public class ContainerGrindstone extends Container { - i = Math.max(item.getMaxDurability() - l, 0); - itemstack2 = this.b(itemstack, itemstack1); - if (!itemstack2.e()) { -- if (!ItemStack.matches(itemstack, itemstack1)) { -+ if (!ItemStack.matches(itemstack, itemstack1) || itemstack2.getMaxStackSize() == 1) { // Paper - add max stack size check - this.resultInventory.setItem(0, ItemStack.b); - this.c(); - return; - } - -- b0 = 2; -+ b0 = 2; // Paper - the problem line for above change, causing over-stacking - } - } else { - boolean flag3 = !itemstack.isEmpty(); diff --git a/Spigot-Server-Patches/Prevent-headless-pistons-from-being-created.patch b/Spigot-Server-Patches/Prevent-headless-pistons-from-being-created.patch deleted file mode 100644 index 0e6f3a9e31..0000000000 --- a/Spigot-Server-Patches/Prevent-headless-pistons-from-being-created.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: commandblockguy -Date: Fri, 14 Aug 2020 14:44:14 -0500 -Subject: [PATCH] Prevent headless pistons from being created - -Prevent headless pistons from being created by explosions or tree/mushroom growth. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - set("settings.unsupported-settings.allow-tnt-duplication", null); - } - -+ public static boolean allowHeadlessPistons; -+ private static void allowHeadlessPistons() { -+ config.set("settings.unsupported-settings.allow-headless-pistons-readme", "This setting controls if players should be able to create headless pistons."); -+ allowHeadlessPistons = getBoolean("settings.unsupported-settings.allow-headless-pistons", false); -+ } -+ - public static int playerAutoSaveRate = -1; - public static int maxPlayerAutoSavePerTick = 10; - private static void playerAutoSaveRate() { -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -0,0 +0,0 @@ import java.util.Set; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; - import net.minecraft.core.BlockPosition; -+import net.minecraft.core.EnumDirection; - import net.minecraft.core.particles.Particles; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.Block; - import net.minecraft.world.level.block.BlockFireAbstract; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.piston.BlockPistonExtension; -+import net.minecraft.world.level.block.piston.TileEntityPiston; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.material.Fluid; - import net.minecraft.world.level.storage.loot.LootTableInfo; -@@ -0,0 +0,0 @@ public class Explosion { - - if (f > 0.0F && this.l.a(this, this.world, blockposition, iblockdata, f) && blockposition.getY() < 256 && blockposition.getY() >= 0) { // CraftBukkit - don't wrap explosions - set.add(blockposition); -+ // Paper start - prevent headless pistons from forming -+ if (!com.destroystokyo.paper.PaperConfig.allowHeadlessPistons && iblockdata.getBlock() == Blocks.MOVING_PISTON) { -+ TileEntity extension = this.world.getTileEntity(blockposition); -+ if (extension instanceof TileEntityPiston && ((TileEntityPiston) extension).isHead()) { -+ EnumDirection direction = iblockdata.get(BlockPistonExtension.FACING); -+ set.add(blockposition.shift(direction.opposite())); -+ } -+ } -+ // Paper end - } - - d4 += d0 * 0.30000001192092896D; -diff --git a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/TileEntityPiston.java -@@ -0,0 +0,0 @@ public class TileEntityPiston extends TileEntity implements ITickable { - return this.b; - } - -+ public final boolean isHead() { return this.h(); } // Paper - OBFHELPER -+ - public boolean h() { - return this.g; - } diff --git a/Spigot-Server-Patches/Prevent-logins-from-being-processed-when-the-player-.patch b/Spigot-Server-Patches/Prevent-logins-from-being-processed-when-the-player-.patch deleted file mode 100644 index fb1add08b3..0000000000 --- a/Spigot-Server-Patches/Prevent-logins-from-being-processed-when-the-player-.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: killme -Date: Sun, 12 Nov 2017 19:40:01 +0100 -Subject: [PATCH] Prevent logins from being processed when the player has - disconnected - - -diff --git a/src/main/java/net/minecraft/server/network/LoginListener.java b/src/main/java/net/minecraft/server/network/LoginListener.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/LoginListener.java -+++ b/src/main/java/net/minecraft/server/network/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { - } - // Paper end - if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { -- this.c(); -+ // Paper start - prevent logins to be processed even though disconnect was called -+ if (networkManager.isConnected()) { -+ this.c(); -+ } -+ // Paper end - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { - EntityPlayer entityplayer = this.server.getPlayerList().getPlayer(this.i.getId()); - diff --git a/Spigot-Server-Patches/Prevent-mob-spawning-from-loading-generating-chunks.patch b/Spigot-Server-Patches/Prevent-mob-spawning-from-loading-generating-chunks.patch deleted file mode 100644 index 44fda99a69..0000000000 --- a/Spigot-Server-Patches/Prevent-mob-spawning-from-loading-generating-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 12 Sep 2018 21:12:57 -0400 -Subject: [PATCH] Prevent mob spawning from loading/generating chunks - -also prevents if out of world border bounds - -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - StructureManager structuremanager = worldserver.getStructureManager(); - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - int i = blockposition.getY(); -- IBlockData iblockdata = ichunkaccess.getType(blockposition); -+ IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn - -- if (!iblockdata.isOccluding(ichunkaccess, blockposition)) { -+ if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); - int j = 0; - int k = 0; -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - if (entityhuman != null) { - double d2 = entityhuman.h(d0, (double) i, d1); - -- if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2)) { -+ if (a(worldserver, ichunkaccess, blockposition_mutableblockposition, d2) && worldserver.isLoadedAndInBounds(blockposition_mutableblockposition)) { // Paper - don't load chunks for mob spawn - if (biomesettingsmobs_c == null) { - biomesettingsmobs_c = a(worldserver, structuremanager, chunkgenerator, enumcreaturetype, worldserver.random, (BlockPosition) blockposition_mutableblockposition); - if (biomesettingsmobs_c == null) { diff --git a/Spigot-Server-Patches/Prevent-opening-inventories-when-frozen.patch b/Spigot-Server-Patches/Prevent-opening-inventories-when-frozen.patch deleted file mode 100644 index cfa0abdec3..0000000000 --- a/Spigot-Server-Patches/Prevent-opening-inventories-when-frozen.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 13 Apr 2020 07:31:44 +0100 -Subject: [PATCH] Prevent opening inventories when frozen - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - containerUpdateDelay = world.paperConfig.containerUpdateTickRate; - } - // Paper end -- if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { -+ if (!this.world.isClientSide && this.activeContainer != this.defaultContainer && (isFrozen() || !this.activeContainer.canUse(this))) { // Paper - auto close while frozen - this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.activeContainer = this.defaultContainer; - } -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } else { - // CraftBukkit start - this.activeContainer = container; -- this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); -+ if (!isFrozen()) this.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(), container.getTitle())); // Paper - // CraftBukkit end - container.addSlotListener(this); - return OptionalInt.of(this.containerCounter); -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - @Override -- protected boolean isFrozen() { -+ public boolean isFrozen() { // Paper - protected > public - return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper - - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - getHandle().activeContainer = container; - getHandle().activeContainer.addSlotListener(player); - } -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper - if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper - //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper -+ if (!player.isFrozen()) player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - player.activeContainer = container; - player.activeContainer.addSlotListener(player); - } diff --git a/Spigot-Server-Patches/Prevent-position-desync-in-playerconnection-causing-.patch b/Spigot-Server-Patches/Prevent-position-desync-in-playerconnection-causing-.patch deleted file mode 100644 index 52ab763df6..0000000000 --- a/Spigot-Server-Patches/Prevent-position-desync-in-playerconnection-causing-.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 12 Jun 2020 16:51:39 -0700 -Subject: [PATCH] Prevent position desync in playerconnection causing tp - exploit - -Caused the server to revert to the player's overworld coordinates -after teleporting into the end. - -Sidenote: The underlying issue is that the move call can teleport -entities and do other things like kill the entity. In the future, -to fix all exploits derieved from this usually unexpected -behaviour, we need to move all of this dangerous logic outside -of the move call and into an appropriate place in the tick method. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); - this.player.setOnGround(packetplayinflying.b()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move -+ // Paper start - prevent position desync -+ if (this.teleportPos != null) { -+ return; // ... thanks Mojang for letting move calls teleport across dimensions. -+ } -+ // Paper end - prevent position desync - double d12 = d8; - - d7 = d4 - this.player.locX(); diff --git a/Spigot-Server-Patches/Prevent-rayTrace-from-loading-chunks.patch b/Spigot-Server-Patches/Prevent-rayTrace-from-loading-chunks.patch deleted file mode 100644 index 62fe4453fe..0000000000 --- a/Spigot-Server-Patches/Prevent-rayTrace-from-loading-chunks.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 26 Nov 2018 19:21:58 -0500 -Subject: [PATCH] Prevent rayTrace from loading chunks - -ray tracing into an unloaded chunk should be treated as a miss -this saves a ton of lag for when AI tries to raytrace near unloaded chunks. - -diff --git a/src/main/java/net/minecraft/world/level/IBlockAccess.java b/src/main/java/net/minecraft/world/level/IBlockAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/IBlockAccess.java -+++ b/src/main/java/net/minecraft/world/level/IBlockAccess.java -@@ -0,0 +0,0 @@ public interface IBlockAccess { - - // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace - default MovingObjectPositionBlock rayTraceBlock(RayTrace raytrace1, BlockPosition blockposition) { -- IBlockData iblockdata = this.getType(blockposition); -+ // Paper start - Prevent raytrace from loading chunks -+ IBlockData iblockdata = this.getTypeIfLoaded(blockposition); -+ if (iblockdata == null) { -+ // copied the last function parameter (listed below) -+ Vec3D vec3d = raytrace1.b().d(raytrace1.a()); -+ -+ return MovingObjectPositionBlock.a(raytrace1.a(), EnumDirection.a(vec3d.x, vec3d.y, vec3d.z), new BlockPosition(raytrace1.a())); -+ } -+ // Paper end - Fluid fluid = this.getFluid(blockposition); - Vec3D vec3d = raytrace1.b(); - Vec3D vec3d1 = raytrace1.a(); diff --git a/Spigot-Server-Patches/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/Spigot-Server-Patches/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch deleted file mode 100644 index db4c238489..0000000000 --- a/Spigot-Server-Patches/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Callahan -Date: Mon, 13 Jan 2020 23:47:28 -0600 -Subject: [PATCH] Prevent sync chunk loads when villagers try to find beds - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorSleep.java -@@ -0,0 +0,0 @@ public class BehaviorSleep extends Behavior { - } - } - -- IBlockData iblockdata = worldserver.getType(globalpos.getBlockPosition()); -+ IBlockData iblockdata = worldserver.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper -+ if (iblockdata == null) { return false; } // Paper - - return globalpos.getBlockPosition().a((IPosition) entityliving.getPositionVector(), 2.0D) && iblockdata.getBlock().a((Tag) TagsBlock.BEDS) && !(Boolean) iblockdata.get(BlockBed.OCCUPIED); - } diff --git a/Spigot-Server-Patches/Prevent-teleporting-dead-entities.patch b/Spigot-Server-Patches/Prevent-teleporting-dead-entities.patch deleted file mode 100644 index 727d717e69..0000000000 --- a/Spigot-Server-Patches/Prevent-teleporting-dead-entities.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 3 Mar 2020 05:26:40 +0000 -Subject: [PATCH] Prevent teleporting dead entities - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set) { -+ if (player.dead) { -+ LOGGER.info("Attempt to teleport dead player {} restricted", player.getName()); -+ return; -+ } - // CraftBukkit start - if (Float.isNaN(f)) { - f = 0; diff --git a/Spigot-Server-Patches/Prevent-tile-entity-and-entity-crashes.patch b/Spigot-Server-Patches/Prevent-tile-entity-and-entity-crashes.patch deleted file mode 100644 index f91eccc0a1..0000000000 --- a/Spigot-Server-Patches/Prevent-tile-entity-and-entity-crashes.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 1 Mar 2016 23:52:34 -0600 -Subject: [PATCH] Prevent tile entity and entity crashes - - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - gameprofilerfiller.exit(); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.a(throwable, "Ticking block entity"); -- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block entity being ticked"); -- -- tileentity.a(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()); -+ throwable.printStackTrace(); -+ tilesThisCycle--; -+ this.tileEntityListTick.remove(tileTickPosition--); -+ continue; -+ // Paper end - // Spigot start - } finally { - tileentity.tickTimer.stopTiming(); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - try { - consumer.accept(entity); - } catch (Throwable throwable) { -- CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); -- CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); -- -- entity.appendEntityCrashDetails(crashreportsystemdetails); -- throw new ReportedException(crashreport); -+ // Paper start - Prevent tile entity and entity crashes -+ System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ()); -+ throwable.printStackTrace(); -+ entity.dead = true; -+ return; -+ // Paper end - } - } - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - return IRegistry.BLOCK_ENTITY_TYPE.getKey(this.getTileType()) + " // " + this.getClass().getCanonicalName(); - }); - if (this.world != null) { -- CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.getBlock()); -+ // Paper start - Prevent TileEntity and Entity crashes -+ IBlockData block = this.getBlock(); -+ if (block != null) { -+ CrashReportSystemDetails.a(crashreportsystemdetails, this.position, block); -+ } -+ // Paper end - CrashReportSystemDetails.a(crashreportsystemdetails, this.position, this.world.getType(this.position)); - } - } diff --git a/Spigot-Server-Patches/Print-Error-details-when-failing-to-save-player-data.patch b/Spigot-Server-Patches/Print-Error-details-when-failing-to-save-player-data.patch deleted file mode 100644 index 3bcf4ce32c..0000000000 --- a/Spigot-Server-Patches/Print-Error-details-when-failing-to-save-player-data.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 15 Jun 2018 20:37:03 -0400 -Subject: [PATCH] Print Error details when failing to save player data - - -diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -+++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java -@@ -0,0 +0,0 @@ public class WorldNBTStorage { - - SystemUtils.a(file1, file, file2); - } catch (Exception exception) { -- WorldNBTStorage.LOGGER.warn("Failed to save player data for {}", entityhuman.getDisplayName().getString()); -+ WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper - } - - } diff --git a/Spigot-Server-Patches/Profile-Lookup-Events.patch b/Spigot-Server-Patches/Profile-Lookup-Events.patch deleted file mode 100644 index d9b9aff6a5..0000000000 --- a/Spigot-Server-Patches/Profile-Lookup-Events.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 17:00:32 -0400 -Subject: [PATCH] Profile Lookup Events - -Adds a Pre Lookup Event and a Post Lookup Event so that plugins may prefill in profile data, and cache the responses from -profiles that had to be looked up. - -diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -+++ b/src/main/java/com/destroystokyo/paper/profile/PaperGameProfileRepository.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper.profile; - -+import com.destroystokyo.paper.event.profile.LookupProfileEvent; -+import com.destroystokyo.paper.event.profile.PreLookupProfileEvent; -+import com.google.common.collect.Sets; - import com.mojang.authlib.Agent; - import com.mojang.authlib.Environment; -+import com.mojang.authlib.GameProfile; - import com.mojang.authlib.ProfileLookupCallback; - import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; - import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; - -+import java.util.Set; - public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - public PaperGameProfileRepository(YggdrasilAuthenticationService authenticationService, Environment environment) { - super(authenticationService, environment); -@@ -0,0 +0,0 @@ public class PaperGameProfileRepository extends YggdrasilGameProfileRepository { - - @Override - public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) { -- super.findProfilesByNames(names, agent, callback); -+ Set unfoundNames = Sets.newHashSet(); -+ for (String name : names) { -+ PreLookupProfileEvent event = new PreLookupProfileEvent(name); -+ event.callEvent(); -+ if (event.getUUID() != null) { -+ // Plugin provided UUI, we can skip network call. -+ GameProfile gameprofile = new GameProfile(event.getUUID(), name); -+ // We might even have properties! -+ Set profileProperties = event.getProfileProperties(); -+ if (!profileProperties.isEmpty()) { -+ for (ProfileProperty property : profileProperties) { -+ gameprofile.getProperties().put(property.getName(), CraftPlayerProfile.asAuthlib(property)); -+ } -+ } -+ callback.onProfileLookupSucceeded(gameprofile); -+ } else { -+ unfoundNames.add(name); -+ } -+ } -+ -+ // Some things were not found.... Proceed to look up. -+ if (!unfoundNames.isEmpty()) { -+ String[] namesArr = unfoundNames.toArray(new String[unfoundNames.size()]); -+ super.findProfilesByNames(namesArr, agent, new PreProfileLookupCallback(callback)); -+ } -+ } -+ -+ private static class PreProfileLookupCallback implements ProfileLookupCallback { -+ private final ProfileLookupCallback callback; -+ -+ PreProfileLookupCallback(ProfileLookupCallback callback) { -+ this.callback = callback; -+ } -+ -+ @Override -+ public void onProfileLookupSucceeded(GameProfile gameProfile) { -+ PlayerProfile from = CraftPlayerProfile.asBukkitMirror(gameProfile); -+ new LookupProfileEvent(from).callEvent(); -+ callback.onProfileLookupSucceeded(gameProfile); -+ } -+ -+ @Override -+ public void onProfileLookupFailed(GameProfile gameProfile, Exception e) { -+ callback.onProfileLookupFailed(gameProfile, e); -+ } - } - } diff --git a/Spigot-Server-Patches/ProfileWhitelistVerifyEvent.patch b/Spigot-Server-Patches/ProfileWhitelistVerifyEvent.patch deleted file mode 100644 index 5b6d8129f8..0000000000 --- a/Spigot-Server-Patches/ProfileWhitelistVerifyEvent.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 3 Jul 2017 18:11:10 -0500 -Subject: [PATCH] ProfileWhitelistVerifyEvent - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - - // return chatmessage; - if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Spigot // Paper - Adventure -- } else if (!this.isWhitelisted(gameprofile)) { -- chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); -- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure -+ } else if (!this.isWhitelisted(gameprofile, event)) { // Paper -+ //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper -+ //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted - } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { - IpBanEntry ipbanentry = this.l.get(socketaddress); - -@@ -0,0 +0,0 @@ public abstract class PlayerList { - this.server.getCommandDispatcher().a(entityplayer); - } - -+ // Paper start - public boolean isWhitelisted(GameProfile gameprofile) { -- return !this.hasWhitelist || this.operators.d(gameprofile) || this.whitelist.d(gameprofile); -+ return isWhitelisted(gameprofile, null); - } -+ public boolean isWhitelisted(GameProfile gameprofile, org.bukkit.event.player.PlayerLoginEvent loginEvent) { -+ boolean isOp = this.operators.d(gameprofile); -+ boolean isWhitelisted = !this.hasWhitelist || isOp || this.whitelist.d(gameprofile); -+ final com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent event; -+ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(MCUtil.toBukkit(gameprofile), this.hasWhitelist, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); -+ event.callEvent(); -+ if (!event.isWhitelisted()) { -+ if (loginEvent != null) { -+ loginEvent.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getKickMessage() == null ? org.spigotmc.SpigotConfig.whitelistMessage : event.getKickMessage())); -+ } -+ return false; -+ } -+ return true; -+ } -+ // Paper end - - public boolean isOp(GameProfile gameprofile) { - return this.operators.d(gameprofile) || this.server.a(gameprofile) && this.server.getSaveData().o() || this.v; diff --git a/Spigot-Server-Patches/Properly-fix-item-duplication-bug.patch b/Spigot-Server-Patches/Properly-fix-item-duplication-bug.patch deleted file mode 100644 index a2f83d975a..0000000000 --- a/Spigot-Server-Patches/Properly-fix-item-duplication-bug.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Alfie Cleveland -Date: Tue, 27 Dec 2016 01:57:57 +0000 -Subject: [PATCH] Properly fix item duplication bug - -Credit to prplz for figuring out the real issue - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - @Override -- public boolean isFrozen() { -- return super.isFrozen() || !getBukkitEntity().isOnline(); -+ protected boolean isFrozen() { -+ return super.isFrozen() || (this.playerConnection != null && this.playerConnection.isDisconnected()); // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - public final boolean isDisconnected() { -- return !this.player.joining && !this.networkManager.isConnected(); -+ return (!this.player.joining && !this.networkManager.isConnected()) || this.processedDisconnect; // Paper - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/Properly-handle-async-calls-to-restart-the-server.patch b/Spigot-Server-Patches/Properly-handle-async-calls-to-restart-the-server.patch deleted file mode 100644 index 56b481e5f5..0000000000 --- a/Spigot-Server-Patches/Properly-handle-async-calls-to-restart-the-server.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Fri, 12 May 2017 23:34:11 -0500 -Subject: [PATCH] Properly handle async calls to restart the server - -The watchdog thread calls the server restart function asynchronously. Prior to -this change, it attempted to do several non-safe operations from the watchdog -thread, rather than the main. Specifically, because of a separate upstream change, -it causes player entities to be ticked asynchronously, among other things. - -This is dangerous. - -This patch moves the old handling into a synchronous variant, for calls from the -restart command, and adds separate handling for async calls, such as those from -the watchdog thread. - -When calling from the watchdog thread, we cannot assume the main thread is in a -tickable state; it may be completely deadlocked. In order to handle this, we mark -the server as stopping, in order to account for situations where the server should -complete a tick reasonbly soon, i.e. 99% of cases. - -Should the server not enter a state where it is stopping within 10 seconds, We -will assume that the server has in fact deadlocked and will proceed to force -kill the server. - -This modification does not force restart the server should we actually enter a -deadlocked state where the server is stopping, whereas this will in most cases -exit within a reasonable amount of time, to put a fixed limit on a process that -will have plugins and worlds saving to the disk has a high potential to result -in corruption/dataloss. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant, WorldServer> worldServer; - private PlayerList playerList; - private volatile boolean isRunning; -+ private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart - private boolean isStopped; - private int ticks; - protected final Proxy proxy; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && new File( split[0] ).isFile() ) -+ // Paper - extract method and cleanup -+ boolean isRestarting = addShutdownHook( restartScript ); -+ if ( isRestarting ) - { -- System.out.println( "Attempting to restart with " + restartScript ); -+ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); -+ } else -+ { -+ System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -+ } -+ // Stop the watchdog -+ WatchdogThread.doStop(); - -- // Disable Watchdog -- WatchdogThread.doStop(); -+ shutdownServer( isRestarting ); -+ // Paper end -+ } catch ( Exception ex ) -+ { -+ ex.printStackTrace(); -+ } -+ } - -- // Kick all players -- for ( EntityPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) -- { -- p.playerConnection.disconnect(SpigotConfig.restartMessage); -- } -- // Give the socket a chance to send the packets -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -- // Close the socket so we can rebind with the new process -- MinecraftServer.getServer().getServerConnection().b(); -+ // Paper start - sync copied from above with minor changes, async added -+ private static void shutdownServer(boolean isRestarting) -+ { -+ if ( MinecraftServer.getServer().isMainThread() ) -+ { -+ // Kick all players -+ for ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) -+ { -+ p.playerConnection.disconnect(SpigotConfig.restartMessage); -+ } -+ // Give the socket a chance to send the packets -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } - -- // Give time for it to kick in -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } -+ closeSocket(); - -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { -- } -+ // Actually shutdown -+ try -+ { -+ MinecraftServer.getServer().close(); // calls stop() -+ } catch ( Throwable t ) -+ { -+ } -+ -+ // Actually stop the JVM -+ System.exit( 0 ); - -- // This will be done AFTER the server has completely halted -- Thread shutdownHook = new Thread() -+ } else -+ { -+ // Mark the server to shutdown at the end of the tick -+ MinecraftServer.getServer().safeShutdown( false, isRestarting ); -+ -+ // wait 10 seconds to see if we're actually going to try shutdown -+ try -+ { -+ Thread.sleep( 10000 ); -+ } -+ catch (InterruptedException ignored) -+ { -+ } -+ -+ // Check if we've actually hit a state where the server is going to safely shutdown -+ // if we have, let the server stop as usual -+ if (MinecraftServer.getServer().isStopped()) return; -+ -+ // If the server hasn't stopped by now, assume worse case and kill -+ closeSocket(); -+ System.exit( 0 ); -+ } -+ } -+ // Paper end -+ -+ // Paper - Split from moved code -+ private static void closeSocket() -+ { -+ // Close the socket so we can rebind with the new process -+ MinecraftServer.getServer().getServerConnection().b(); -+ -+ // Give time for it to kick in -+ try -+ { -+ Thread.sleep( 100 ); -+ } catch ( InterruptedException ex ) -+ { -+ } -+ } -+ // Paper end -+ -+ // Paper start - copied from above and modified to return if the hook registered -+ private static boolean addShutdownHook(String restartScript) -+ { -+ String[] split = restartScript.split( " " ); -+ if ( split.length > 0 && new File( split[0] ).isFile() ) -+ { -+ Thread shutdownHook = new Thread() -+ { -+ @Override -+ public void run() - { -- @Override -- public void run() -+ try - { -- try -+ String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -+ if ( os.contains( "win" ) ) - { -- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -- if ( os.contains( "win" ) ) -- { -- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -- } else -- { -- Runtime.getRuntime().exec( "sh " + restartScript ); -- } -- } catch ( Exception e ) -+ Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -+ } else - { -- e.printStackTrace(); -+ Runtime.getRuntime().exec( "sh " + restartScript ); - } -+ } catch ( Exception e ) -+ { -+ e.printStackTrace(); - } -- }; -- -- shutdownHook.setDaemon( true ); -- Runtime.getRuntime().addShutdownHook( shutdownHook ); -- } else -- { -- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -- -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { - } -- } -- System.exit( 0 ); -- } catch ( Exception ex ) -+ }; -+ -+ shutdownHook.setDaemon( true ); -+ Runtime.getRuntime().addShutdownHook( shutdownHook ); -+ return true; -+ } else - { -- ex.printStackTrace(); -+ return false; - } - } -+ // Paper end -+ - } diff --git a/Spigot-Server-Patches/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/Spigot-Server-Patches/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch deleted file mode 100644 index db921d24e0..0000000000 --- a/Spigot-Server-Patches/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 May 2020 23:01:26 -0400 -Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed - -This fixes exploits that let players destroy bedrock by Pistons, explosions -and Mushrooom/Tree generation. - -These blocks are designed to not be broken except by creative players/commands. -So protect them from a multitude of methods of destroying them. - -A config is provided if you rather let players use these exploits, and let -them destroy the worlds End Portals and get on top of the nether easy. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void midTickChunkTasks() { - midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks); - } -+ -+ public static boolean allowBlockPermanentBreakingExploits = false; -+ private static void allowBlockPermanentBreakingExploits() { -+ if (config.contains("allow-perm-block-break-exploits")) { -+ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false); -+ config.set("allow-perm-block-break-exploits", null); -+ } -+ -+ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks."); -+ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits); -+ -+ } -+ - } -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -0,0 +0,0 @@ public class Explosion { - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPosition blockposition = new BlockPosition(d4, d5, d6); - IBlockData iblockdata = this.world.getType(blockposition); -+ if (!iblockdata.isDestroyable()) continue; // Paper - Fluid fluid = iblockdata.getFluid(); // Paper - Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); - -@@ -0,0 +0,0 @@ public class Explosion { - IBlockData iblockdata = this.world.getType(blockposition); - Block block = iblockdata.getBlock(); - -- if (!iblockdata.isAir()) { -+ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper - BlockPosition blockposition1 = blockposition.immutableCopy(); - - this.world.getMethodProfiler().enter("explosion_blocks"); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -+ // Paper start -+ IBlockData type = getType(blockposition); -+ if (!type.isDestroyable()) return false; -+ // Paper end - CraftBlockState blockstate = capturedBlockStates.get(blockposition); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -0,0 +0,0 @@ public class Block extends BlockBase implements IMaterial { - protected final BlockStateList blockStateList; - private IBlockData blockData; - // Paper start -+ public final boolean isDestroyable() { -+ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || -+ this != Blocks.BEDROCK && -+ this != Blocks.END_PORTAL_FRAME && -+ this != Blocks.END_PORTAL && -+ this != Blocks.END_GATEWAY && -+ this != Blocks.COMMAND_BLOCK && -+ this != Blocks.REPEATING_COMMAND_BLOCK && -+ this != Blocks.CHAIN_COMMAND_BLOCK && -+ this != Blocks.BARRIER && -+ this != Blocks.STRUCTURE_BLOCK && -+ this != Blocks.JIGSAW; -+ } - public co.aikar.timings.Timing timing; - public co.aikar.timings.Timing getTiming() { - if (timing == null) { -diff --git a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -+++ b/src/main/java/net/minecraft/world/level/block/piston/BlockPiston.java -@@ -0,0 +0,0 @@ public class BlockPiston extends BlockDirectional { - @Override - public boolean a(IBlockData iblockdata, World world, BlockPosition blockposition, int i, int j) { - EnumDirection enumdirection = (EnumDirection) iblockdata.get(BlockPiston.FACING); -+ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) -+ EnumDirection directionQueuedAs = EnumDirection.fromType1(j & 7); // Paper - copied from below -+ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) { -+ return false; -+ } -+ // Paper end - prevent retracting when we're facing the wrong way - - if (!world.isClientSide) { - boolean flag = this.a(world, blockposition, enumdirection); -@@ -0,0 +0,0 @@ public class BlockPiston extends BlockDirectional { - IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPistonMoving.a, enumdirection)).set(BlockPistonMoving.b, this.sticky ? BlockPropertyPistonType.STICKY : BlockPropertyPistonType.DEFAULT); - - world.setTypeAndData(blockposition, iblockdata1, 20); -- world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); -+ world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above - world.update(blockposition, iblockdata1.getBlock()); - iblockdata1.a(world, blockposition, 2); - if (this.sticky) { -@@ -0,0 +0,0 @@ public class BlockPiston extends BlockDirectional { - } - } - } else { -- world.a(blockposition.shift(enumdirection), false); -+ // Paper start - fix headless pistons breaking blocks -+ BlockPosition headPos = blockposition.shift(enumdirection); -+ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getType(headPos) == Blocks.PISTON_HEAD.getBlockData().set(FACING, enumdirection)) { // double check to make sure we're not a headless piston. -+ world.setAir(headPos, false); -+ } else { -+ ((WorldServer)world).getChunkProvider().flagDirty(headPos); // ... fix client desync -+ } -+ // Paper end - fix headless pistons breaking blocks - } - - world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PISTON_CONTRACT, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -0,0 +0,0 @@ public abstract class BlockBase { - - @Deprecated - public boolean a(IBlockData iblockdata, BlockActionContext blockactioncontext) { -- return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()); -+ return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()) && (iblockdata.isDestroyable() || (blockactioncontext.getEntity() != null && blockactioncontext.getEntity().abilities.canInstantlyBuild)); // Paper - } - - @Deprecated -@@ -0,0 +0,0 @@ public abstract class BlockBase { - public Block getBlock() { - return (Block) this.c; - } -- -+ // Paper start -+ public final boolean isDestroyable() { -+ return getBlock().isDestroyable(); -+ } -+ // Paper end - public Material getMaterial() { - return this.g; - } -@@ -0,0 +0,0 @@ public abstract class BlockBase { - } - - public EnumPistonReaction getPushReaction() { -- return this.getBlock().getPushReaction(this.p()); -+ return !isDestroyable() ? EnumPistonReaction.BLOCK : this.getBlock().getPushReaction(this.p()); // Paper - } - - public boolean i(IBlockAccess iblockaccess, BlockPosition blockposition) { diff --git a/Spigot-Server-Patches/Provide-E-TE-Chunk-count-stat-methods.patch b/Spigot-Server-Patches/Provide-E-TE-Chunk-count-stat-methods.patch deleted file mode 100644 index 772ef6cfe3..0000000000 --- a/Spigot-Server-Patches/Provide-E-TE-Chunk-count-stat-methods.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 7 Jan 2017 15:24:46 -0500 -Subject: [PATCH] Provide E/TE/Chunk count stat methods - -Provides counts without the ineffeciency of using .getEntities().size() -which creates copy of the collections. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - private int waterAmbientSpawn = -1; - private int ambientSpawn = -1; - -+ // Paper start - Provide fast information methods -+ public int getEntityCount() { -+ int ret = 0; -+ for (net.minecraft.world.entity.Entity entity : world.entitiesById.values()) { -+ if (entity.isChunkLoaded()) { -+ ++ret; -+ } -+ } -+ return ret; -+ } -+ public int getTileEntityCount() { -+ // We don't use the full world tile entity list, so we must iterate chunks -+ Long2ObjectLinkedOpenHashMap chunks = world.getChunkProvider().playerChunkMap.visibleChunks; -+ int size = 0; -+ for (PlayerChunk playerchunk : chunks.values()) { -+ net.minecraft.world.level.chunk.Chunk chunk = playerchunk.getChunk(); -+ if (chunk == null) { -+ continue; -+ } -+ size += chunk.tileEntities.size(); -+ } -+ return size; -+ } -+ public int getTickableTileEntityCount() { -+ return world.tileEntityListTick.size(); -+ } -+ public int getChunkCount() { -+ int ret = 0; -+ -+ for (PlayerChunk chunkHolder : world.getChunkProvider().playerChunkMap.visibleChunks.values()) { -+ if (chunkHolder.getChunk() != null) { -+ ++ret; -+ } -+ } -+ -+ return ret; -+ } -+ public int getPlayerCount() { -+ return world.players.size(); -+ } -+ // Paper end -+ - private static final Random rand = new Random(); - - public CraftWorld(WorldServer world, ChunkGenerator gen, Environment env) { diff --git a/Spigot-Server-Patches/RangedEntity-API.patch b/Spigot-Server-Patches/RangedEntity-API.patch deleted file mode 100644 index 158cce5cc6..0000000000 --- a/Spigot-Server-Patches/RangedEntity-API.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 26 Jun 2018 22:00:49 -0400 -Subject: [PATCH] RangedEntity API - -Allows you to determine if an entity is capable of ranged attacks, -and to perform an attack. - -diff --git a/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/entity/CraftRangedEntity.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.entity; -+ -+import net.minecraft.world.entity.monster.IRangedEntity; -+import org.bukkit.craftbukkit.entity.CraftLivingEntity; -+import org.bukkit.entity.LivingEntity; -+ -+public interface CraftRangedEntity extends RangedEntity { -+ T getHandle(); -+ -+ @Override -+ default void rangedAttack(LivingEntity target, float charge) { -+ getHandle().rangedAttack(((CraftLivingEntity) target).getHandle(), charge); -+ } -+ -+ @Override -+ default void setChargingAttack(boolean raiseHands) { -+ getHandle().setChargingAttack(raiseHands); -+ } -+} -diff --git a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -+++ b/src/main/java/net/minecraft/world/entity/monster/IRangedEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.EntityLiving; - - public interface IRangedEntity { - -- void a(EntityLiving entityliving, float f); -+ void a(EntityLiving entityliving, float f); default void rangedAttack(EntityLiving entityliving, float f) { a(entityliving, f); } // Paper - OBFHELPER -+ -+ // - see EntitySkeletonAbstract melee goal -+ void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.Drowned; - import org.bukkit.entity.EntityType; - --public class CraftDrowned extends CraftZombie implements Drowned { -+public class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftDrowned(CraftServer server, EntityDrowned entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Illusioner; - --public class CraftIllusioner extends CraftSpellcaster implements Illusioner { -+public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftIllusioner(CraftServer server, EntityIllagerIllusioner entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.entity; - -+import com.destroystokyo.paper.entity.CraftRangedEntity; - import com.google.common.base.Preconditions; - import net.minecraft.world.entity.animal.horse.EntityLlama; - import org.bukkit.craftbukkit.CraftServer; -@@ -0,0 +0,0 @@ import org.bukkit.entity.Llama; - import org.bukkit.entity.Llama.Color; - import org.bukkit.inventory.LlamaInventory; - --public class CraftLlama extends CraftChestedHorse implements Llama { -+public class CraftLlama extends CraftChestedHorse implements Llama, CraftRangedEntity { // Paper - - public CraftLlama(CraftServer server, EntityLlama entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Piglin; - import org.bukkit.inventory.Inventory; - --public class CraftPiglin extends CraftPiglinAbstract implements Piglin { -+public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPiglin(CraftServer server, EntityPiglin entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Pillager; - import org.bukkit.inventory.Inventory; - --public class CraftPillager extends CraftIllager implements Pillager { -+public class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftPillager(CraftServer server, EntityPillager entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -@@ -0,0 +0,0 @@ import org.bukkit.entity.EntityType; - import org.bukkit.entity.Skeleton; - import org.bukkit.entity.Skeleton.SkeletonType; - --public class CraftSkeleton extends CraftMonster implements Skeleton { -+public class CraftSkeleton extends CraftMonster implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - public CraftSkeleton(CraftServer server, EntitySkeletonAbstract entity) { - super(server, entity); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Snowman; - --public class CraftSnowman extends CraftGolem implements Snowman { -+public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftSnowman(CraftServer server, EntitySnowman entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Witch; - --public class CraftWitch extends CraftRaider implements Witch { -+public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftWitch(CraftServer server, EntityWitch entity) { - super(server, entity); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.boss.CraftBossBar; - import org.bukkit.entity.EntityType; - import org.bukkit.entity.Wither; - --public class CraftWither extends CraftMonster implements Wither { -+public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - - private BossBar bossBar; - diff --git a/Spigot-Server-Patches/Re-add-vanilla-entity-warnings-for-duplicates.patch b/Spigot-Server-Patches/Re-add-vanilla-entity-warnings-for-duplicates.patch deleted file mode 100644 index 44614565c8..0000000000 --- a/Spigot-Server-Patches/Re-add-vanilla-entity-warnings-for-duplicates.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:08:05 -0400 -Subject: [PATCH] Re-add vanilla entity warnings for duplicates - -These are a critical sign that somethin went wrong, and you've lost some data.... - -We should kind of know about these things you know. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (entity1 == null) { - return false; - } else { -- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit -+ WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit // Paper - return true; - } - } diff --git a/Spigot-Server-Patches/Reduce-Either-Optional-allocation.patch b/Spigot-Server-Patches/Reduce-Either-Optional-allocation.patch deleted file mode 100644 index 738c666afd..0000000000 --- a/Spigot-Server-Patches/Reduce-Either-Optional-allocation.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:35:09 -0700 -Subject: [PATCH] Reduce Either Optional allocation - -In order to get chunk values, we shouldn't need to create -an optional each time. - -diff --git a/src/main/java/com/mojang/datafixers/util/Either.java b/src/main/java/com/mojang/datafixers/util/Either.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/mojang/datafixers/util/Either.java -+++ b/src/main/java/com/mojang/datafixers/util/Either.java -@@ -0,0 +0,0 @@ public abstract class Either implements App, L> { - } - - private static final class Left extends Either { -- private final L value; -+ private final L value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Left(final L value) { - this.value = value; -@@ -0,0 +0,0 @@ public abstract class Either implements App, L> { - - @Override - public Optional left() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override -@@ -0,0 +0,0 @@ public abstract class Either implements App, L> { - } - - private static final class Right extends Either { -- private final R value; -+ private final R value; private Optional valueOptional; // Paper - reduce the optional allocation... - - public Right(final R value) { - this.value = value; -@@ -0,0 +0,0 @@ public abstract class Either implements App, L> { - - @Override - public Optional right() { -- return Optional.of(value); -+ return this.valueOptional == null ? this.valueOptional = Optional.of(this.value) : this.valueOptional; // Paper - reduce the optional allocation... - } - - @Override diff --git a/Spigot-Server-Patches/Reduce-MutableInt-allocations-from-light-engine.patch b/Spigot-Server-Patches/Reduce-MutableInt-allocations-from-light-engine.patch deleted file mode 100644 index a45bc68306..0000000000 --- a/Spigot-Server-Patches/Reduce-MutableInt-allocations-from-light-engine.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 02:48:06 -0700 -Subject: [PATCH] Reduce MutableInt allocations from light engine - -We can abuse the fact light is single threaded and share an instance -per light engine instance - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineBlock.java -@@ -0,0 +0,0 @@ public final class LightEngineBlock extends LightEngineLayer= 15) { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineSky.java -@@ -0,0 +0,0 @@ public final class LightEngineSky extends LightEngineLayer= 15) { - return k; - } else { -- MutableInt mutableint = new MutableInt(); -+ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded - IBlockData iblockdata = this.a(j, mutableint); - - if (mutableint.getValue() >= 15) { diff --git a/Spigot-Server-Patches/Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/Spigot-Server-Patches/Reduce-allocation-of-Vec3D-by-entity-tracker.patch deleted file mode 100644 index fb60d2b8f9..0000000000 --- a/Spigot-Server-Patches/Reduce-allocation-of-Vec3D-by-entity-tracker.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 00:04:16 -0700 -Subject: [PATCH] Reduce allocation of Vec3D by entity tracker - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - ++this.o; - i = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); - j = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); -- Vec3D vec3d = this.tracker.getPositionVector().d(PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc)); -- boolean flag1 = vec3d.g() >= 7.62939453125E-6D; -+ // Paper start - reduce allocation of Vec3D here -+ double vec3d_dx = this.tracker.locX() - 2.44140625E-4D*(this.xLoc); -+ double vec3d_dy = this.tracker.locY() - 2.44140625E-4D*(this.yLoc); -+ double vec3d_dz = this.tracker.locZ() - 2.44140625E-4D*(this.zLoc); -+ boolean flag1 = (vec3d_dx * vec3d_dx + vec3d_dy * vec3d_dy + vec3d_dz * vec3d_dz) >= 7.62939453125E-6D; -+ // Paper end - reduce allocation of Vec3D here - Packet packet1 = null; - boolean flag2 = flag1 || this.tickCounter % 60 == 0; - boolean flag3 = Math.abs(i - this.yRot) >= 1 || Math.abs(j - this.xRot) >= 1; -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - // CraftBukkit end - - if (this.tickCounter > 0 || this.tracker instanceof EntityArrow) { -- long k = PacketPlayOutEntity.a(vec3d.x); -- long l = PacketPlayOutEntity.a(vec3d.y); -- long i1 = PacketPlayOutEntity.a(vec3d.z); -+ // Paper start - remove allocation of Vec3D here -+ long k = PacketPlayOutEntity.a(vec3d_dx); -+ long l = PacketPlayOutEntity.a(vec3d_dy); -+ long i1 = PacketPlayOutEntity.a(vec3d_dz); -+ // Paper end - remove allocation of Vec3D here - boolean flag4 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L; - - if (!flag4 && this.o <= 400 && !this.q && this.r == this.tracker.isOnGround()) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public void updatePlayer(EntityPlayer entityplayer) { - org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot - if (entityplayer != this.tracker) { -- Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -+ // Paper start - remove allocation of Vec3D here -+ //Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113 -+ double vec3d_dx = entityplayer.locX() - this.tracker.locX(); -+ double vec3d_dy = entityplayer.locY() - this.tracker.locY(); -+ double vec3d_dz = entityplayer.locZ() - this.tracker.locZ(); -+ // Paper end - remove allocation of Vec3D here - int i = Math.min(this.b(), (PlayerChunkMap.this.viewDistance - 1) * 16); -- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.tracker.a(entityplayer); -+ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.tracker.a(entityplayer); // Paper - remove allocation of Vec3D here - - if (flag) { - boolean flag1 = this.tracker.attachedToPlayer; diff --git a/Spigot-Server-Patches/Reduce-blockpos-allocation-from-pathfinding.patch b/Spigot-Server-Patches/Reduce-blockpos-allocation-from-pathfinding.patch deleted file mode 100644 index 30acc1faca..0000000000 --- a/Spigot-Server-Patches/Reduce-blockpos-allocation-from-pathfinding.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 25 Apr 2020 17:10:55 -0700 -Subject: [PATCH] Reduce blockpos allocation from pathfinding - - -diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathfinderNormal.java -@@ -0,0 +0,0 @@ public class PathfinderNormal extends PathfinderAbstract { - return PathType.DANGER_FIRE; - } - -- if (iblockaccess.getFluid(blockposition_mutableblockposition).a((Tag) TagsFluid.WATER)) { -+ if (iblockdata.getFluid().a((Tag) TagsFluid.WATER)) { // Paper - remove another getType call - return PathType.WATER_BORDER; - } - } // Paper -@@ -0,0 +0,0 @@ public class PathfinderNormal extends PathfinderAbstract { - } else if (iblockdata.a(Blocks.COCOA)) { - return PathType.COCOA; - } else { -- Fluid fluid = iblockaccess.getFluid(blockposition); -+ Fluid fluid = iblockdata.getFluid(); // Paper - remove another get type call - - return fluid.a((Tag) TagsFluid.WATER) ? PathType.WATER : (fluid.a((Tag) TagsFluid.LAVA) ? PathType.LAVA : (a(iblockdata) ? PathType.DAMAGE_FIRE : (BlockDoor.l(iblockdata) && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_WOOD_CLOSED : (block instanceof BlockDoor && material == Material.ORE && !(Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_IRON_CLOSED : (block instanceof BlockDoor && (Boolean) iblockdata.get(BlockDoor.OPEN) ? PathType.DOOR_OPEN : (block instanceof BlockMinecartTrackAbstract ? PathType.RAIL : (block instanceof BlockLeaves ? PathType.LEAVES : (!block.a((Tag) TagsBlock.FENCES) && !block.a((Tag) TagsBlock.WALLS) && (!(block instanceof BlockFenceGate) || (Boolean) iblockdata.get(BlockFenceGate.OPEN)) ? (!iblockdata.a(iblockaccess, blockposition, PathMode.LAND) ? PathType.BLOCKED : PathType.OPEN) : PathType.FENCE)))))))); - } diff --git a/Spigot-Server-Patches/Reduce-memory-footprint-of-NBTTagCompound.patch b/Spigot-Server-Patches/Reduce-memory-footprint-of-NBTTagCompound.patch deleted file mode 100644 index ec23e9c459..0000000000 --- a/Spigot-Server-Patches/Reduce-memory-footprint-of-NBTTagCompound.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:39:25 -0700 -Subject: [PATCH] Reduce memory footprint of NBTTagCompound - -Fastutil maps are going to have a lower memory footprint - which -is important because we clone chunk data after reading it for safety. -So, reduce the impact of the clone on GC. - -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -0,0 +0,0 @@ import net.minecraft.ReportedException; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.chat.IChatMutableComponent; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - if (i > 512) { - throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); - } else { -- HashMap hashmap = Maps.newHashMap(); -+ Object2ObjectOpenHashMap hashmap = new Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound - - byte b0; - -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - } - - public NBTTagCompound() { -- this(Maps.newHashMap()); -+ this(new Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound - } - - @Override -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - - @Override - public NBTTagCompound clone() { -- Map map = Maps.newHashMap(Maps.transformValues(this.map, NBTBase::clone)); -+ // Paper start - reduce memory footprint of NBTTagCompound -+ Object2ObjectOpenHashMap ret = new Object2ObjectOpenHashMap<>(this.map.size(), 0.8f); - -- return new NBTTagCompound(map); -+ Iterator> iterator = (this.map instanceof Object2ObjectOpenHashMap) ? ((Object2ObjectOpenHashMap)this.map).object2ObjectEntrySet().fastIterator() : this.map.entrySet().iterator(); -+ while (iterator.hasNext()) { -+ Map.Entry entry = iterator.next(); -+ ret.put(entry.getKey(), entry.getValue().clone()); -+ } -+ -+ return new NBTTagCompound(ret); -+ // Paper end - reduce memory footprint of NBTTagCompound - } - - public boolean equals(Object object) { diff --git a/Spigot-Server-Patches/Reduce-sync-loads.patch b/Spigot-Server-Patches/Reduce-sync-loads.patch deleted file mode 100644 index 41ac7f9723..0000000000 --- a/Spigot-Server-Patches/Reduce-sync-loads.patch +++ /dev/null @@ -1,342 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 19 Jul 2019 03:29:14 -0700 -Subject: [PATCH] Reduce sync loads - -This reduces calls to getChunkAt which would load chunks. - -This patch also adds a tool to find calls which are doing this, however -it must be enabled by setting the startup flag -Dpaper.debug-sync-loads=true - -To get a debug log for sync loads, the command is /paper syncloadinfo - -diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperCommand.java -+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ - package com.destroystokyo.paper; - - import com.destroystokyo.paper.io.chunk.ChunkTaskManager; -+import com.destroystokyo.paper.io.SyncLoadFinder; - import com.google.common.base.Functions; - import com.google.common.base.Joiner; - import com.google.common.collect.ImmutableSet; -@@ -0,0 +0,0 @@ import com.google.common.collect.Iterables; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import net.minecraft.resources.MinecraftKey; -+import com.google.gson.JsonObject; -+import com.google.gson.internal.Streams; -+import com.google.gson.stream.JsonWriter; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ChunkProviderServer; - import net.minecraft.server.level.PlayerChunk; -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.entity.Player; - - import java.io.File; -+import java.io.FileOutputStream; -+import java.io.PrintStream; -+import java.io.StringWriter; - import java.time.LocalDateTime; - import java.time.format.DateTimeFormatter; - import java.util.ArrayList; -@@ -0,0 +0,0 @@ import java.util.stream.Collectors; - - public class PaperCommand extends Command { - private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); - - public PaperCommand(String name) { - super(name); -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - case "chunkinfo": - doChunkInfo(sender, args); - break; -+ case "syncloadinfo": -+ this.doSyncLoadInfo(sender, args); -+ break; - case "ver": - if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) - case "version": -@@ -0,0 +0,0 @@ public class PaperCommand extends Command { - return true; - } - -+ private void doSyncLoadInfo(CommandSender sender, String[] args) { -+ if (!SyncLoadFinder.ENABLED) { -+ sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); -+ return; -+ } -+ File file = new File(new File(new File("."), "debug"), -+ "sync-load-info" + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); -+ file.getParentFile().mkdirs(); -+ sender.sendMessage(ChatColor.GREEN + "Writing sync load info to " + file.toString()); -+ -+ -+ try { -+ final JsonObject data = SyncLoadFinder.serialize(); -+ -+ StringWriter stringWriter = new StringWriter(); -+ JsonWriter jsonWriter = new JsonWriter(stringWriter); -+ jsonWriter.setIndent(" "); -+ jsonWriter.setLenient(false); -+ Streams.write(data, jsonWriter); -+ -+ String fileData = stringWriter.toString(); -+ -+ try ( -+ PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8") -+ ) { -+ out.print(fileData); -+ } -+ sender.sendMessage(ChatColor.GREEN + "Successfully written sync load information!"); -+ } catch (Throwable thr) { -+ sender.sendMessage(ChatColor.RED + "Failed to write sync load information"); -+ thr.printStackTrace(); -+ } -+ } -+ - private void doChunkInfo(CommandSender sender, String[] args) { - List worlds; - if (args.length < 2 || args[1].equals("*")) { -diff --git a/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/io/SyncLoadFinder.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.io; -+ -+import com.google.gson.JsonArray; -+import com.google.gson.JsonObject; -+import com.mojang.datafixers.util.Pair; -+import it.unimi.dsi.fastutil.longs.Long2IntMap; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+ -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Map; -+import java.util.WeakHashMap; -+import net.minecraft.world.level.World; -+ -+public class SyncLoadFinder { -+ -+ public static final boolean ENABLED = Boolean.getBoolean("paper.debug-sync-loads"); -+ -+ private static final WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); -+ -+ private static final class SyncLoadInformation { -+ -+ public int times; -+ -+ public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); -+ } -+ -+ public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { -+ if (!ENABLED) { -+ return; -+ } -+ -+ final ThrowableWithEquals stacktrace = new ThrowableWithEquals(Thread.currentThread().getStackTrace()); -+ -+ SYNC_LOADS.compute(world, (final World keyInMap, Object2ObjectOpenHashMap map) -> { -+ if (map == null) { -+ map = new Object2ObjectOpenHashMap<>(); -+ } -+ -+ map.compute(stacktrace, (ThrowableWithEquals keyInMap0, SyncLoadInformation valueInMap) -> { -+ if (valueInMap == null) { -+ valueInMap = new SyncLoadInformation(); -+ } -+ -+ ++valueInMap.times; -+ -+ valueInMap.coordinateTimes.compute(IOUtil.getCoordinateKey(chunkX, chunkZ), (Long keyInMap1, Integer valueInMap1) -> { -+ return valueInMap1 == null ? Integer.valueOf(1) : Integer.valueOf(valueInMap1.intValue() + 1); -+ }); -+ -+ return valueInMap; -+ }); -+ -+ return map; -+ }); -+ } -+ -+ public static JsonObject serialize() { -+ final JsonObject ret = new JsonObject(); -+ -+ final JsonArray worldsData = new JsonArray(); -+ -+ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { -+ final World world = entry.getKey(); -+ -+ final JsonObject worldData = new JsonObject(); -+ -+ worldData.addProperty("name", world.getWorld().getName()); -+ -+ final List> data = new ArrayList<>(); -+ -+ entry.getValue().forEach((ThrowableWithEquals stacktrace, SyncLoadInformation times) -> { -+ data.add(new Pair<>(stacktrace, times)); -+ }); -+ -+ data.sort((Pair pair1, Pair pair2) -> { -+ return Integer.compare(pair2.getSecond().times, pair1.getSecond().times); // reverse order -+ }); -+ -+ final JsonArray stacktraces = new JsonArray(); -+ -+ for (Pair pair : data) { -+ final JsonObject stacktrace = new JsonObject(); -+ -+ stacktrace.addProperty("times", pair.getSecond().times); -+ -+ final JsonArray traces = new JsonArray(); -+ -+ for (StackTraceElement element : pair.getFirst().stacktrace) { -+ traces.add(String.valueOf(element)); -+ } -+ -+ stacktrace.add("stacktrace", traces); -+ -+ final JsonArray coordinates = new JsonArray(); -+ -+ for (Long2IntMap.Entry coordinate : pair.getSecond().coordinateTimes.long2IntEntrySet()) { -+ final long key = coordinate.getLongKey(); -+ final int times = coordinate.getIntValue(); -+ coordinates.add("(" + IOUtil.getCoordinateX(key) + "," + IOUtil.getCoordinateZ(key) + "): " + times); -+ } -+ -+ stacktrace.add("coordinates", coordinates); -+ -+ stacktraces.add(stacktrace); -+ } -+ -+ -+ worldData.add("stacktraces", stacktraces); -+ worldsData.add(worldData); -+ } -+ -+ ret.add("worlds", worldsData); -+ -+ return ret; -+ } -+ -+ static final class ThrowableWithEquals { -+ -+ private final StackTraceElement[] stacktrace; -+ private final int hash; -+ -+ public ThrowableWithEquals(final StackTraceElement[] stacktrace) { -+ this.stacktrace = stacktrace; -+ this.hash = ThrowableWithEquals.hash(stacktrace); -+ } -+ -+ public static int hash(final StackTraceElement[] stacktrace) { -+ int hash = 0; -+ -+ for (int i = 0; i < stacktrace.length; ++i) { -+ hash *= 31; -+ hash += stacktrace[i].hashCode(); -+ } -+ -+ return hash; -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object obj) { -+ if (obj == null || obj.getClass() != this.getClass()) { -+ return false; -+ } -+ -+ final ThrowableWithEquals other = (ThrowableWithEquals)obj; -+ final StackTraceElement[] otherStackTrace = other.stacktrace; -+ -+ if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) { -+ return false; -+ } -+ -+ if (this == obj) { -+ return true; -+ } -+ -+ for (int i = 0; i < this.stacktrace.length; ++i) { -+ if (!this.stacktrace[i].equals(otherStackTrace[i])) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.asyncChunkTaskManager.raisePriority(x, z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.world, x, z); - // Paper end -+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.world, x, z); // Paper - sync load info - this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); - com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }; - public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; - // Paper end -+ // Paper start -+ @Override -+ public boolean isChunkLoaded(int x, int z) { -+ return this.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; -+ } -+ // Paper end - - // Add env and gen to constructor, WorldData -> WorldDataServer - public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 <= j; ++i1) { - for (int j1 = k; j1 <= l; ++j1) { -- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(entity, axisalignedbb, list, predicate); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = this.getChunkProvider().getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(entitytypes, axisalignedbb, list, predicate); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(oclass, axisalignedbb, list, predicate); diff --git a/Spigot-Server-Patches/Refresh-player-inventory-when-cancelling-PlayerInter.patch b/Spigot-Server-Patches/Refresh-player-inventory-when-cancelling-PlayerInter.patch deleted file mode 100644 index f9ac5c62ed..0000000000 --- a/Spigot-Server-Patches/Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 13 Jul 2018 14:54:43 +0200 -Subject: [PATCH] Refresh player inventory when cancelling - PlayerInteractEntityEvent - -When interacting with entities with an item, the client will assume -the interaction is successful, and update the held item on the -client. However, if the interaction is cancelled on the server side, -the client will still mistakenly remove/replace the item in hand. - -Examples for this are milking cows with a bucket or dyeing sheep. -The bucket is replaced with milk and the dye removed from inventory. - -Refresh the player inventory when PlayerInteractEntityEvent is -cancelled to avoid this problem. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - if (event.isCancelled()) { -+ this.player.updateInventory(this.player.activeContainer); // Paper - Refresh player inventory - return; - } - // CraftBukkit end diff --git a/Spigot-Server-Patches/Remote-Connections-shouldn-t-hold-up-shutdown.patch b/Spigot-Server-Patches/Remote-Connections-shouldn-t-hold-up-shutdown.patch deleted file mode 100644 index 2c7491c56c..0000000000 --- a/Spigot-Server-Patches/Remote-Connections-shouldn-t-hold-up-shutdown.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:50:42 -0400 -Subject: [PATCH] Remote Connections shouldn't hold up shutdown - -Bugs in the connection logic appears to leave stale connections even, preventing shutdown - -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 IMinecraftServer - } - - if (this.remoteControlListener != null) { -- this.remoteControlListener.b(); -+ //this.remoteControlListener.b(); // Paper - don't wait for remote connections - } - - if (this.remoteStatusListener != null) { -- this.remoteStatusListener.b(); -+ //this.remoteStatusListener.b(); // Paper - don't wait for remote connections - } - - System.exit(0); // CraftBukkit diff --git a/Spigot-Server-Patches/Remove-CraftScheduler-Async-Task-Debugger.patch b/Spigot-Server-Patches/Remove-CraftScheduler-Async-Task-Debugger.patch deleted file mode 100644 index 7941dd2e6b..0000000000 --- a/Spigot-Server-Patches/Remove-CraftScheduler-Async-Task-Debugger.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 5 Feb 2017 00:04:04 -0500 -Subject: [PATCH] Remove CraftScheduler Async Task Debugger - -I have not once ever seen this system help debug a crash. -One report of a suspected memory leak with the system. - -This adds additional overhead to asynchronous task dispatching - -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - parsePending(); - } else { -- debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -+ //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper - executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper - // We don't need to parse pending - // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - pending.addAll(temp); - temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); -- debugHead = debugHead.getNextHead(currentTick); -+ //debugHead = debugHead.getNextHead(currentTick); // Paper - } - - private void addTask(final CraftTask task) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - - @Override - public String toString() { -+ // Paper start -+ return ""; -+ /* - int debugTick = currentTick; - StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); - debugHead.debugTo(string); - return string.append('}').toString(); -+ */ -+ // Paper end - } - - @Deprecated diff --git a/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch deleted file mode 100644 index af566cd19a..0000000000 --- a/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 16 Jun 2016 00:17:23 -0400 -Subject: [PATCH] Remove FishingHook reference on Craft Entity removal - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -@@ -0,0 +0,0 @@ public class CraftFishHook extends CraftProjectile implements FishHook { - public HookState getState() { - return HookState.values()[getHandle().hookState.ordinal()]; - } -+ -+ // Paper start -+ @Override -+ public void remove() { -+ super.remove(); -+ if (getHandle().getOwner() != null) { -+ getHandle().getOwner().hookedFish = null; -+ } -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Remove-Metadata-on-reload.patch b/Spigot-Server-Patches/Remove-Metadata-on-reload.patch deleted file mode 100644 index c6e4d700a6..0000000000 --- a/Spigot-Server-Patches/Remove-Metadata-on-reload.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 18 Mar 2016 13:50:14 -0400 -Subject: [PATCH] Remove Metadata on reload - -Metadata is not meant to persist reload as things break badly with non primitive types -This will remove metadata on reload so it does not crash everything if a plugin uses it. - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - world.paperConfig.init(); // Paper - } - -+ Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper - pluginManager.clearPlugins(); - commandMap.clearCommands(); -+ -+ // Paper start -+ for (Plugin plugin : pluginClone) { -+ entityMetadata.removeAll(plugin); -+ worldMetadata.removeAll(plugin); -+ playerMetadata.removeAll(plugin); -+ } -+ // Paper end -+ - resetRecipes(); - reloadData(); - org.spigotmc.SpigotConfig.registerCommands(); // Spigot diff --git a/Spigot-Server-Patches/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/Spigot-Server-Patches/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch deleted file mode 100644 index 91ac1e1582..0000000000 --- a/Spigot-Server-Patches/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Jan 2021 14:30:12 -0500 -Subject: [PATCH] Remove ProjectileHitEvent call when fireballs dead - -The duplicate ProjectileHitEvent in EntityFireball was removed. The -event was always called before the duplicate call. - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityFireball.java -@@ -0,0 +0,0 @@ public abstract class EntityFireball extends IProjectile { - - // CraftBukkit start - Fire ProjectileHitEvent - if (this.dead) { -- CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); -+ // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/Remove-armour-stand-double-add-to-world.patch b/Spigot-Server-Patches/Remove-armour-stand-double-add-to-world.patch deleted file mode 100644 index ec61f26065..0000000000 --- a/Spigot-Server-Patches/Remove-armour-stand-double-add-to-world.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Fri, 14 Aug 2020 23:59:26 +0200 -Subject: [PATCH] Remove armour stand double add to world - - -diff --git a/src/main/java/net/minecraft/world/item/ItemArmorStand.java b/src/main/java/net/minecraft/world/item/ItemArmorStand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemArmorStand.java -+++ b/src/main/java/net/minecraft/world/item/ItemArmorStand.java -@@ -0,0 +0,0 @@ public class ItemArmorStand extends Item { - return EnumInteractionResult.FAIL; - } - -- worldserver.addAllEntities(entityarmorstand); -+ // Paper - moved down - float f = (float) MathHelper.d((MathHelper.g(itemactioncontext.h() - 180.0F) + 22.5F) / 45.0F) * 45.0F; - - entityarmorstand.setPositionRotation(entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), f, 0.0F); -@@ -0,0 +0,0 @@ public class ItemArmorStand extends Item { - return EnumInteractionResult.FAIL; - } - // CraftBukkit end -- world.addEntity(entityarmorstand); -+ worldserver.addAllEntities(entityarmorstand); // Paper - moved down - world.playSound((EntityHuman) null, entityarmorstand.locX(), entityarmorstand.locY(), entityarmorstand.locZ(), SoundEffects.ENTITY_ARMOR_STAND_PLACE, SoundCategory.BLOCKS, 0.75F, 0.8F); - } - diff --git a/Spigot-Server-Patches/Remove-invalid-mob-spawner-tile-entities.patch b/Spigot-Server-Patches/Remove-invalid-mob-spawner-tile-entities.patch deleted file mode 100644 index 714ebcd961..0000000000 --- a/Spigot-Server-Patches/Remove-invalid-mob-spawner-tile-entities.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Tue, 1 Mar 2016 15:08:03 -0600 -Subject: [PATCH] Remove invalid mob spawner tile entities - - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.TickListChunk; - import net.minecraft.world.level.TickListEmpty; - import net.minecraft.world.level.World; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.BlockMobSpawner; - import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.ITileEntity; - import net.minecraft.world.level.block.entity.TileEntity; -+import net.minecraft.world.level.block.entity.TileEntityMobSpawner; - import net.minecraft.world.level.block.state.IBlockData; - import net.minecraft.world.level.levelgen.ChunkProviderDebug; - import net.minecraft.world.level.levelgen.HeightMap; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - - // CraftBukkit start -+ // Paper start - Remove invalid mob spawner tile entities -+ } else if (tileentity instanceof TileEntityMobSpawner && !(getBlockData(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getBlock() instanceof BlockMobSpawner)) { -+ this.tileEntities.remove(blockposition); -+ // Paper end - } else { - System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ() - + " (" + getType(blockposition) + ") where there was no entity tile!"); diff --git a/Spigot-Server-Patches/Remove-some-streams-from-structures.patch b/Spigot-Server-Patches/Remove-some-streams-from-structures.patch deleted file mode 100644 index 5b1d1c58c3..0000000000 --- a/Spigot-Server-Patches/Remove-some-streams-from-structures.patch +++ /dev/null @@ -1,140 +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/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/StructureManager.java -+++ b/src/main/java/net/minecraft/world/level/StructureManager.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level; - - import com.mojang.datafixers.DataFixUtils; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import java.util.stream.Stream; - import javax.annotation.Nullable; - import net.minecraft.core.BaseBlockPosition; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IStructureAccess; - import net.minecraft.world.level.levelgen.GeneratorSettings; - import net.minecraft.world.level.levelgen.feature.StructureGenerator; -+import net.minecraft.world.level.levelgen.structure.StructurePiece; - import net.minecraft.world.level.levelgen.structure.StructureStart; - - public class StructureManager { - -- private final GeneratorAccess a; -+ private final GeneratorAccess a; public GeneratorAccess getLevel() { return a; } // Paper - OBFHELPER - private final GeneratorSettings b; - - public StructureManager(GeneratorAccess generatoraccess, GeneratorSettings generatorsettings) { -@@ -0,0 +0,0 @@ public class StructureManager { - }); - } - -+ // Paper start - remove structure streams -+ public java.util.List> getFeatureStarts(SectionPosition sectionPosition, StructureGenerator structureGenerator) { -+ java.util.List> list = new ObjectArrayList<>(); -+ for (Long curLong: getLevel().getChunkAt(sectionPosition.a(), sectionPosition.c(), ChunkStatus.STRUCTURE_REFERENCES).b(structureGenerator)) { -+ SectionPosition sectionPosition1 = SectionPosition.a(new ChunkCoordIntPair(curLong), 0); -+ StructureStart structurestart = a(sectionPosition1, structureGenerator, getLevel().getChunkAt(sectionPosition1.a(), sectionPosition1.c(), ChunkStatus.STRUCTURE_STARTS)); -+ if (structurestart != null && structurestart.e()) { -+ list.add(structurestart); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - @Nullable - public StructureStart a(SectionPosition sectionposition, StructureGenerator structuregenerator, IStructureAccess istructureaccess) { - return istructureaccess.a(structuregenerator); -@@ -0,0 +0,0 @@ public class StructureManager { - } - - public StructureStart a(BlockPosition blockposition, boolean flag, StructureGenerator structuregenerator) { -- return (StructureStart) DataFixUtils.orElse(this.a(SectionPosition.a(blockposition), structuregenerator).filter((structurestart) -> { -- return structurestart.c().b((BaseBlockPosition) blockposition); -- }).filter((structurestart) -> { -- return !flag || structurestart.d().stream().anyMatch((structurepiece) -> { -- return structurepiece.g().b((BaseBlockPosition) blockposition); -- }); -- }).findFirst(), StructureStart.a); -+ // Paper start - remove structure streams -+ for (StructureStart structurestart : getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { -+ if (structurestart.c().b(blockposition)) { -+ if (!flag) { -+ return structurestart; -+ } -+ for (StructurePiece structurepiece : structurestart.d()) { -+ if (structurepiece.g().b(blockposition)) { -+ return structurestart; -+ } -+ } -+ } -+ } -+ return StructureStart.a; -+ // Paper end - } - - // Spigot start -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeBase.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.WorldGenStage; - import net.minecraft.world.level.levelgen.feature.StructureGenerator; - import net.minecraft.world.level.levelgen.feature.WorldGenFeatureConfigured; - import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.surfacebuilders.WorldGenSurfaceComposite; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; - import net.minecraft.world.level.material.Fluid; -@@ -0,0 +0,0 @@ public final class BiomeBase { - int l1 = j1 << 4; - - try { -- structuremanager.a(SectionPosition.a(blockposition), structuregenerator).forEach((structurestart) -> { -- structurestart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); -- }); -+ // Paper start - remove structure streams -+ for (StructureStart structureStart : structuremanager.getFeatureStarts(SectionPosition.a(blockposition), structuregenerator)) { -+ structureStart.a(regionlimitedworldaccess, structuremanager, chunkgenerator, seededrandom, new StructureBoundingBox(k1, l1, k1 + 15, l1 + 15), new ChunkCoordIntPair(i1, j1)); -+ } -+ // Paper end - } catch (Exception exception) { - CrashReport crashreport = CrashReport.a(exception, "Feature placement"); - -diff --git a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/ChunkGeneratorAbstract.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefi - import net.minecraft.world.level.levelgen.feature.structures.WorldGenFeatureDefinedStructurePoolTemplate; - import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; - import net.minecraft.world.level.levelgen.structure.StructurePiece; -+import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.WorldGenFeaturePillagerOutpostPoolPiece; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3; -@@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - while (iterator.hasNext()) { - StructureGenerator structuregenerator = (StructureGenerator) iterator.next(); - -- structuremanager.a(SectionPosition.a(chunkcoordintpair, 0), structuregenerator).forEach((structurestart) -> { -+ for (StructureStart structurestart : structuremanager.getFeatureStarts(SectionPosition.a(chunkcoordintpair, 0), structuregenerator)) { // Paper - remove structure streams - Iterator iterator1 = structurestart.d().iterator(); - - while (iterator1.hasNext()) { -@@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator { - } - } - -- }); -+ } // Paper - remove structure streams - } - - double[][][] adouble = new double[2][this.p + 1][this.o + 1]; diff --git a/Spigot-Server-Patches/Remove-stale-POIs.patch b/Spigot-Server-Patches/Remove-stale-POIs.patch deleted file mode 100644 index 27c4e51a36..0000000000 --- a/Spigot-Server-Patches/Remove-stale-POIs.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 9 Jan 2021 14:17:07 +0100 -Subject: [PATCH] Remove stale POIs - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - }); - optional1.ifPresent((villageplacetype) -> { - this.getMinecraftServer().execute(() -> { -+ // Paper start -+ if (!optional.isPresent() && this.getPoiStorage().test(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { -+ this.getPoiStorage().remove(blockposition1); -+ } -+ // Paper end - this.y().a(blockposition1, villageplacetype); - PacketDebug.a(this, blockposition1); - }); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - -+ public final VillagePlace getPoiStorage() { return this.y(); } // Paper - OBFHELPER - public VillagePlace y() { - return this.getChunkProvider().j(); - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/VillagePlace.java -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition, villageplacetype); - } - -+ public void remove(BlockPosition blockposition) { this.a(blockposition); } // Paper - OBFHELPER - public void a(BlockPosition blockposition) { - ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).a(blockposition); - } -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { - return ((VillagePlaceSection) this.e(SectionPosition.a(blockposition).s())).c(blockposition); - } - -+ public final boolean test(BlockPosition blockposition, Predicate predicate) { return this.a(blockposition, predicate); } // Paper - OBFHELPER - public boolean a(BlockPosition blockposition, Predicate predicate) { - return (Boolean) this.d(SectionPosition.a(blockposition).s()).map((villageplacesection) -> { - return villageplacesection.a(blockposition, predicate); diff --git a/Spigot-Server-Patches/Remove-streams-from-Mob-AI-System.patch b/Spigot-Server-Patches/Remove-streams-from-Mob-AI-System.patch deleted file mode 100644 index b18af6809f..0000000000 --- a/Spigot-Server-Patches/Remove-streams-from-Mob-AI-System.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 17:53:29 -0700 -Subject: [PATCH] Remove streams from Mob AI System - -The streams hurt performance and allocate tons of garbage, so -replace them with the standard iterator. - -Also optimise the stream.anyMatch statement to move to a bitset -where we can replace the call with a single bitwise operation. - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import java.util.EnumSet; - - public abstract class PathfinderGoal { - -- private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); -+ private final EnumSet a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - - public PathfinderGoal() {} - -@@ -0,0 +0,0 @@ public abstract class PathfinderGoal { - public void e() {} - - public void a(EnumSet enumset) { -- this.a.clear(); -- this.a.addAll(enumset); -+ // Paper start - remove streams from pathfindergoalselector -+ this.goalTypes.clear(); -+ this.goalTypes.addAllUnchecked(enumset); -+ // Paper end - remove streams from pathfindergoalselector - } - - public String toString() { - return this.getClass().getSimpleName(); - } - -- public EnumSet i() { -- return this.a; -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.goalTypes; -+ // Paper end - remove streams from pathfindergoalselector - } - - public static enum Type { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.entity.ai.goal; - -+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector - import com.google.common.collect.Sets; - import java.util.EnumMap; - import java.util.EnumSet; -+import java.util.Iterator; // Paper - remove streams from pathfindergoalselector - import java.util.Map; - import java.util.Set; - import java.util.function.Supplier; -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - private final Map c = new EnumMap(PathfinderGoal.Type.class); - private final Set d = Sets.newLinkedHashSet(); private Set getTasks() { return d; }// Paper - OBFHELPER - private final Supplier e; -- private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); -+ private final EnumSet f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be. -+ private final OptimizedSmallEnumSet goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector - private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER - private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO - -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - // Paper end - - public void a(PathfinderGoal pathfindergoal) { -- this.d.stream().filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.j() == pathfindergoal; -- }).filter(PathfinderGoalWrapped::g).forEach(PathfinderGoalWrapped::d); -- this.d.removeIf((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.j() == pathfindergoal; -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped goalWrapped = iterator.next(); -+ if (goalWrapped.j() != pathfindergoal) { -+ continue; -+ } -+ if (goalWrapped.g()) { -+ goalWrapped.d(); -+ } -+ iterator.remove(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - } - -+ private static final PathfinderGoal.Type[] PATHFINDER_GOAL_TYPES = PathfinderGoal.Type.values(); // Paper - remove streams from pathfindergoalselector -+ - public void doTick() { - GameProfilerFiller gameprofilerfiller = (GameProfilerFiller) this.e.get(); - - gameprofilerfiller.enter("goalCleanup"); -- this.d().filter((pathfindergoalwrapped) -> { -- boolean flag; -- -- if (pathfindergoalwrapped.g()) { -- Stream stream = pathfindergoalwrapped.i().stream(); -- EnumSet enumset = this.f; -- -- this.f.getClass(); -- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.b()) { -- flag = false; -- return flag; -- } -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (!wrappedGoal.g()) { -+ continue; - } -- -- flag = true; -- return flag; -- }).forEach(PathfinderGoal::d); -+ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.b()) { -+ continue; -+ } -+ wrappedGoal.d(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - this.c.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { - if (!pathfindergoalwrapped.g()) { - this.c.remove(pathfindergoal_type); -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - }); - gameprofilerfiller.exit(); - gameprofilerfiller.enter("goalUpdate"); -- this.d.stream().filter((pathfindergoalwrapped) -> { -- return !pathfindergoalwrapped.g(); -- }).filter((pathfindergoalwrapped) -> { -- Stream stream = pathfindergoalwrapped.i().stream(); -- EnumSet enumset = this.f; -- -- this.f.getClass(); -- return stream.noneMatch(enumset::contains); -- }).filter((pathfindergoalwrapped) -> { -- return pathfindergoalwrapped.i().stream().allMatch((pathfindergoal_type) -> { -- return ((PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b)).a(pathfindergoalwrapped); -- }); -- }).filter(PathfinderGoalWrapped::a).forEach((pathfindergoalwrapped) -> { -- pathfindergoalwrapped.i().forEach((pathfindergoal_type) -> { -- PathfinderGoalWrapped pathfindergoalwrapped1 = (PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b); -- -- pathfindergoalwrapped1.d(); -- this.c.put(pathfindergoal_type, pathfindergoalwrapped); -- }); -- pathfindergoalwrapped.c(); -- }); -+ // Paper start - remove streams from pathfindergoalselector -+ goal_update_loop: for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (wrappedGoal.g()) { -+ continue; -+ } -+ -+ OptimizedSmallEnumSet wrappedGoalSet = wrappedGoal.getGoalTypes(); -+ -+ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) { -+ continue; -+ } -+ -+ long iterator1 = wrappedGoalSet.getBackingSet(); -+ int wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); -+ if (!wrapped.a(wrappedGoal)) { -+ continue goal_update_loop; -+ } -+ } -+ -+ if (!wrappedGoal.a()) { -+ continue; -+ } -+ -+ iterator1 = wrappedGoalSet.getBackingSet(); -+ wrappedGoalSize = wrappedGoalSet.size(); -+ for (int i = 0; i < wrappedGoalSize; ++i) { -+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; -+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); -+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b); -+ -+ wrapped.d(); -+ this.c.put(type, wrappedGoal); -+ } -+ -+ wrappedGoal.c(); -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.exit(); - gameprofilerfiller.enter("goalTick"); -- this.d().forEach(PathfinderGoalWrapped::e); -+ // Paper start - remove streams from pathfindergoalselector -+ for (Iterator iterator = this.d.iterator(); iterator.hasNext();) { -+ PathfinderGoalWrapped wrappedGoal = iterator.next(); -+ if (wrappedGoal.g()) { -+ wrappedGoal.e(); -+ } -+ } -+ // Paper end - remove streams from pathfindergoalselector - gameprofilerfiller.exit(); - } - -@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { - } - - public void a(PathfinderGoal.Type pathfindergoal_type) { -- this.f.add(pathfindergoal_type); -+ this.goalTypes.addUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector - } - - public void b(PathfinderGoal.Type pathfindergoal_type) { -- this.f.remove(pathfindergoal_type); -+ this.goalTypes.removeUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector - } - - public void a(PathfinderGoal.Type pathfindergoal_type, boolean flag) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java -@@ -0,0 +0,0 @@ public class PathfinderGoalWrapped extends PathfinderGoal { - this.a.a(enumset); - } - -- @Override -- public EnumSet i() { -- return this.a.i(); -+ // Paper start - remove streams from pathfindergoalselector -+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { -+ return this.a.getGoalTypes(); -+ // Paper end - remove streams from pathfindergoalselector - } - - public boolean isRunning() { return this.g(); } // Paper - OBFHELPER diff --git a/Spigot-Server-Patches/Remove-streams-from-PairedQueue.patch b/Spigot-Server-Patches/Remove-streams-from-PairedQueue.patch deleted file mode 100644 index 65457f4171..0000000000 --- a/Spigot-Server-Patches/Remove-streams-from-PairedQueue.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 6 Apr 2020 18:10:43 -0700 -Subject: [PATCH] Remove streams from PairedQueue - -We shouldn't be doing stream calls just to see if the queue is -empty. This creates loads of garbage thanks to how often it's called. - -diff --git a/src/main/java/net/minecraft/util/thread/PairedQueue.java b/src/main/java/net/minecraft/util/thread/PairedQueue.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/thread/PairedQueue.java -+++ b/src/main/java/net/minecraft/util/thread/PairedQueue.java -@@ -0,0 +0,0 @@ public interface PairedQueue { - - public static final class a implements PairedQueue { - -- private final List> a; -+ private final List> a; private final List> getQueues() { return this.a; } // Paper - OBFHELPER - - public a(int i) { -- this.a = (List) IntStream.range(0, i).mapToObj((j) -> { -- return Queues.newConcurrentLinkedQueue(); -- }).collect(Collectors.toList()); -+ // Paper start - remove streams -+ this.a = new java.util.ArrayList<>(i); // queues -+ for (int j = 0; j < i; ++j) { -+ this.getQueues().add(Queues.newConcurrentLinkedQueue()); -+ } -+ // Paper end - remove streams - } - - @Nullable - @Override - public Runnable a() { -- Iterator iterator = this.a.iterator(); -- -- Runnable runnable; -- -- do { -- if (!iterator.hasNext()) { -- return null; -+ // Paper start - remove iterator creation -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ Runnable ret = queue.poll(); -+ if (ret != null) { -+ return ret; - } -- -- Queue queue = (Queue) iterator.next(); -- -- runnable = (Runnable) queue.poll(); -- } while (runnable == null); -- -- return runnable; -+ } -+ return null; -+ // Paper end - remove iterator creation - } - - public boolean a(PairedQueue.b pairedqueue_b) { -@@ -0,0 +0,0 @@ public interface PairedQueue { - - @Override - public boolean b() { -- return this.a.stream().allMatch(Collection::isEmpty); -+ // Paper start - remove streams -+ // why are we doing streams every time we might want to execute a task? -+ for (int i = 0, len = this.getQueues().size(); i < len; ++i) { -+ Queue queue = this.getQueues().get(i); -+ if (!queue.isEmpty()) { -+ return false; -+ } -+ } -+ return true; -+ // Paper end - remove streams - } - } - diff --git a/Spigot-Server-Patches/Remove-streams-from-SensorNearest.patch b/Spigot-Server-Patches/Remove-streams-from-SensorNearest.patch deleted file mode 100644 index ec1f8657c8..0000000000 --- a/Spigot-Server-Patches/Remove-streams-from-SensorNearest.patch +++ /dev/null @@ -1,120 +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/SensorNearestItems.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestItems.java -@@ -0,0 +0,0 @@ public class SensorNearestItems extends Sensor { - List list = worldserver.a(EntityItem.class, entityinsentient.getBoundingBox().grow(8.0D, 4.0D, 8.0D), (entityitem) -> { - return true; - }); -- -- entityinsentient.getClass(); -+ // Paper start - remove streams in favour of lists - list.sort(Comparator.comparingDouble(entityinsentient::h)); -- Stream stream = list.stream().filter((entityitem) -> { -- return entityinsentient.i(entityitem.getItemStack()); -- }).filter((entityitem) -> { -- return entityitem.a((Entity) entityinsentient, 9.0D); -- }); -- -- entityinsentient.getClass(); -- Optional optional = stream.filter(entityinsentient::hasLineOfSight).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); -+ EntityItem nearest = null; -+ for (EntityItem entityItem : list) { -+ if (entityinsentient.i(entityItem.getItemStack()) && entityItem.a(entityinsentient, 9.0D) && entityinsentient.hasLineOfSight(entityItem)) { -+ nearest = entityItem; -+ break; -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); -+ // Paper end - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestLivingEntities.java -@@ -0,0 +0,0 @@ public class SensorNearestLivingEntities extends Sensor { - list.sort(Comparator.comparingDouble(entityliving::h)); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); - -- behaviorcontroller.setMemory(MemoryModuleType.MOBS, (Object) list); -- behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, list.stream().filter((entityliving1) -> { -- return a(entityliving, entityliving1); -- }).collect(Collectors.toList())); -+ behaviorcontroller.setMemory(MemoryModuleType.MOBS, list); // Paper - decompile error -+ // Paper start - remove streams in favour of lists -+ List visibleMobs = new java.util.ArrayList<>(list); -+ visibleMobs.removeIf(otherEntityLiving -> !Sensor.a(entityliving, otherEntityLiving)); -+ behaviorcontroller.setMemory(MemoryModuleType.VISIBLE_MOBS, visibleMobs); -+ // Paper end - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/SensorNearestPlayers.java -@@ -0,0 +0,0 @@ public class SensorNearestPlayers extends Sensor { - - @Override - protected void a(WorldServer worldserver, EntityLiving entityliving) { -- Stream stream = worldserver.getPlayers().stream().filter(IEntitySelector.g).filter((entityplayer) -> { -- return entityliving.a((Entity) entityplayer, 16.0D); -- }); -+ // Paper start - remove streams in favour of lists -+ List players = new java.util.ArrayList<>(worldserver.getPlayers()); -+ players.removeIf(player -> !IEntitySelector.notSpectator().test(player) || !entityliving.a(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator -+ players.sort(Comparator.comparingDouble(entityliving::h)); - -- entityliving.getClass(); -- List list = (List) stream.sorted(Comparator.comparingDouble(entityliving::h)).collect(Collectors.toList()); - BehaviorController behaviorcontroller = entityliving.getBehaviorController(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, (Object) list); -- List list1 = (List) list.stream().filter((entityhuman) -> { -- return a(entityliving, (EntityLiving) entityhuman); -- }).collect(Collectors.toList()); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, (Object) (list1.isEmpty() ? null : (EntityHuman) list1.get(0))); -- Optional optional = list1.stream().filter(IEntitySelector.f).findFirst(); -- -- behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, optional); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); -+ -+ EntityHuman nearest = null, nearestTargetable = null; -+ for (EntityHuman player : players) { -+ if (Sensor.a(entityliving, player)) { -+ if (nearest == null) nearest = player; -+ if (IEntitySelector.canAITarget().test(player)) { -+ nearestTargetable = player; -+ break; // Both variables are assigned, no reason to loop further -+ } -+ } -+ } -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); -+ behaviorcontroller.setMemory(MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, nearestTargetable); -+ // Paper end - } - } diff --git a/Spigot-Server-Patches/Remove-streams-from-classes-related-villager-gossip.patch b/Spigot-Server-Patches/Remove-streams-from-classes-related-villager-gossip.patch deleted file mode 100644 index abd808838d..0000000000 --- a/Spigot-Server-Patches/Remove-streams-from-classes-related-villager-gossip.patch +++ /dev/null @@ -1,100 +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/Reputation.java b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/Reputation.java -@@ -0,0 +0,0 @@ import com.mojang.serialization.DynamicOps; - import it.unimi.dsi.fastutil.objects.Object2IntMap; - import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; - import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper - import it.unimi.dsi.fastutil.objects.ObjectIterator; - import java.util.Arrays; - import java.util.Collection; -@@ -0,0 +0,0 @@ public class Reputation { - }); - } - -+ // Paper start - Remove streams from reputation -+ private List decompress() { -+ List list = new ObjectArrayList<>(); -+ for (Map.Entry entry : getReputations().entrySet()) { -+ for (Reputation.b cur : entry.getValue().decompress(entry.getKey())) { -+ if (cur.a() != 0) -+ list.add(cur); -+ } -+ } -+ return list; -+ } -+ // Paper end -+ - private Collection a(Random random, int i) { -- List list = (List) this.c().collect(Collectors.toList()); -+ List list = decompress(); // Paper - Remove streams from reputation - - if (list.isEmpty()) { - return Collections.emptyList(); -@@ -0,0 +0,0 @@ public class Reputation { - } - - public Dynamic a(DynamicOps dynamicops) { -- return new Dynamic(dynamicops, dynamicops.createList(this.c().map((reputation_b) -> { -+ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { - return reputation_b.a(dynamicops); - }).map(Dynamic::getValue))); - } -@@ -0,0 +0,0 @@ public class Reputation { - - public static class a { // Paper - make public - -- private final Object2IntMap a; -+ private final Object2IntMap a; private Object2IntMap getEntries() { return a; } // Paper - OBFHELPER - - public a() { // Paper - make public - update CraftVillager setReputation on change - this.a = new Object2IntOpenHashMap(); - } - - public int a(Predicate predicate) { -- return this.a.object2IntEntrySet().stream().filter((entry) -> { -- return predicate.test(entry.getKey()); -- }).mapToInt((entry) -> { -- return entry.getIntValue() * ((ReputationType) entry.getKey()).g; -- }).sum(); -+ // Paper start - Remove streams from reputation -+ int weight = 0; -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ if (predicate.test(entry.getKey())) { -+ weight += entry.getIntValue() * entry.getKey().getWeight(); -+ } -+ } -+ return weight; -+ } -+ -+ public List decompress(UUID uuid) { -+ List list = new ObjectArrayList<>(); -+ for (Object2IntMap.Entry entry : getEntries().object2IntEntrySet()) { -+ list.add(new Reputation.b(uuid, entry.getKey(), entry.getIntValue())); -+ } -+ return list; -+ // Paper - end - } - - public Stream a(UUID uuid) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -+++ b/src/main/java/net/minecraft/world/entity/ai/gossip/ReputationType.java -@@ -0,0 +0,0 @@ public enum ReputationType { - MAJOR_NEGATIVE("major_negative", -5, 100, 10, 10), MINOR_NEGATIVE("minor_negative", -1, 200, 20, 20), MINOR_POSITIVE("minor_positive", 1, 200, 1, 5), MAJOR_POSITIVE("major_positive", 5, 100, 0, 100), TRADING("trading", 1, 25, 2, 20); - - public final String f; -- public final int g; -+ public final int g; public int getWeight() { return g; } // Paper - OBFHELPER - public final int h; - public final int i; - public final int j; diff --git a/Spigot-Server-Patches/Remove-unused-World-Tile-Entity-List.patch b/Spigot-Server-Patches/Remove-unused-World-Tile-Entity-List.patch deleted file mode 100644 index 551a515e97..0000000000 --- a/Spigot-Server-Patches/Remove-unused-World-Tile-Entity-List.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 13 Apr 2016 00:25:28 -0400 -Subject: [PATCH] Remove unused World Tile Entity List - -Massive hit to performance and it is completely unnecessary. - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size())); -- bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityList.size())); -+ bufferedwriter.write(String.format("block_entities: %d\n", this.tileEntityListTick.size())); // Paper - remove unused list - bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTickList().a())); - bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getFluidTickList().a())); - bufferedwriter.write("distance_manager: " + playerchunkmap.e().c() + "\n"); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - private void a(Writer writer) throws IOException { - CSVWriter csvwriter = CSVWriter.a().a("x").a("y").a("z").a("type").a(writer); -- Iterator iterator = this.tileEntityList.iterator(); -+ Iterator iterator = this.tileEntityListTick.iterator(); // Paper - remove unused list - - while (iterator.hasNext()) { - TileEntity tileentity = (TileEntity) iterator.next(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public static final ResourceKey THE_NETHER = ResourceKey.a(IRegistry.L, new MinecraftKey("the_nether")); - public static final ResourceKey THE_END = ResourceKey.a(IRegistry.L, new MinecraftKey("the_end")); - private static final EnumDirection[] a = EnumDirection.values(); -- public final List tileEntityList = Lists.newArrayList(); -+ //public final List tileEntityList = Lists.newArrayList(); // Paper - remove unused list - public final List tileEntityListTick = Lists.newArrayList(); - protected final List tileEntityListPending = Lists.newArrayList(); - protected final java.util.Set tileEntityListUnload = com.google.common.collect.Sets.newHashSet(); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - }, tileentity::getPosition}); - } - -- boolean flag = this.tileEntityList.add(tileentity); -+ boolean flag = true; // Paper - remove unused list - -- if (flag && tileentity instanceof ITickable) { -+ if (flag && tileentity instanceof ITickable && !this.tileEntityListTick.contains(tileentity)) { // Paper - this.tileEntityListTick.add(tileentity); - } - -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - timings.tileEntityTick.startTiming(); // Spigot - if (!this.tileEntityListUnload.isEmpty()) { - this.tileEntityListTick.removeAll(this.tileEntityListUnload); -- this.tileEntityList.removeAll(this.tileEntityListUnload); -+ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list - this.tileEntityListUnload.clear(); - } - -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - tilesThisCycle--; - this.tileEntityListTick.remove(tileTickPosition--); - // Spigot end -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - if (this.isLoaded(tileentity.getPosition())) { - this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition()); - } -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.notify(tileentity1.getPosition(), iblockdata, iblockdata, 3); - // CraftBukkit start - // From above, don't screw this up - SPIGOT-1746 -- if (!this.tileEntityList.contains(tileentity1)) { -+ if (true) { // Paper - remove unused list - this.a(tileentity1); - } - // CraftBukkit end -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } else { - if (tileentity != null) { - this.tileEntityListPending.remove(tileentity); -- this.tileEntityList.remove(tileentity); -+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list - this.tileEntityListTick.remove(tileentity); - } - diff --git a/Spigot-Server-Patches/Reset-Ender-Crystals-on-Dragon-Spawn.patch b/Spigot-Server-Patches/Reset-Ender-Crystals-on-Dragon-Spawn.patch deleted file mode 100644 index b79c43de71..0000000000 --- a/Spigot-Server-Patches/Reset-Ender-Crystals-on-Dragon-Spawn.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 1 Jun 2016 23:29:17 -0400 -Subject: [PATCH] Reset Ender Crystals on Dragon Spawn - -Crystals can end up in a bad state in certain conditions which causes -an exception on the expected number of crystals going negative. - -This ensures the crystals/pillars are in expected state when the dragon spawns. - -See #3522 - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -0,0 +0,0 @@ public class EnderDragonBattle { - entityenderdragon.setPositionRotation(0.0D, 128.0D, 0.0D, this.world.random.nextFloat() * 360.0F, 0.0F); - this.world.addEntity(entityenderdragon); - this.dragonUUID = entityenderdragon.getUniqueID(); -+ this.resetCrystals(); // Paper - return entityenderdragon; - } - diff --git a/Spigot-Server-Patches/Reset-players-airTicks-on-respawn.patch b/Spigot-Server-Patches/Reset-players-airTicks-on-respawn.patch deleted file mode 100644 index a92929f0d8..0000000000 --- a/Spigot-Server-Patches/Reset-players-airTicks-on-respawn.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: GreenMeanie -Date: Sat, 20 Oct 2018 22:34:02 -0400 -Subject: [PATCH] Reset players airTicks on respawn - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - - this.setHealth(this.getMaxHealth()); -+ this.setAirTicks(this.getMaxAirTicks()); // Paper - this.fireTicks = 0; - this.fallDistance = 0; - this.foodData = new FoodMetaData(this); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - } - -+ public final int getMaxAirTicks() { return bH(); } // Paper - OBFHELPER - public int bH() { - return 300; - } diff --git a/Spigot-Server-Patches/Reset-shield-blocking-on-dimension-change.patch b/Spigot-Server-Patches/Reset-shield-blocking-on-dimension-change.patch deleted file mode 100644 index 8ef85b78e3..0000000000 --- a/Spigot-Server-Patches/Reset-shield-blocking-on-dimension-change.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Yive -Date: Sun, 24 Jan 2021 08:55:19 -0800 -Subject: [PATCH] Reset shield blocking on dimension change - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.world.getServer().getPluginManager().callEvent(changeEvent); - // CraftBukkit end - } -+ // Paper start -+ if (this.isBlocking()) { -+ this.clearActiveItem(); -+ } -+ // Paper end - - return this; - } diff --git a/Spigot-Server-Patches/Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/Spigot-Server-Patches/Reset-spawner-timer-when-spawner-event-is-cancelled.patch deleted file mode 100644 index 943f1a2f06..0000000000 --- a/Spigot-Server-Patches/Reset-spawner-timer-when-spawner-event-is-cancelled.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Mon, 31 Jul 2017 01:45:19 -0500 -Subject: [PATCH] Reset spawner timer when spawner event is cancelled - - -diff --git a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/world/level/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - // Spigot End - } - entity.spawnedViaMobSpawner = true; // Paper -+ flag = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - ((EntityInsentient) entity).doSpawnEffect(); - } - -- flag = true; -+ /*flag = true;*/ // Paper - moved up above cancellable event - } - } - } diff --git a/Spigot-Server-Patches/Reset-villager-inventory-on-cancelled-pickup-event.patch b/Spigot-Server-Patches/Reset-villager-inventory-on-cancelled-pickup-event.patch deleted file mode 100644 index 3269576ef6..0000000000 --- a/Spigot-Server-Patches/Reset-villager-inventory-on-cancelled-pickup-event.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Tue, 1 Jun 2021 22:05:08 -0500 -Subject: [PATCH] Reset villager inventory on cancelled pickup event - - -diff --git a/src/main/java/net/minecraft/world/InventorySubcontainer.java b/src/main/java/net/minecraft/world/InventorySubcontainer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/InventorySubcontainer.java -+++ b/src/main/java/net/minecraft/world/InventorySubcontainer.java -@@ -0,0 +0,0 @@ public class InventorySubcontainer implements IInventory, AutoRecipeOutput { - return this.items; - } - -+ // Paper start -+ public void setContents(List items) { -+ this.items.clear(); -+ for(int i = 0; i < items.size(); i++) { -+ this.items.set(i, items.get(i)); -+ } -+ this.update(); -+ } -+ // Paper end -+ - public void onOpen(CraftHumanEntity who) { - transaction.add(who); - } -@@ -0,0 +0,0 @@ public class InventorySubcontainer implements IInventory, AutoRecipeOutput { - return itemstack; - } - -+ public ItemStack addItem(ItemStack itemstack) { return a(itemstack); } // Paper - OBFHELPER - public ItemStack a(ItemStack itemstack) { - ItemStack itemstack1 = itemstack.cloneItemStack(); - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - } - - // CraftBukkit start -- ItemStack remaining = new InventorySubcontainer(inventorysubcontainer).a(itemstack); -- if (CraftEventFactory.callEntityPickupItemEvent(this, entityitem, remaining.getCount(), false).isCancelled()) { -+ // Paper start -+ List contentsSnapshot = new java.util.ArrayList<>(inventorysubcontainer.getContents()); -+ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); -+ if (CraftEventFactory.callEntityPickupItemEvent(this, entityitem, itemstack1.getCount(), false).isCancelled()) { -+ inventorysubcontainer.setContents(contentsSnapshot); -+ // Paper end - return; - } - // CraftBukkit end - - this.a(entityitem); - this.receive(entityitem, itemstack.getCount()); -- ItemStack itemstack1 = inventorysubcontainer.a(itemstack); -+ // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up - - if (itemstack1.isEmpty()) { - entityitem.die(); diff --git a/Spigot-Server-Patches/Restore-custom-InventoryHolder-support.patch b/Spigot-Server-Patches/Restore-custom-InventoryHolder-support.patch deleted file mode 100644 index d5c9bd78b9..0000000000 --- a/Spigot-Server-Patches/Restore-custom-InventoryHolder-support.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 5 Nov 2018 04:23:51 +0000 -Subject: [PATCH] Restore custom InventoryHolder support - -Upstream removed the ability to consistently use a custom InventoryHolder, -However, the implementation does not use an InventoryHolder in any form -outside of custom inventories. - -We can take that knowledge and apply some expected behavior, if we're given -an inventory holder, we should use it and return a custom inventory with the -holder, otherwise, create an inventory backed by the intended inventory, as -per upstream behavior. - -This provides a "best of both worlds" scenario: plugins with InventoryHolder's -will always work as intended in the past, those without will create implementation -based inventories. - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java -@@ -0,0 +0,0 @@ public final class CraftInventoryCreator { - } - - public Inventory createInventory(InventoryHolder holder, InventoryType type) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type); - } - -@@ -0,0 +0,0 @@ public final class CraftInventoryCreator { - // Paper end - - public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { -+ // Paper start -+ if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type, title); -+ } -+ //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type, title); - } - diff --git a/Spigot-Server-Patches/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/Spigot-Server-Patches/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch deleted file mode 100644 index d207708d6b..0000000000 --- a/Spigot-Server-Patches/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 18 Aug 2018 12:43:16 -0400 -Subject: [PATCH] Restore vanlla default mob-spawn-range and water animals - limit - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -0,0 +0,0 @@ public class SpigotWorldConfig - public byte mobSpawnRange; - private void mobSpawnRange() - { -- mobSpawnRange = (byte) getInt( "mob-spawn-range", 6 ); -+ mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla - log( "Mob Spawn Range: " + mobSpawnRange ); - } - -diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/configurations/bukkit.yml -+++ b/src/main/resources/configurations/bukkit.yml -@@ -0,0 +0,0 @@ settings: - spawn-limits: - monsters: 70 - animals: 10 -- water-animals: 15 -+ water-animals: 5 - water-ambient: 20 - ambient: 15 - chunk-gc: diff --git a/Spigot-Server-Patches/Restrict-vanilla-teleport-command-to-valid-locations.patch b/Spigot-Server-Patches/Restrict-vanilla-teleport-command-to-valid-locations.patch deleted file mode 100644 index 601d05da00..0000000000 --- a/Spigot-Server-Patches/Restrict-vanilla-teleport-command-to-valid-locations.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Thu, 16 Apr 2020 20:07:29 -0500 -Subject: [PATCH] Restrict vanilla teleport command to valid locations - -Fixes GH-3165, GH-3575 - -diff --git a/src/main/java/net/minecraft/server/commands/CommandTeleport.java b/src/main/java/net/minecraft/server/commands/CommandTeleport.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandTeleport.java -+++ b/src/main/java/net/minecraft/server/commands/CommandTeleport.java -@@ -0,0 +0,0 @@ public class CommandTeleport { - - private static void a(CommandListenerWrapper commandlistenerwrapper, Entity entity, WorldServer worldserver, double d0, double d1, double d2, Set set, float f, float f1, @Nullable CommandTeleport.a commandteleport_a) throws CommandSyntaxException { - BlockPosition blockposition = new BlockPosition(d0, d1, d2); -+ // Paper start - Don't allow teleport command to invalid locations -+ if (d0 <= -30000000 || d2 <= -30000000 || d0 > 30000000 || d2 > 30000000 || d1 > 30000000 || d1 <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation -+ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + entity.getName() + " to " + d0 + ", " + d1 + ", " + d2); -+ return; -+ } -+ // Paper end - - if (!World.l(blockposition)) { - throw CommandTeleport.a.create(); diff --git a/Spigot-Server-Patches/Retain-block-place-order-when-capturing-blockstates.patch b/Spigot-Server-Patches/Retain-block-place-order-when-capturing-blockstates.patch deleted file mode 100644 index 6f630fcbf8..0000000000 --- a/Spigot-Server-Patches/Retain-block-place-order-when-capturing-blockstates.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Fri, 7 Aug 2020 04:27:56 -0700 -Subject: [PATCH] Retain block place order when capturing blockstates - -Fixes twisted vines not connecting properly when grown via -bonemeal by a player. - -In general, look at making this logic more robust (i.e properly handling -cases where a captured entry is overriden) - but for now this will do. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; - public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper -- public Map capturedTileEntities = new HashMap<>(); -+ public Map capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - public List captureDrops; - public long ticksPerAnimalSpawns; - public long ticksPerMonsterSpawns; diff --git a/Spigot-Server-Patches/Return-chat-component-with-empty-text-instead-of-thr.patch b/Spigot-Server-Patches/Return-chat-component-with-empty-text-instead-of-thr.patch deleted file mode 100644 index 507823c09a..0000000000 --- a/Spigot-Server-Patches/Return-chat-component-with-empty-text-instead-of-thr.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: CDFN -Date: Tue, 7 Jul 2020 17:53:23 +0200 -Subject: [PATCH] Return chat component with empty text instead of throwing - exception - - -diff --git a/src/main/java/net/minecraft/world/inventory/Container.java b/src/main/java/net/minecraft/world/inventory/Container.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/inventory/Container.java -+++ b/src/main/java/net/minecraft/world/inventory/Container.java -@@ -0,0 +0,0 @@ import net.minecraft.CrashReportSystemDetails; - import net.minecraft.ReportedException; - import net.minecraft.core.IRegistry; - import net.minecraft.core.NonNullList; -+import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.IInventory; -@@ -0,0 +0,0 @@ public abstract class Container { - } - private IChatBaseComponent title; - public final IChatBaseComponent getTitle() { -- Preconditions.checkState(this.title != null, "Title not set"); -+ // Paper start - return chat component with empty text instead of throwing error -+ // Preconditions.checkState(this.title != null, "Title not set"); -+ if(this.title == null){ -+ return new ChatComponentText(""); -+ } -+ // Paper end - return this.title; - } - public final void setTitle(IChatBaseComponent title) { diff --git a/Spigot-Server-Patches/Sanitise-RegionFileCache-and-make-configurable.patch b/Spigot-Server-Patches/Sanitise-RegionFileCache-and-make-configurable.patch deleted file mode 100644 index 1b718e4453..0000000000 --- a/Spigot-Server-Patches/Sanitise-RegionFileCache-and-make-configurable.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Antony Riley -Date: Tue, 29 Mar 2016 08:22:55 +0300 -Subject: [PATCH] Sanitise RegionFileCache and make configurable. - -RegionFileCache prior to this patch would close every single open region -file upon reaching a size of 256. -This patch modifies that behaviour so it closes the the least recently -used RegionFile. -The implementation uses a LinkedHashMap as an LRU cache (modified from HashMap). -The maximum size of the RegionFileCache is also made configurable. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ public class PaperConfig { - private static void loadPermsBeforePlugins() { - loadPermsBeforePlugins = getBoolean("settings.load-permissions-yml-before-plugins", true); - } -+ -+ public static int regionFileCacheSize = 256; -+ private static void regionFileCacheSize() { -+ regionFileCacheSize = Math.max(getInt("settings.region-file-cache-size", 256), 4); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileCache.java -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { - if (regionfile != null) { - return regionfile; - } else { -- if (this.cache.size() >= 256) { -+ if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable - ((RegionFile) this.cache.removeLast()).close(); - } - diff --git a/Spigot-Server-Patches/Seed-based-feature-search.patch b/Spigot-Server-Patches/Seed-based-feature-search.patch deleted file mode 100644 index 86c56c8bc2..0000000000 --- a/Spigot-Server-Patches/Seed-based-feature-search.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Phoenix616 -Date: Mon, 13 Jan 2020 15:40:32 +0100 -Subject: [PATCH] Seed based feature search - -This tries to work around the issue where the server will load -surrounding chunks up to a radius of 100 chunks in order to search for -features e.g. when running the /locate command or for treasure maps -(issue #2312). -This is done by backporting Mojang's change in 1.17 which makes it so -that the biome (generated by the seed) is checked first if the feature -can be generated before actually to load the chunk. - -Additionally to that the center location of the target chunk is simply -returned if the chunk is not loaded to avoid the sync chunk load. -As this can lead to less precise locations a toggle is provided to -enable the sync loading of the target chunk again. - -The main downside of this is that it breaks once the seed or generator -changes but this should usually not happen. A config option to disable -this completely is added though in case that should ever be necessary. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - } - } - -+ public boolean seedBasedFeatureSearch = true; -+ public boolean seedBasedFeatureSearchLoadsChunks = false; -+ private void seedBasedFeatureSearch() { -+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch); -+ seedBasedFeatureSearchLoadsChunks = getBoolean("seed-based-feature-search-loads-chunks", seedBasedFeatureSearchLoadsChunks); -+ log("Feature search is based on seed: " + seedBasedFeatureSearch + ", loads chunks:" + seedBasedFeatureSearchLoadsChunks); -+ } -+ - public int maxCollisionsPerEntity; - private void maxEntityCollision() { - maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); -diff --git a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -+++ b/src/main/java/net/minecraft/world/level/ChunkCoordIntPair.java -@@ -0,0 +0,0 @@ public class ChunkCoordIntPair { - } - } - -+ public int getBlockX() { return d(); } // Paper - OBFHELPER - public int d() { - return this.x << 4; - } - -+ public int getBlockZ() { return e(); } // Paper - OBFHELPER - public int e() { - return this.z << 4; - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return this.methodProfiler; - } - -- @Override -- public BiomeManager d() { -+ public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER -+ @Override public BiomeManager d() { - return this.biomeManager; - } - -diff --git a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -+++ b/src/main/java/net/minecraft/world/level/biome/BiomeManager.java -@@ -0,0 +0,0 @@ public class BiomeManager { - return new BiomeManager(worldchunkmanager, this.b, this.c); - } - -+ public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER - public BiomeBase a(BlockPosition blockposition) { - return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a); - } -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureGenerator.java -@@ -0,0 +0,0 @@ public abstract class StructureGenerator - int j2 = i1 + k * l1; - ChunkCoordIntPair chunkcoordintpair = this.a(structuresettingsfeature, j, seededrandom, i2, j2); - if (!iworldreader.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper -- IChunkAccess ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ // Paper start - seed based feature search -+ IChunkAccess ichunkaccess = null; -+ if (structuremanager.getWorld().paperConfig.seedBasedFeatureSearch) { -+ BiomeBase biomeBase = structuremanager.getWorld().getBiomeManager().getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9)); -+ if (!biomeBase.e().a(this)) { -+ continue; -+ } -+ if (!structuremanager.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { -+ ichunkaccess = structuremanager.getWorld().getChunkIfLoaded(chunkcoordintpair.x, chunkcoordintpair.z); -+ if (ichunkaccess == null) { -+ return chunkcoordintpair.asPosition().add(8, blockposition.getY(), 8); -+ } -+ } -+ } -+ if (ichunkaccess == null) { -+ ichunkaccess = iworldreader.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS); -+ } -+ // Paper end - StructureStart structurestart = structuremanager.a(SectionPosition.a(ichunkaccess.getPos(), 0), this, ichunkaccess); - - if (structurestart != null && structurestart.e()) { diff --git a/Spigot-Server-Patches/Send-absolute-position-the-first-time-an-entity-is-s.patch b/Spigot-Server-Patches/Send-absolute-position-the-first-time-an-entity-is-s.patch deleted file mode 100644 index 232fae6f72..0000000000 --- a/Spigot-Server-Patches/Send-absolute-position-the-first-time-an-entity-is-s.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -Date: Wed, 2 Mar 2016 23:13:07 -0600 -Subject: [PATCH] Send absolute position the first time an entity is seen - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -0,0 +0,0 @@ import com.google.common.collect.Lists; - import com.mojang.datafixers.util.Pair; - import java.util.Collection; - import java.util.Collections; -+import java.util.HashSet; - import java.util.Iterator; - import java.util.List; - import java.util.Set; -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - private final Entity tracker; - private final int d; - private final boolean e; -- private final Consumer> f; -+ private final Consumer> f; private Consumer> getPacketConsumer() { return f; } // Paper - OBFHELPER - private long xLoc; - private long yLoc; - private long zLoc; -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - private boolean r; - // CraftBukkit start - private final Set trackedPlayers; -+ // Paper start -+ private java.util.Map trackedPlayerMap = null; -+ -+ /** -+ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets -+ */ -+ public void sendPlayerPacket(EntityPlayer player, Packet packet) { -+ player.playerConnection.sendPacket(packet); -+ } -+ -+ public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, java.util.Map trackedPlayers) { -+ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet()); -+ trackedPlayerMap = trackedPlayers; -+ } - - public EntityTrackerEntry(WorldServer worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { -+ // Paper end - this.trackedPlayers = trackedPlayers; - // CraftBukkit end - this.m = Vec3D.ORIGIN; -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - } - - if (packet1 != null) { -- this.f.accept(packet1); -+ // paper start -+ if (trackedPlayerMap == null || packet1 instanceof PacketPlayOutEntityTeleport) { -+ this.f.accept((packet1)); -+ } else { -+ PacketPlayOutEntityTeleport teleportPacket = null; -+ -+ for (java.util.Map.Entry viewer : trackedPlayerMap.entrySet()) { -+ if (viewer.getValue()) { -+ viewer.setValue(false); -+ if (teleportPacket == null) { -+ teleportPacket = new PacketPlayOutEntityTeleport(this.tracker); -+ } -+ sendPlayerPacket(viewer.getKey(), teleportPacket); -+ } else { -+ sendPlayerPacket(viewer.getKey(), packet1); -+ } -+ } -+ } -+ // Paper end - } - - this.c(); -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - private final Entity tracker; - private final int trackingDistance; - private SectionPosition e; -- public final Set trackedPlayers = Sets.newHashSet(); -+ // Paper start -+ // Replace trackedPlayers Set with a Map. The value is true until the player receives -+ // their first update (which is forced to have absolute coordinates), false afterward. -+ public java.util.Map trackedPlayerMap = new java.util.HashMap<>(); -+ public Set trackedPlayers = trackedPlayerMap.keySet(); - - public EntityTracker(Entity entity, int i, int j, boolean flag) { -- this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayers); // CraftBukkit -+ this.trackerEntry = new EntityTrackerEntry(PlayerChunkMap.this.world, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper - this.tracker = entity; - this.trackingDistance = i; - this.e = SectionPosition.a(entity); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId())); - // CraftBukkit end - -- if (flag1 && this.trackedPlayers.add(entityplayer)) { -+ if (flag1 && this.trackedPlayerMap.putIfAbsent(entityplayer, true) == null) { // Paper - this.trackerEntry.b(entityplayer); - } - } else if (this.trackedPlayers.remove(entityplayer)) { diff --git a/Spigot-Server-Patches/Send-attack-SoundEffects-only-to-players-who-can-see.patch b/Spigot-Server-Patches/Send-attack-SoundEffects-only-to-players-who-can-see.patch deleted file mode 100644 index fd0750db39..0000000000 --- a/Spigot-Server-Patches/Send-attack-SoundEffects-only-to-players-who-can-see.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Brokkonaut -Date: Tue, 31 Oct 2017 03:26:18 +0100 -Subject: [PATCH] Send attack SoundEffects only to players who can see the - attacker - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ import net.minecraft.network.chat.ChatMessage; - import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.chat.IChatMutableComponent; - import net.minecraft.network.protocol.game.PacketPlayOutEntityVelocity; -+import net.minecraft.network.protocol.game.PacketPlayOutNamedSoundEffect; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - int i = b0 + EnchantmentManager.b((EntityLiving) this); - - if (this.isSprinting() && flag) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_KNOCKBACK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - ++i; - flag1 = true; - } -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - } - } - -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_SWEEP, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.ex(); - } - -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - } - - if (flag2) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_CRIT, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - this.a(entity); - } - - if (!flag2 && !flag3) { - if (flag) { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_STRONG, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - } else { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_WEAK, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - } - } - -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - - this.applyExhaustion(world.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value - } else { -- this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); -+ sendSoundEffect(this, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_PLAYER_ATTACK_NODAMAGE, this.getSoundCategory(), 1.0F, 1.0F); // Paper - send while respecting visibility - if (flag4) { - entity.extinguish(); - } -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - public int getExpToLevel() { - return this.expLevel >= 30 ? 112 + (this.expLevel - 30) * 9 : (this.expLevel >= 15 ? 37 + (this.expLevel - 15) * 5 : 7 + this.expLevel * 2); - } -+ // Paper start - send SoundEffect to everyone who can see fromEntity -+ private static void sendSoundEffect(EntityHuman fromEntity, double x, double y, double z, SoundEffect soundEffect, SoundCategory soundCategory, float volume, float pitch) { -+ fromEntity.world.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself -+ if (fromEntity instanceof EntityPlayer) { -+ ((EntityPlayer) fromEntity).playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(soundEffect, soundCategory, x, y, z, volume, pitch)); -+ } -+ } -+ // Paper end - - // CraftBukkit start - public void applyExhaustion(float f) { diff --git a/Spigot-Server-Patches/Send-empty-commands-if-tab-completion-is-disabled.patch b/Spigot-Server-Patches/Send-empty-commands-if-tab-completion-is-disabled.patch deleted file mode 100644 index 8360f60660..0000000000 --- a/Spigot-Server-Patches/Send-empty-commands-if-tab-completion-is-disabled.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Mon, 26 Apr 2021 01:27:08 +0100 -Subject: [PATCH] Send empty commands if tab completion is disabled - - -diff --git a/src/main/java/net/minecraft/commands/CommandDispatcher.java b/src/main/java/net/minecraft/commands/CommandDispatcher.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CommandDispatcher.java -+++ b/src/main/java/net/minecraft/commands/CommandDispatcher.java -@@ -0,0 +0,0 @@ public class CommandDispatcher { - } - - public void a(EntityPlayer entityplayer) { -- if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) return; // Spigot -+ // Paper start - Send empty commands if tab completion is disabled -+ if ( org.spigotmc.SpigotConfig.tabComplete < 0 ) { //return; // Spigot -+ entityplayer.playerConnection.sendPacket(new PacketPlayOutCommands(new RootCommandNode<>())); -+ return; -+ } -+ // Paper end - // CraftBukkit start - // Register Vanilla commands into builtRoot as before - // Paper start - Async command map building diff --git a/Spigot-Server-Patches/Server-Tick-Events.patch b/Spigot-Server-Patches/Server-Tick-Events.patch deleted file mode 100644 index 52c96c6ddd..0000000000 --- a/Spigot-Server-Patches/Server-Tick-Events.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 27 Mar 2019 22:48:45 -0400 -Subject: [PATCH] Server Tick Events - -Fires event at start and end of a server tick - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Mon, 4 Mar 2019 02:23:28 -0500 -Subject: [PATCH] Set Zombie last tick at start of drowning process - -Fixes GH-1887 - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - ++this.bt; - if (this.bt >= 600) { - this.startDrownedConversion(300); -+ this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 - } - } else { - this.bt = -1; diff --git a/Spigot-Server-Patches/Set-area-affect-cloud-rotation.patch b/Spigot-Server-Patches/Set-area-affect-cloud-rotation.patch deleted file mode 100644 index 717dcc3a49..0000000000 --- a/Spigot-Server-Patches/Set-area-affect-cloud-rotation.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> -Date: Mon, 5 Apr 2021 16:58:20 -0400 -Subject: [PATCH] Set area affect cloud rotation - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - entity = EntityTypes.LIGHTNING_BOLT.a(world); - } else if (AreaEffectCloud.class.isAssignableFrom(clazz)) { - entity = new EntityAreaEffectCloud(world, x, y, z); -+ entity.setPositionRotation(x, y, z, yaw, pitch); // Paper - Set area effect cloud Rotation - } else if (EvokerFangs.class.isAssignableFrom(clazz)) { - entity = new EntityEvokerFangs(world, x, y, z, (float) Math.toRadians(yaw), 0, null); - } diff --git a/Spigot-Server-Patches/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/Spigot-Server-Patches/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch deleted file mode 100644 index 86f387b8e6..0000000000 --- a/Spigot-Server-Patches/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 4 May 2020 01:08:56 -0400 -Subject: [PATCH] Set cap on JDK per-thread native byte buffer cache - -See: https://www.evanjones.ca/java-bytebuffer-leak.html - -This is potentially a source of lots of native memory usage. - -We are clearly seeing native usage upwards to 1-4GB which doesn't make sense. - -Region File usage fixed in previous patch should of tecnically only been somewhat -temporary until GC finally gets it some time later, but between all the various -plugins doing IO on various threads, this hidden detail of the JDK could be -keeping long lived large direct buffers in cache. - -Set system properly at server startup if not set already to help protect from this. - -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - } - // Paper end - // Todo: Installation script -+ if (System.getProperty("jdk.nio.maxCachedBufferSize") == null) System.setProperty("jdk.nio.maxCachedBufferSize", "262144"); // Paper - cap per-thread NIO cache size - OptionParser parser = new OptionParser() { - { - acceptsAll(asList("?", "help"), "Show the help"); diff --git a/Spigot-Server-Patches/Set-spigots-verbose-world-setting-to-false-by-def.patch b/Spigot-Server-Patches/Set-spigots-verbose-world-setting-to-false-by-def.patch deleted file mode 100644 index ebcfd3f143..0000000000 --- a/Spigot-Server-Patches/Set-spigots-verbose-world-setting-to-false-by-def.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 2 Dec 2020 20:17:54 -0800 -Subject: [PATCH] Set spigots verbose world setting to false by def - - -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -0,0 +0,0 @@ public class SpigotWorldConfig - - public void init() - { -- this.verbose = getBoolean( "verbose", true ); -+ this.verbose = getBoolean( "verbose", false ); // Paper - - log( "-------- World Settings For [" + worldName + "] --------" ); - SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/Spigot-Server-Patches/Shoulder-Entities-Release-API.patch b/Spigot-Server-Patches/Shoulder-Entities-Release-API.patch deleted file mode 100644 index 4b864860b3..0000000000 --- a/Spigot-Server-Patches/Shoulder-Entities-Release-API.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 17 Jun 2017 15:18:30 -0400 -Subject: [PATCH] Shoulder Entities Release API - - -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - - } - -+ // Paper start -+ public Entity releaseLeftShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); -+ if (entity != null) { -+ this.setShoulderEntityLeft(new NBTTagCompound()); -+ } -+ return entity; -+ } -+ -+ public Entity releaseRightShoulderEntity() { -+ Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); -+ if (entity != null) { -+ this.setShoulderEntityRight(new NBTTagCompound()); -+ } -+ return entity; -+ } -+ // Paper - maintain old signature - private boolean spawnEntityFromShoulder(NBTTagCompound nbttagcompound) { // CraftBukkit void->boolean -- if (!this.world.isClientSide && !nbttagcompound.isEmpty()) { -+ return spawnEntityFromShoulder0(nbttagcompound) != null; -+ } -+ -+ // Paper - return entity -+ private Entity spawnEntityFromShoulder0(@Nullable NBTTagCompound nbttagcompound) { -+ if (!this.world.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { - return EntityTypes.a(nbttagcompound, this.world).map((entity) -> { // CraftBukkit - if (entity instanceof EntityTameableAnimal) { - ((EntityTameableAnimal) entity).setOwnerUUID(this.uniqueID); - } - - entity.setPosition(this.locX(), this.locY() + 0.699999988079071D, this.locZ()); -- return ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -- }).orElse(true); // CraftBukkit -+ boolean addedToWorld = ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit -+ return addedToWorld ? entity : null; -+ }).orElse(null); // CraftBukkit // Paper - false -> null - } - -- return true; // CraftBukkit -+ return null; // Paper - return null - } -+ // Paper end - - @Override - public abstract boolean isSpectator(); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - getHandle().getCooldownTracker().setCooldown(CraftMagicNumbers.getItem(material), ticks); - } - -+ // Paper start -+ @Override -+ public org.bukkit.entity.Entity releaseLeftShoulderEntity() { -+ if (!getHandle().getShoulderEntityLeft().isEmpty()) { -+ Entity entity = getHandle().releaseLeftShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public org.bukkit.entity.Entity releaseRightShoulderEntity() { -+ if (!getHandle().getShoulderEntityRight().isEmpty()) { -+ Entity entity = getHandle().releaseRightShoulderEntity(); -+ if (entity != null) { -+ return entity.getBukkitEntity(); -+ } -+ } -+ -+ return null; -+ } -+ // Paper end -+ - @Override - public boolean discoverRecipe(NamespacedKey recipe) { - return discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/Spigot-Server-Patches/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/Spigot-Server-Patches/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch deleted file mode 100644 index fd7ae88eac..0000000000 --- a/Spigot-Server-Patches/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Tue, 1 Mar 2016 14:32:43 -0600 -Subject: [PATCH] Show 'Paper' in client crashes, server lists, and Mojang - stats - - -diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/EULA.java -+++ b/src/main/java/net/minecraft/server/EULA.java -@@ -0,0 +0,0 @@ public class EULA { - Properties properties = new Properties(); - - properties.setProperty("eula", "false"); -- properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula)."); -+ properties.store(outputstream, "By changing the setting below to TRUE you are indicating your agreement to our EULA (https://account.mojang.com/documents/minecraft_eula).\nYou also agree that tacos are tasty, and the best food in the world."); // Paper - fix lag; - } catch (Throwable throwable1) { - throwable = throwable1; - throw throwable1; -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant // CraftBukkit - cb > vanilla! -+ return "Paper"; //Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! - } - - public CrashReport b(CrashReport crashreport) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; - import net.md_5.bungee.api.chat.BaseComponent; // Spigot - - public final class CraftServer implements Server { -- private final String serverName = "CraftBukkit"; -+ private final String serverName = "Paper"; // Paper - private final String serverVersion; - private final String bukkitVersion = Versioning.getBukkitVersion(); - private final Logger logger = Logger.getLogger("Minecraft"); -diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Main.java -+++ b/src/main/java/org/bukkit/craftbukkit/Main.java -@@ -0,0 +0,0 @@ public class Main { - deadline.add(Calendar.DAY_OF_YEAR, -28); - if (buildDate.before(deadline.getTime())) { - System.err.println("*** Error, this build is outdated ***"); -- System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***"); -+ System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads ***"); // Paper - System.err.println("*** Server will start in 20 seconds ***"); - Thread.sleep(TimeUnit.SECONDS.toMillis(20)); - } - } - -+ // Paper start - Log Java and OS versioning to help with debugging plugin issues -+ java.lang.management.RuntimeMXBean runtimeMX = java.lang.management.ManagementFactory.getRuntimeMXBean(); -+ java.lang.management.OperatingSystemMXBean osMX = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); -+ if (runtimeMX != null && osMX != null) { -+ String javaInfo = "Java " + runtimeMX.getSpecVersion() + " (" + runtimeMX.getVmName() + " " + runtimeMX.getVmVersion() + ")"; -+ String osInfo = "Host: " + osMX.getName() + " " + osMX.getVersion() + " (" + osMX.getArch() + ")"; -+ -+ System.out.println("System Info: " + javaInfo + " " + osInfo); -+ } else { -+ System.out.println("Unable to read system info"); -+ } -+ // Paper end -+ - System.out.println("Loading libraries, please wait..."); - net.minecraft.server.Main.main(options); - } catch (Throwable t) { -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - - private WatchdogThread(long timeoutTime, boolean restart) - { -- super( "Spigot Watchdog Thread" ); -+ super( "Paper Watchdog Thread" ); - this.timeoutTime = timeoutTime; - this.restart = restart; - } -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Spigot bug." ); -+ log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper - log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" ); - log.log( Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring" ); - log.log( Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once" ); - log.log( Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes" ); -- log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); -+ log.log( Level.SEVERE, "If you are unsure or still think this is a Paper bug, please report this to https://github.com/PaperMC/Paper/issues" ); - log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); -- log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); -+ log.log( Level.SEVERE, "Paper version: " + Bukkit.getServer().getVersion() ); - // - if ( net.minecraft.world.level.World.lastPhysicsProblem != null ) - { -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - } - // - log.log( Level.SEVERE, "------------------------------" ); -- log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); -+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // diff --git a/Spigot-Server-Patches/Show-blockstate-location-if-we-failed-to-read-it.patch b/Spigot-Server-Patches/Show-blockstate-location-if-we-failed-to-read-it.patch deleted file mode 100644 index ad3c24e902..0000000000 --- a/Spigot-Server-Patches/Show-blockstate-location-if-we-failed-to-read-it.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 15 Jun 2019 10:28:25 -0700 -Subject: [PATCH] Show blockstate location if we failed to read it - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockState - public CraftBlockEntityState(Block block, Class tileEntityClass) { - super(block); - -+ try {// Paper - show location on failure -+ - this.tileEntityClass = tileEntityClass; - - // get tile entity from block: -@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockState - this.load(this.snapshot); - } - // Paper end -+ // Paper start - show location on failure -+ } catch (Throwable thr) { -+ if (thr instanceof ThreadDeath) { -+ throw (ThreadDeath)thr; -+ } -+ throw new RuntimeException("Failed to read BlockState at: world: " + block.getWorld().getName() + " location: (" + block.getX() + ", " + block.getY() + ", " + block.getZ() + ")", thr); -+ } -+ // Paper end - } - - public final boolean snapshotDisabled; // Paper diff --git a/Spigot-Server-Patches/Significantly-improve-performance-of-the-end-generat.patch b/Spigot-Server-Patches/Significantly-improve-performance-of-the-end-generat.patch deleted file mode 100644 index eed9579a8e..0000000000 --- a/Spigot-Server-Patches/Significantly-improve-performance-of-the-end-generat.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com> -Date: Tue, 3 Nov 2020 23:48:05 -0600 -Subject: [PATCH] Significantly improve performance of the end generation - -This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement. - -Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric) - -Co-authored-by: Gegy -Co-authored-by: Dylan Xaldin -Co-authored-by: pop4959 - -diff --git a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -+++ b/src/main/java/net/minecraft/world/level/biome/WorldChunkManagerTheEnd.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.biome; - import com.google.common.collect.ImmutableList; - import com.mojang.serialization.Codec; - import com.mojang.serialization.codecs.RecordCodecBuilder; -+import it.unimi.dsi.fastutil.HashCommon; // Paper - import java.util.List; - import net.minecraft.core.IRegistry; - import net.minecraft.resources.RegistryLookupCodec; - import net.minecraft.util.MathHelper; -+import net.minecraft.world.level.ChunkCoordIntPair; - import net.minecraft.world.level.levelgen.SeededRandom; - import net.minecraft.world.level.levelgen.synth.NoiseGenerator3Handler; - -@@ -0,0 +0,0 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - private final BiomeBase k; - private final BiomeBase l; - private final BiomeBase m; -+ // Paper start -+ private static final class NoiseCache { -+ public long[] keys = new long[8192]; -+ public float[] values = new float[8192]; -+ public NoiseCache() { -+ java.util.Arrays.fill(keys, Long.MIN_VALUE); -+ } -+ } -+ private static final ThreadLocal> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new); -+ // Paper end - - public WorldChunkManagerTheEnd(IRegistry iregistry, long i) { - this(iregistry, i, (BiomeBase) iregistry.d(Biomes.THE_END), (BiomeBase) iregistry.d(Biomes.END_HIGHLANDS), (BiomeBase) iregistry.d(Biomes.END_MIDLANDS), (BiomeBase) iregistry.d(Biomes.SMALL_END_ISLANDS), (BiomeBase) iregistry.d(Biomes.END_BARRENS)); -@@ -0,0 +0,0 @@ public class WorldChunkManagerTheEnd extends WorldChunkManager { - - f = MathHelper.a(f, -100.0F, 80.0F); - -+ NoiseCache cache = noiseCache.get().computeIfAbsent(noisegenerator3handler, m -> new NoiseCache()); // Paper - for (int k1 = -12; k1 <= 12; ++k1) { - for (int l1 = -12; l1 <= 12; ++l1) { - long i2 = (long) (k + k1); - long j2 = (long) (l + l1); - -- if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { -- float f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; -+ // Paper start - Significantly improve end generation performance by using a noise cache -+ long key = ChunkCoordIntPair.pair((int) i2, (int) j2); -+ int index = (int) HashCommon.mix(key) & 8191; -+ float f1 = Float.MIN_VALUE; -+ if (cache.keys[index] == key) { -+ f1 = cache.values[index]; -+ } else { -+ if (i2 * i2 + j2 * j2 > 4096L && noisegenerator3handler.a((double) i2, (double) j2) < -0.8999999761581421D) { -+ f1 = (MathHelper.e((float) i2) * 3439.0F + MathHelper.e((float) j2) * 147.0F) % 13.0F + 9.0F; -+ } -+ cache.keys[index] = key; -+ cache.values[index] = f1; -+ } -+ if (f1 != Float.MIN_VALUE) { -+ // Paper end - float f2 = (float) (i1 - k1 * 2); - float f3 = (float) (j1 - l1 * 2); - float f4 = 100.0F - MathHelper.c(f2 * f2 + f3 * f3) * f1; diff --git a/Spigot-Server-Patches/SkeletonHorse-Additions.patch b/Spigot-Server-Patches/SkeletonHorse-Additions.patch deleted file mode 100644 index bccabc357b..0000000000 --- a/Spigot-Server-Patches/SkeletonHorse-Additions.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 27 Jul 2018 22:36:31 -0500 -Subject: [PATCH] SkeletonHorse Additions - - -diff --git a/src/main/java/net/minecraft/world/entity/IEntitySelector.java b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/IEntitySelector.java -+++ b/src/main/java/net/minecraft/world/entity/IEntitySelector.java -@@ -0,0 +0,0 @@ public final class IEntitySelector { - public static final Predicate f = (entity) -> { - return !(entity instanceof EntityHuman) || !entity.isSpectator() && !((EntityHuman) entity).isCreative() && entity.world.getDifficulty() != EnumDifficulty.PEACEFUL; - }; -+ public static Predicate notSpectator() { return g; } // Paper - OBFHELPER - public static final Predicate g = (entity) -> { - return !entity.isSpectator(); - }; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseSkeleton.java -@@ -0,0 +0,0 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - - private final PathfinderGoalHorseTrap bw = new PathfinderGoalHorseTrap(this); - private boolean bx; -- private int by; -+ private int by; public int getTrapTime() { return this.by; } // Paper - OBFHELPER - - public EntityHorseSkeleton(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityHorseSkeleton extends EntityHorseAbstract { - return 0.96F; - } - -+ public boolean isTrap() { return this.eM(); } // Paper - OBFHELPER - public boolean eM() { - return this.bx; - } - -+ public void setTrap(boolean trap) { this.t(trap); } // Paper - OBFHELPER - public void t(boolean flag) { - if (flag != this.bx) { - this.bx = flag; -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/PathfinderGoalHorseTrap.java -@@ -0,0 +0,0 @@ import net.minecraft.world.item.Items; - import net.minecraft.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.level.World; - -+import org.bukkit.entity.HumanEntity; -+ -+import java.util.List; -+ - public class PathfinderGoalHorseTrap extends PathfinderGoal { - - private final EntityHorseSkeleton a; -+ private List eligiblePlayers; // Paper - - public PathfinderGoalHorseTrap(EntityHorseSkeleton entityhorseskeleton) { - this.a = entityhorseskeleton; -@@ -0,0 +0,0 @@ public class PathfinderGoalHorseTrap extends PathfinderGoal { - - @Override - public boolean a() { -- return this.a.world.isPlayerNearby(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D); -+ return !(eligiblePlayers = this.a.world.findNearbyBukkitPlayers(this.a.locX(), this.a.locY(), this.a.locZ(), 10.0D, false)).isEmpty(); // Paper - } - - @Override - public void e() { - WorldServer worldserver = (WorldServer) this.a.world; -+ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.a.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper - DifficultyDamageScaler difficultydamagescaler = worldserver.getDamageScaler(this.a.getChunkCoordinates()); - - this.a.t(false); -diff --git a/src/main/java/net/minecraft/world/level/IEntityAccess.java b/src/main/java/net/minecraft/world/level/IEntityAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/IEntityAccess.java -+++ b/src/main/java/net/minecraft/world/level/IEntityAccess.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level; - -+import com.google.common.collect.ImmutableList; - import com.google.common.collect.Lists; -+import org.bukkit.entity.HumanEntity; -+ - import java.util.Iterator; - import java.util.List; - import java.util.UUID; -@@ -0,0 +0,0 @@ public interface IEntityAccess { - return entityhuman; - } - -+ // Paper start -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { -+ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? IEntitySelector.notSpectator() : IEntitySelector.canAITarget()); -+ } -+ -+ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { -+ ImmutableList.Builder builder = ImmutableList.builder(); -+ -+ for (EntityHuman human : this.getPlayers()) { -+ if (predicate == null || predicate.test(human)) { -+ double distanceSquared = human.getDistanceSquared(x, y, z); -+ -+ if (radius < 0.0D || distanceSquared < radius * radius) { -+ builder.add(human.getBukkitEntity()); -+ } -+ } -+ } -+ -+ return builder.build(); -+ } -+ // Paper end -+ - @Nullable - default EntityHuman findNearbyPlayer(Entity entity, double d0) { - return this.a(entity.locX(), entity.locY(), entity.locZ(), d0, false); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -@@ -0,0 +0,0 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo - public Variant getVariant() { - return Variant.SKELETON_HORSE; - } -+ -+ // Paper start -+ @Override -+ public EntityHorseSkeleton getHandle() { -+ return (EntityHorseSkeleton) super.getHandle(); -+ } -+ -+ @Override -+ public int getTrapTime() { -+ return getHandle().getTrapTime(); -+ } -+ -+ @Override -+ public boolean isTrap() { -+ return getHandle().isTrap(); -+ } -+ -+ @Override -+ public void setTrap(boolean trap) { -+ getHandle().setTrap(trap); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Skip-distance-map-update-when-spawning-disabled.patch b/Spigot-Server-Patches/Skip-distance-map-update-when-spawning-disabled.patch deleted file mode 100644 index 65512c9a1e..0000000000 --- a/Spigot-Server-Patches/Skip-distance-map-update-when-spawning-disabled.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Beech Horn -Date: Fri, 14 Feb 2020 19:39:59 +0000 -Subject: [PATCH] Skip distance map update when spawning disabled. - - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - int l = this.chunkMapDistance.b(); - // Paper start - per player mob spawning - SpawnerCreature.d spawnercreature_d; // moved down -- if (this.playerChunkMap.playerMobDistanceMap != null) { -+ if ((this.allowAnimals || this.allowMonsters) && this.playerChunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled - // update distance map - this.world.timings.playerMobDistanceMapUpdate.startTiming(); - this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); diff --git a/Spigot-Server-Patches/Slime-Pathfinder-Events.patch b/Spigot-Server-Patches/Slime-Pathfinder-Events.patch deleted file mode 100644 index bc814678df..0000000000 --- a/Spigot-Server-Patches/Slime-Pathfinder-Events.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Fri, 24 Aug 2018 08:18:42 -0500 -Subject: [PATCH] Slime Pathfinder Events - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntitySlime.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.SeededRandom; - import net.minecraft.world.level.storage.loot.LootTables; - import net.minecraft.world.phys.Vec3D; - -+// Paper start -+import com.destroystokyo.paper.event.entity.SlimeChangeDirectionEvent; -+import com.destroystokyo.paper.event.entity.SlimeSwimEvent; -+import com.destroystokyo.paper.event.entity.SlimeTargetLivingEntityEvent; -+import com.destroystokyo.paper.event.entity.SlimeWanderEvent; -+import org.bukkit.entity.LivingEntity; -+import org.bukkit.entity.Slime; -+// Paper end - // CraftBukkit start - import java.util.ArrayList; - import java.util.List; -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - @Override - public void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -+ nbttagcompound.setBoolean("Paper.canWander", this.canWander); // Paper - nbttagcompound.setInt("Size", this.getSize() - 1); - nbttagcompound.setBoolean("wasOnGround", this.bp); - } -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - this.setSize(i + 1, false); - super.loadData(nbttagcompound); -+ // Paper start - check exists before loading or this will be loaded as false -+ if (nbttagcompound.hasKey("Paper.canWander")) { -+ this.canWander = nbttagcompound.getBoolean("Paper.canWander"); -+ } -+ // Paper end - this.bp = nbttagcompound.getBoolean("wasOnGround"); - } - -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return !this.a.isPassenger(); -+ return !this.a.isPassenger() && this.a.canWander && new SlimeWanderEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; -+ return (this.a.isInWater() || this.a.aQ()) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeSwimEvent((Slime) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - - @Override - public boolean a() { -- return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime; -+ return this.a.getGoalTarget() == null && (this.a.onGround || this.a.isInWater() || this.a.aQ() || this.a.hasEffect(MobEffects.LEVITATION)) && this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander; // Paper - add canWander - } - - @Override - public void e() { - if (--this.c <= 0) { - this.c = 40 + this.a.getRandom().nextInt(60); -- this.b = (float) this.a.getRandom().nextInt(360); -+ // Paper start -+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((Slime) this.a.getBukkitEntity(), (float) this.a.getRandom().nextInt(360)); -+ if (!this.a.canWander || !event.callEvent()) return; -+ this.b = event.getNewYaw(); -+ // Paper end - } - - ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.b, false); -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - public boolean a() { - EntityLiving entityliving = this.a.getGoalTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { -+ return false; -+ } -+ return this.a.getControllerMove() instanceof EntitySlime.ControllerMoveSlime && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - public boolean b() { - EntityLiving entityliving = this.a.getGoalTarget(); - -- return entityliving == null ? false : (!entityliving.isAlive() ? false : (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable ? false : --this.b > 0)); -+ // Paper start -+ if (entityliving == null || !entityliving.isAlive()) { -+ return false; -+ } -+ if (entityliving instanceof EntityHuman && ((EntityHuman) entityliving).abilities.isInvulnerable) { -+ return false; -+ } -+ return --this.b > 0 && this.a.canWander && new SlimeTargetLivingEntityEvent((Slime) this.a.getBukkitEntity(), (LivingEntity) entityliving.getBukkitEntity()).callEvent(); -+ // Paper end - } - - @Override -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - this.a.a((Entity) this.a.getGoalTarget(), 10.0F, 10.0F); - ((EntitySlime.ControllerMoveSlime) this.a.getControllerMove()).a(this.a.yaw, this.a.eL()); - } -+ -+ // Paper start - clear timer and target when goal resets -+ public void d() { -+ this.b = 0; -+ this.a.setGoalTarget(null); -+ } -+ // Paper end - } - - static class ControllerMoveSlime extends ControllerMove { -@@ -0,0 +0,0 @@ public class EntitySlime extends EntityInsentient implements IMonster { - } - } - } -+ -+ // Paper start -+ private boolean canWander = true; -+ public boolean canWander() { -+ return canWander; -+ } -+ -+ public void setWander(boolean canWander) { -+ this.canWander = canWander; -+ } -+ // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -0,0 +0,0 @@ public class CraftSlime extends CraftMob implements Slime { - public EntityType getType() { - return EntityType.SLIME; - } -+ -+ // Paper start -+ public boolean canWander() { -+ return getHandle().canWander(); -+ } -+ -+ public void setWander(boolean canWander) { -+ getHandle().setWander(canWander); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Spawn-player-in-correct-world-on-login.patch b/Spigot-Server-Patches/Spawn-player-in-correct-world-on-login.patch deleted file mode 100644 index 1bf01a8259..0000000000 --- a/Spigot-Server-Patches/Spawn-player-in-correct-world-on-login.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Wyatt Childers -Date: Fri, 3 Jul 2020 14:57:05 -0400 -Subject: [PATCH] Spawn player in correct world on login - - -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - }String lastKnownName = s; // Paper - // CraftBukkit end - -- if (nbttagcompound != null) { -+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID. -+ if (nbttagcompound != null && nbttagcompound.hasKey("WorldUUIDMost") && nbttagcompound.hasKey("WorldUUIDLeast")) { -+ UUID uid = new UUID(nbttagcompound.getLong("WorldUUIDMost"), nbttagcompound.getLong("WorldUUIDLeast")); -+ org.bukkit.World bWorld = org.bukkit.Bukkit.getServer().getWorld(uid); -+ if (bWorld != null) { -+ resourcekey = ((CraftWorld) bWorld).getHandle().getDimensionKey(); -+ } else { -+ resourcekey = World.OVERWORLD; -+ } -+ } else if (nbttagcompound != null) { -+ // Vanilla migration support -+ // Paper end - DataResult dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("Dimension"))); - Logger logger = PlayerList.LOGGER; - diff --git a/Spigot-Server-Patches/Stop-copy-on-write-operations-for-updating-light-dat.patch b/Spigot-Server-Patches/Stop-copy-on-write-operations-for-updating-light-dat.patch deleted file mode 100644 index 1339474e1b..0000000000 --- a/Spigot-Server-Patches/Stop-copy-on-write-operations-for-updating-light-dat.patch +++ /dev/null @@ -1,319 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 27 Apr 2020 04:05:38 -0700 -Subject: [PATCH] Stop copy-on-write operations for updating light data - -Causes huge memory allocations + gc issues - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorage.java -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - protected final LongSet b = new LongOpenHashSet(); - protected final LongSet c = new LongOpenHashSet(); - protected final LongSet d = new LongOpenHashSet(); -- protected volatile M e; -- protected final M f; -+ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -+ protected final M f; // Paper - diff on change, should be "updating" - protected final LongSet g = new LongOpenHashSet(); - protected final LongSet h = new LongOpenHashSet(); - protected final Long2ObjectMap i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - this.l = enumskyblock; - this.m = ilightaccess; - this.f = m0; -- this.e = m0.b(); -- this.e.d(); -+ this.e_visible = m0.b(); // Paper - avoid copying light data -+ this.e_visible.d(); // Paper - avoid copying light data - } - - protected boolean g(long i) { -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - - @Nullable - protected NibbleArray a(long i, boolean flag) { -- return this.a(flag ? this.f : this.e, i); -+ // Paper start - avoid copying light data -+ if (flag) { -+ return this.a(this.f, i); -+ } else { -+ synchronized (this.visibleUpdateLock) { -+ return this.a(this.e_visible, i); -+ } -+ } -+ // Paper end - avoid copying light data - } - - @Nullable -@@ -0,0 +0,0 @@ public abstract class LightEngineStorage> e - - protected void e() { - if (!this.g.isEmpty()) { -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - M m0 = this.f.b(); - - m0.d(); -- this.e = m0; -+ this.e_visible = m0; // Paper - avoid copying light data -+ } // Paper - avoid copying light data - this.g.clear(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageArray.java -@@ -0,0 +0,0 @@ public abstract class LightEngineStorageArray a; -- -- protected LightEngineStorageArray(Long2ObjectOpenHashMap long2objectopenhashmap) { -- this.a = long2objectopenhashmap; -+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data -+ protected final boolean isVisible; // Paper - avoid copying light data -+ java.util.function.Function lookup; // Paper - faster branchless lookup -+ -+ // Paper start - avoid copying light data -+ protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { -+ if (isVisible) { -+ data.performUpdatesLockMap(); -+ } -+ this.data = data; -+ this.isVisible = isVisible; -+ if (isVisible) { -+ lookup = data::getVisibleAsync; -+ } else { -+ lookup = data::getUpdating; -+ } -+ // Paper end - avoid copying light data - this.c(); - this.d = true; - } -@@ -0,0 +0,0 @@ public abstract class LightEngineStorageArray { - - protected LightEngineStorageBlock(ILightAccess ilightaccess) { -- super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new Long2ObjectOpenHashMap())); -+ super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data - } - - @Override -@@ -0,0 +0,0 @@ public class LightEngineStorageBlock extends LightEngineStorage { - -- public a(Long2ObjectOpenHashMap long2objectopenhashmap) { -- super(long2objectopenhashmap); -+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data -+ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data - } - - @Override - public LightEngineStorageBlock.a b() { -- return new LightEngineStorageBlock.a(this.a.clone()); -+ return new a(this.data, true); // Paper - avoid copying light data - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LightEngineStorageSky.java -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data - } - - @Override - protected int d(long i) { - long j = SectionPosition.e(i); - int k = SectionPosition.c(j); -- LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e; -- int l = lightenginestoragesky_a.c.get(SectionPosition.f(j)); -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data -+ LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -+ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPosition.f(j)); // Paper - avoid copying light data - - if (l != lightenginestoragesky_a.b && k < l) { - NibbleArray nibblearray = this.a(lightenginestoragesky_a, j); // Paper - decompile fix -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage j) { - ((LightEngineStorageSky.a) this.f).b = j; -- ((LightEngineStorageSky.a) this.f).c.defaultReturnValue(((LightEngineStorageSky.a) this.f).b); -+ ((LightEngineStorageSky.a) this.f).otherData.queueDefaultReturnValue(((LightEngineStorageSky.a) this.f).b); // Paper - avoid copying light data - } - - long k = SectionPosition.f(i); -- int l = ((LightEngineStorageSky.a) this.f).c.get(k); -+ int l = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(k); // Paper - avoid copying light data - - if (l < j + 1) { -- ((LightEngineStorageSky.a) this.f).c.put(k, j + 1); -+ ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data - if (this.o.contains(k)) { - this.q(i); - if (l > ((LightEngineStorageSky.a) this.f).b) { -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage= k; - } -@@ -0,0 +0,0 @@ public class LightEngineStorageSky extends LightEngineStorage { - - private int b; -- private final Long2IntOpenHashMap c; -- -- public a(Long2ObjectOpenHashMap long2objectopenhashmap, Long2IntOpenHashMap long2intopenhashmap, int i) { -- super(long2objectopenhashmap); -- this.c = long2intopenhashmap; -- long2intopenhashmap.defaultReturnValue(i); -+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data -+ -+ // Paper start - avoid copying light data -+ public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { -+ super(data, isVisible); -+ this.otherData = otherData; -+ otherData.queueDefaultReturnValue(i); -+ // Paper end - avoid copying light data - this.b = i; - } - - @Override - public LightEngineStorageSky.a b() { -- return new LightEngineStorageSky.a(this.a.clone(), this.c.clone(), this.b); -+ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data -+ return new LightEngineStorageSky.a(this.data, this.otherData, this.b, true); // Paper - avoid copying light data - } - } - } diff --git a/Spigot-Server-Patches/Store-counts-for-each-Entity-Block-Entity-Type.patch b/Spigot-Server-Patches/Store-counts-for-each-Entity-Block-Entity-Type.patch deleted file mode 100644 index 8b01ce0da7..0000000000 --- a/Spigot-Server-Patches/Store-counts-for-each-Entity-Block-Entity-Type.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:13:59 -0400 -Subject: [PATCH] Store counts for each Entity/Block Entity Type - -Opens door for future patches to optimize performance - -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - - // Paper start -+ public final co.aikar.util.Counter entityCounts = new co.aikar.util.Counter<>(); -+ public final co.aikar.util.Counter tileEntityCounts = new co.aikar.util.Counter<>(); - private class TileEntityHashMap extends java.util.HashMap { - @Override - public TileEntity put(BlockPosition key, TileEntity value) { - TileEntity replaced = super.put(key, value); - if (replaced != null) { - replaced.setCurrentChunk(null); -+ tileEntityCounts.decrement(replaced.getMinecraftKeyString()); - } - if (value != null) { - value.setCurrentChunk(Chunk.this); -+ tileEntityCounts.increment(value.getMinecraftKeyString()); - } - return replaced; - } -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - TileEntity removed = super.remove(key); - if (removed != null) { - removed.setCurrentChunk(null); -+ tileEntityCounts.decrement(removed.getMinecraftKeyString()); - } - return removed; - } -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - k = this.entitySlices.length - 1; - } - -+ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper - entity.inChunk = true; - entity.setCurrentChunk(this); // Paper - entity.chunkX = this.loc.x; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - if (!this.entitySlices[i].remove(entity)) { - return; - } -+ entityCounts.decrement(entity.getMinecraftKeyString()); - // Paper end - this.entities.remove(entity); // Paper - } diff --git a/Spigot-Server-Patches/Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch b/Spigot-Server-Patches/Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch deleted file mode 100644 index 8988926945..0000000000 --- a/Spigot-Server-Patches/Store-reference-to-current-Chunk-for-Entity-and-Bloc.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 02:10:36 -0400 -Subject: [PATCH] Store reference to current Chunk for Entity and Block - Entities - -This enables us a fast reference to the entities current chunk instead -of having to look it up by hashmap lookups. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isChunkLoaded() { -- return world.isChunkLoaded((int) Math.floor(this.locX()) >> 4, (int) Math.floor(this.locZ()) >> 4); -+ return getCurrentChunk() != null; - } - // CraftBukkit end - -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - // Paper start -+ public java.lang.ref.WeakReference currentChunk = null; -+ -+ public void setCurrentChunk(net.minecraft.world.level.chunk.Chunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } -+ /** -+ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null -+ */ -+ public net.minecraft.world.level.chunk.Chunk getCurrentChunk() { -+ final net.minecraft.world.level.chunk.Chunk chunk = currentChunk != null ? currentChunk.get() : null; -+ if (chunk != null && chunk.loaded) { -+ return chunk; -+ } -+ -+ return !inChunk ? null : ((WorldServer)world).getChunkProvider().getChunkAtIfLoadedMainThreadNoCache(chunkX, chunkZ); -+ } -+ - private MinecraftKey entityKey; - private String entityKeyString; - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.World; - import net.minecraft.world.level.block.EnumBlockMirror; - import net.minecraft.world.level.block.EnumBlockRotation; - import net.minecraft.world.level.block.state.IBlockData; -+import net.minecraft.world.level.chunk.Chunk; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import org.apache.logging.log4j.util.Supplier; -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - getMinecraftKey(); // Try to load if it doesn't exists. - return tileEntityKeyString; - } -+ -+ private java.lang.ref.WeakReference currentChunk = null; -+ public Chunk getCurrentChunk() { -+ final Chunk chunk = currentChunk != null ? currentChunk.get() : null; -+ return chunk != null && chunk.loaded ? chunk : null; -+ } -+ public void setCurrentChunk(Chunk chunk) { -+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; -+ } - // Paper end - - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null); - } - -+ // Paper start -+ private class TileEntityHashMap extends java.util.HashMap { -+ @Override -+ public TileEntity put(BlockPosition key, TileEntity value) { -+ TileEntity replaced = super.put(key, value); -+ if (replaced != null) { -+ replaced.setCurrentChunk(null); -+ } -+ if (value != null) { -+ value.setCurrentChunk(Chunk.this); -+ } -+ return replaced; -+ } -+ -+ @Override -+ public TileEntity remove(Object key) { -+ TileEntity removed = super.remove(key); -+ if (removed != null) { -+ removed.setCurrentChunk(null); -+ } -+ return removed; -+ } -+ } -+ // Paper end -+ - public Chunk(World world, ChunkCoordIntPair chunkcoordintpair, BiomeStorage biomestorage, ChunkConverter chunkconverter, TickList ticklist, TickList ticklist1, long i, @Nullable ChunkSection[] achunksection, @Nullable Consumer consumer) { - this.sections = new ChunkSection[16]; - this.e = Maps.newHashMap(); - this.heightMap = Maps.newEnumMap(HeightMap.Type.class); -- this.tileEntities = Maps.newHashMap(); -+ this.tileEntities = new TileEntityHashMap(); // Paper - this.l = Maps.newHashMap(); - this.m = Maps.newHashMap(); - this.n = new ShortList[16]; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - - entity.inChunk = true; -+ entity.setCurrentChunk(this); // Paper - entity.chunkX = this.loc.x; - entity.chunkY = k; - entity.chunkZ = this.loc.z; -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - ((HeightMap) this.heightMap.get(heightmap_type)).a(along); - } - -+ public final void removeEntity(Entity entity) { this.b(entity); } // Paper - OBFHELPER - public void b(Entity entity) { - this.a(entity, entity.chunkY); - } -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - i = this.entitySlices.length - 1; - } - -- this.entitySlices[i].remove(entity); -+ // Paper start -+ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null); -+ if (!this.entitySlices[i].remove(entity)) { -+ return; -+ } -+ // Paper end - this.entities.remove(entity); // Paper - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.vehicle.EntityMinecartMobSpawner; - import net.minecraft.world.entity.vehicle.EntityMinecartRideable; - import net.minecraft.world.entity.vehicle.EntityMinecartTNT; - import net.minecraft.world.phys.AxisAlignedBB; -+import org.bukkit.Chunk; // Paper - import org.bukkit.EntityEffect; - import org.bukkit.Location; - import org.bukkit.Server; -@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - this.entity = entity; - } - -+ @Override -+ public Chunk getChunk() { -+ net.minecraft.world.level.chunk.Chunk currentChunk = entity.getCurrentChunk(); -+ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk(); -+ } -+ - public static CraftEntity getEntity(CraftServer server, Entity entity) { - /* - * Order is *EXTREMELY* important -- keep it right! =D diff --git a/Spigot-Server-Patches/String-based-Action-Bar-API.patch b/Spigot-Server-Patches/String-based-Action-Bar-API.patch deleted file mode 100644 index 65ab193fc5..0000000000 --- a/Spigot-Server-Patches/String-based-Action-Bar-API.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 27 Dec 2016 15:02:42 -0500 -Subject: [PATCH] String based Action Bar API - - -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/SystemUtils.java -+++ b/src/main/java/net/minecraft/SystemUtils.java -@@ -0,0 +0,0 @@ public class SystemUtils { - private static final ExecutorService e = a("Main"); - private static final ExecutorService f = n(); - public static LongSupplier a = System::nanoTime; -- public static final UUID b = new UUID(0L, 0L); -+ public static final UUID b = new UUID(0L, 0L); public static final UUID getNullUUID() {return b;} // Paper OBFHELPER - private static final Logger LOGGER = LogManager.getLogger(); - - public static Collector, ?, Map> a() { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - // Paper start -+ @Override -+ public void sendActionBar(BaseComponent[] message) { -+ if (getHandle().playerConnection == null) return; -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, message, -1, -1, -1)); -+ } -+ -+ @Override -+ public void sendActionBar(String message) { -+ if (getHandle().playerConnection == null || message == null || message.isEmpty()) return; -+ getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, CraftChatMessage.fromStringOrNull(message))); -+ } -+ -+ @Override -+ public void sendActionBar(char alternateChar, String message) { -+ if (message == null || message.isEmpty()) return; -+ sendActionBar(org.bukkit.ChatColor.translateAlternateColorCodes(alternateChar, message)); -+ } -+ - @Override - public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { - if (header != null) { diff --git a/Spigot-Server-Patches/Support-components-in-ItemMeta.patch b/Spigot-Server-Patches/Support-components-in-ItemMeta.patch deleted file mode 100644 index 49e2500685..0000000000 --- a/Spigot-Server-Patches/Support-components-in-ItemMeta.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger | Martin -Date: Sat, 6 Jun 2020 18:13:42 +0200 -Subject: [PATCH] Support components in ItemMeta - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return CraftChatMessage.fromJSONComponent(displayName); - } - -+ // Paper start -+ @Override -+ public net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent() { -+ return displayName == null ? new net.md_5.bungee.api.chat.BaseComponent[0] : net.md_5.bungee.chat.ComponentSerializer.parse(displayName); -+ } -+ // Paper end - @Override - public final void setDisplayName(String name) { - this.displayName = CraftChatMessage.fromStringOrNullToJSON(name); - } - -+ // Paper start -+ @Override -+ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { -+ this.displayName = net.md_5.bungee.chat.ComponentSerializer.toString(component); -+ } -+ // Paper end - @Override - public boolean hasDisplayName() { - return displayName != null; -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); - } - -+ // Paper start -+ @Override -+ public List getLoreComponents() { -+ return this.lore == null ? null : new ArrayList<>(this.lore.stream().map(entry -> -+ net.md_5.bungee.chat.ComponentSerializer.parse(entry) -+ ).collect(java.util.stream.Collectors.toList())); -+ } -+ // Paper end - @Override - public void setLore(List lore) { - if (lore == null || lore.isEmpty()) { -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - } - -+ // Paper start -+ @Override -+ public void setLoreComponents(List lore) { -+ if (lore == null) { -+ this.lore = null; -+ } else { -+ if (this.lore == null) { -+ safelyAdd(lore, this.lore = new ArrayList<>(lore.size()), false); -+ } else { -+ this.lore.clear(); -+ safelyAdd(lore, this.lore, false); -+ } -+ } -+ } -+ // Paper end - @Override - public boolean hasCustomModelData() { - return customModelData != null; -@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - - for (Object object : addFrom) { -+ // Paper start - support components -+ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[]) { -+ addTo.add(net.md_5.bungee.chat.ComponentSerializer.toString((net.md_5.bungee.api.chat.BaseComponent[]) object)); -+ } else -+ // Paper end - if (!(object instanceof String)) { - if (object != null) { - throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); diff --git a/Spigot-Server-Patches/Support-old-UUID-format-for-NBT.patch b/Spigot-Server-Patches/Support-old-UUID-format-for-NBT.patch deleted file mode 100644 index 5a9f5dddd0..0000000000 --- a/Spigot-Server-Patches/Support-old-UUID-format-for-NBT.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 29 Jun 2020 03:26:17 -0400 -Subject: [PATCH] Support old UUID format for NBT - -We have stored UUID in plenty of places that did not get DFU'd - -So just look for old format and load it if it exists. - -diff --git a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -+++ b/src/main/java/net/minecraft/nbt/GameProfileSerializer.java -@@ -0,0 +0,0 @@ public final class GameProfileSerializer { - s = nbttagcompound.getString("Name"); - } - -+ // Paper start - support string UUID's -+ if (nbttagcompound.hasKeyOfType("Id", 8)) { -+ uuid = UUID.fromString(nbttagcompound.getString("Id")); -+ } -+ // Paper end - if (nbttagcompound.b("Id")) { - uuid = nbttagcompound.a("Id"); - } -diff --git a/src/main/java/net/minecraft/nbt/NBTTagCompound.java b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/nbt/NBTTagCompound.java -+++ b/src/main/java/net/minecraft/nbt/NBTTagCompound.java -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - - public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper - OBFHELPER - public void a(String s, UUID uuid) { -+ // Paper start - support old format -+ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ this.map.remove(s + "Most"); -+ this.map.remove(s + "Least"); -+ } -+ // Paper end - this.map.put(s, GameProfileSerializer.a(uuid)); - } - -@@ -0,0 +0,0 @@ public class NBTTagCompound implements NBTBase { - */ - public UUID getUUID(String prefix) { return a(prefix); } // Paper - OBFHELPER - public UUID a(String s) { -+ // Paper start - support old format -+ if (!hasKeyOfType(s, 11) && this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least")); -+ } -+ // Paper end - return GameProfileSerializer.a(this.get(s)); - } - - public final boolean hasUUID(String s) { return this.b(s); } // Paper - OBFHELPER - public boolean b(String s) { -+ // Paper start - support old format -+ if (this.hasKeyOfType(s + "Most", 99) && this.hasKeyOfType(s + "Least", 99)) { -+ return true; -+ } -+ // Paper end - NBTBase nbtbase = this.get(s); - - return nbtbase != null && nbtbase.b() == NBTTagIntArray.a && ((NBTTagIntArray) nbtbase).getInts().length == 4; diff --git a/Spigot-Server-Patches/Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch b/Spigot-Server-Patches/Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch deleted file mode 100644 index 74c23e24d8..0000000000 --- a/Spigot-Server-Patches/Synchronize-DataPaletteBlock-instead-of-ReentrantLoc.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 29 May 2020 20:29:02 -0400 -Subject: [PATCH] Synchronize DataPaletteBlock instead of ReentrantLock - -Mojang has flaws in their logic about chunks being concurrently -wrote to. So we constantly see crashes around multiple threads writing. - -Additionally, java has optimized synchronization so well that its -in many times faster than trying to manage read wrote locks for low -contention situations. - -And this is extremely a low contention situation. - -diff --git a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -+++ b/src/main/java/net/minecraft/world/level/chunk/DataPaletteBlock.java -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - private int i; private int getBitsPerObject() { return this.i; } // Paper - OBFHELPER - private final ReentrantLock j = new ReentrantLock(); - -- public void a() { -+ public void a() { /* // Paper start - disable this - use proper synchronization - if (this.j.isLocked() && !this.j.isHeldByCurrentThread()) { - String s = (String) Thread.getAllStackTraces().keySet().stream().filter(Objects::nonNull).map((thread) -> { - return thread.getName() + ": \n\tat " + (String) Arrays.stream(thread.getStackTrace()).map(Object::toString).collect(Collectors.joining("\n\tat ")); -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - throw new ReportedException(crashreport); - } else { - this.j.lock(); -- } -+ } */ // Paper end - } - - public void b() { -- this.j.unlock(); -+ //this.j.unlock(); // Paper - disable this - } - - public DataPaletteBlock(DataPalette datapalette, RegistryBlockID registryblockid, Function function, Function function1, T t0) { -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - @Override -- public int onResize(int i, T t0) { -+ public synchronized int onResize(int i, T t0) { // Paper - synchronize - this.a(); - DataBits databits = this.a; - DataPalette datapalette = this.h; -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public T setBlock(int i, int j, int k, T t0) { -- this.a(); -- T t1 = this.a(b(i, j, k), t0); -+ //this.a(); // Paper - remove to reduce ops - synchronize handled below -+ return this.a(b(i, j, k), t0); // Paper - -- this.b(); -- return t1; -+ //this.b(); // Paper -+ //return t1; // PAper - } - - public T b(int i, int j, int k, T t0) { - return this.a(b(i, j, k), t0); - } - -- protected T a(int i, T t0) { -+ protected synchronized T a(int i, T t0) { // Paper - synchronize - writes - int j = this.h.a(t0); - int k = this.a.a(i, j); - T t1 = this.h.a(k); -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - } - - public void writeDataPaletteBlock(PacketDataSerializer packetDataSerializer) { this.b(packetDataSerializer); } // Paper - OBFHELPER -- public void b(PacketDataSerializer packetdataserializer) { -+ public synchronized void b(PacketDataSerializer packetdataserializer) { // Paper - synchronize - this.a(); - packetdataserializer.writeByte(this.i); - this.h.b(packetdataserializer); -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - this.b(); - } - -- public void a(NBTTagList nbttaglist, long[] along) { -+ public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize - this.a(); - int i = Math.max(4, MathHelper.e(nbttaglist.size())); - -@@ -0,0 +0,0 @@ public class DataPaletteBlock implements DataPaletteExpandable { - this.b(); - } - -- public void a(NBTTagCompound nbttagcompound, String s, String s1) { -+ public synchronized void a(NBTTagCompound nbttagcompound, String s, String s1) { // Paper - synchronize - this.a(); - DataPaletteHash datapalettehash = new DataPaletteHash<>(this.d, this.i, this.c, this.e, this.f); - T t0 = this.g; diff --git a/Spigot-Server-Patches/System-property-for-disabling-watchdoge.patch b/Spigot-Server-Patches/System-property-for-disabling-watchdoge.patch deleted file mode 100644 index f59f1d69b9..0000000000 --- a/Spigot-Server-Patches/System-property-for-disabling-watchdoge.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Thu, 12 May 2016 23:02:58 -0500 -Subject: [PATCH] System property for disabling watchdoge - - -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -0,0 +0,0 @@ public class WatchdogThread extends Thread - while ( !stopping ) - { - // -- if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime ) -+ if ( lastTick != 0 && timeoutTime > 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable - { - Logger log = Bukkit.getServer().getLogger(); - log.log( Level.SEVERE, "------------------------------" ); diff --git a/Spigot-Server-Patches/Tameable-getOwnerUniqueId-API.patch b/Spigot-Server-Patches/Tameable-getOwnerUniqueId-API.patch deleted file mode 100644 index 5f74fcd941..0000000000 --- a/Spigot-Server-Patches/Tameable-getOwnerUniqueId-API.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 24 Feb 2018 01:14:55 -0500 -Subject: [PATCH] Tameable#getOwnerUniqueId API - -This is faster if all you need is the UUID, as .getOwner() will cause -an OfflinePlayer to be loaded from disk. - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -@@ -0,0 +0,0 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac - } - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - return getHandle().getOwnerUUID(); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -@@ -0,0 +0,0 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat - return (EntityTameableAnimal) super.getHandle(); - } - -+ public UUID getOwnerUniqueId() { -+ return getOwnerUUID(); -+ } - public UUID getOwnerUUID() { - try { - return getHandle().getOwnerUUID(); diff --git a/Spigot-Server-Patches/Thread-Safe-Vanilla-Command-permission-checking.patch b/Spigot-Server-Patches/Thread-Safe-Vanilla-Command-permission-checking.patch deleted file mode 100644 index dba1a7ff45..0000000000 --- a/Spigot-Server-Patches/Thread-Safe-Vanilla-Command-permission-checking.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 11 Jul 2020 03:54:28 -0400 -Subject: [PATCH] Thread Safe Vanilla Command permission checking - -Datapacks check this on load and are built concurrently. This was breaking them badly due -to race conditions. - -Plus, .canUse we want to be safe for async anyways. - -diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java -+++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java -@@ -0,0 +0,0 @@ public abstract class CommandNode implements Comparable> { - public synchronized boolean canUse(final S source) { - if (source instanceof CommandListenerWrapper) { - try { -- ((CommandListenerWrapper) source).currentCommand = this; -+ ((CommandListenerWrapper) source).currentCommand.set(this); // Paper - return requirement.test(source); - } finally { -- ((CommandListenerWrapper) source).currentCommand = null; -+ ((CommandListenerWrapper) source).currentCommand.set(null); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -+++ b/src/main/java/net/minecraft/commands/CommandListenerWrapper.java -@@ -0,0 +0,0 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys - private final ResultConsumer l; - private final ArgumentAnchor.Anchor m; - private final Vec2F n; -- public volatile CommandNode currentCommand; // CraftBukkit -+ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper - - public CommandListenerWrapper(ICommandListener icommandlistener, Vec3D vec3d, Vec2F vec2f, WorldServer worldserver, int i, String s, IChatBaseComponent ichatbasecomponent, MinecraftServer minecraftserver, @Nullable Entity entity) { - this(icommandlistener, vec3d, vec2f, worldserver, i, s, ichatbasecomponent, minecraftserver, entity, false, (commandcontext, flag, j) -> { -@@ -0,0 +0,0 @@ public class CommandListenerWrapper implements ICompletionProvider, com.destroys - @Override - public boolean hasPermission(int i) { - // CraftBukkit start -- CommandNode currentCommand = this.currentCommand; -+ // Paper start - fix concurrency issue -+ CommandNode currentCommand = this.currentCommand.get(); - if (currentCommand != null) { - return hasPermission(i, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); -+ // Paper end - } - // CraftBukkit end - diff --git a/Spigot-Server-Patches/Throw-proper-exception-on-empty-JsonList-file.patch b/Spigot-Server-Patches/Throw-proper-exception-on-empty-JsonList-file.patch deleted file mode 100644 index 71fc1d2adb..0000000000 --- a/Spigot-Server-Patches/Throw-proper-exception-on-empty-JsonList-file.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Sun, 1 Nov 2020 16:43:11 +0100 -Subject: [PATCH] Throw proper exception on empty JsonList file - - -diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/JsonList.java -+++ b/src/main/java/net/minecraft/server/players/JsonList.java -@@ -0,0 +0,0 @@ public abstract class JsonList> { - - try { - JsonArray jsonarray = (JsonArray) JsonList.b.fromJson(bufferedreader, JsonArray.class); -+ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.c.getName() + "\" is either empty or corrupt"); // Paper - - this.d.clear(); - Iterator iterator = jsonarray.iterator(); diff --git a/Spigot-Server-Patches/Timings-v2.patch b/Spigot-Server-Patches/Timings-v2.patch deleted file mode 100644 index 8f3f81270f..0000000000 --- a/Spigot-Server-Patches/Timings-v2.patch +++ /dev/null @@ -1,2309 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 04:00:11 -0600 -Subject: [PATCH] Timings v2 - - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +0,0 @@ -+package co.aikar.timings; -+ -+import com.google.common.collect.MapMaker; -+import net.minecraft.commands.CustomFunction; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.TileEntity; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.scheduler.BukkitTask; -+ -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+ -+import java.util.Map; -+ -+// TODO: Re-implement missing timers -+public final class MinecraftTimings { -+ -+ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing playerListTimer = Timings.ofSafe("Player List"); -+ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); -+ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -+ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); -+ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); -+ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); -+ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); -+ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); -+ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); -+ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); -+ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); -+ public static final Timing savePlayers = Timings.ofSafe("Save Players"); -+ -+ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); -+ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); -+ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); -+ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); -+ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); -+ -+ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); -+ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); -+ -+ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); -+ -+ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); -+ -+ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); -+ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); -+ -+ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); -+ -+ private MinecraftTimings() {} -+ -+ public static Timing getInternalTaskName(String taskName) { -+ return Timings.ofSafe(taskName); -+ } -+ -+ /** -+ * Gets a timer associated with a plugins tasks. -+ * @param bukkitTask -+ * @param period -+ * @return -+ */ -+ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { -+ if (!bukkitTask.isSync()) { -+ return NullTimingHandler.NULL; -+ } -+ Plugin plugin; -+ -+ CraftTask craftTask = (CraftTask) bukkitTask; -+ -+ final Class taskClass = craftTask.getTaskClass(); -+ if (bukkitTask.getOwner() != null) { -+ plugin = bukkitTask.getOwner(); -+ } else { -+ plugin = TimingsManager.getPluginByClassloader(taskClass); -+ } -+ -+ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { -+ try { -+ String clsName = !clazz.isMemberClass() -+ ? clazz.getName() -+ : clazz.getCanonicalName(); -+ if (clsName != null && clsName.contains("$Lambda$")) { -+ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); -+ } -+ return clsName != null ? clsName : "UnknownTask"; -+ } catch (Throwable ex) { -+ new Exception("Error occurred detecting class name", ex).printStackTrace(); -+ return "MangledClassFile"; -+ } -+ }); -+ -+ StringBuilder name = new StringBuilder(64); -+ name.append("Task: ").append(taskname); -+ if (period > 0) { -+ name.append(" (interval:").append(period).append(")"); -+ } else { -+ name.append(" (Single)"); -+ } -+ -+ if (plugin == null) { -+ return Timings.ofSafe(null, name.toString()); -+ } -+ -+ return Timings.ofSafe(plugin, name.toString()); -+ } -+ -+ /** -+ * Get a named timer for the specified entity type to track type specific timings. -+ * @param entityType -+ * @return -+ */ -+ public static Timing getEntityTimings(String entityType, String type) { -+ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); -+ } -+ -+ /** -+ * Get a named timer for the specified tile entity type to track type specific timings. -+ * @param entity -+ * @return -+ */ -+ public static Timing getTileEntityTimings(TileEntity entity) { -+ String entityType = entity.getClass().getName(); -+ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); -+ } -+ public static Timing getCancelTasksTimer() { -+ return Timings.ofSafe("Cancel Tasks"); -+ } -+ public static Timing getCancelTasksTimer(Plugin plugin) { -+ return Timings.ofSafe(plugin, "Cancel Tasks"); -+ } -+ -+ public static void stopServer() { -+ TimingsManager.stopServer(); -+ } -+ -+ public static Timing getBlockTiming(Block block) { -+ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); -+ } -+/* -+ public static Timing getStructureTiming(StructureGenerator structureGenerator) { -+ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); -+ }*/ -+ -+ public static Timing getPacketTiming(Packet packet) { -+ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); -+ } -+ -+ public static Timing getCommandFunctionTiming(CustomFunction function) { -+ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +0,0 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.collect.Sets; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang.StringUtils; -+import org.bukkit.Bukkit; -+import org.bukkit.ChatColor; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.MemorySection; -+import org.bukkit.craftbukkit.util.CraftChatMessage; -+import org.bukkit.entity.EntityType; -+import org.json.simple.JSONObject; -+import org.json.simple.JSONValue; -+ -+import java.io.ByteArrayOutputStream; -+import java.io.IOException; -+import java.io.InputStream; -+import java.io.OutputStream; -+import java.lang.management.ManagementFactory; -+import java.lang.management.OperatingSystemMXBean; -+import java.lang.management.RuntimeMXBean; -+import java.net.HttpURLConnection; -+import java.net.InetAddress; -+import java.net.URL; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import java.util.logging.Level; -+import java.util.zip.GZIPOutputStream; -+ -+import static co.aikar.timings.TimingsManager.HISTORY; -+import static co.aikar.util.JSONUtil.appendObjectData; -+import static co.aikar.util.JSONUtil.createObject; -+import static co.aikar.util.JSONUtil.pair; -+import static co.aikar.util.JSONUtil.toArray; -+import static co.aikar.util.JSONUtil.toArrayMapper; -+import static co.aikar.util.JSONUtil.toObjectMapper; -+ -+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) -+public class TimingsExport extends Thread { -+ -+ private final TimingsReportListener listeners; -+ private final Map out; -+ private final TimingHistory[] history; -+ private static long lastReport = 0; -+ -+ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { -+ super("Timings paste thread"); -+ this.listeners = listeners; -+ this.out = out; -+ this.history = history; -+ } -+ -+ /** -+ * Checks if any pending reports are being requested, and builds one if needed. -+ */ -+ public static void reportTimings() { -+ if (Timings.requestingReport.isEmpty()) { -+ return; -+ } -+ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); -+ listeners.addConsoleIfNeeded(); -+ -+ Timings.requestingReport.clear(); -+ long now = System.currentTimeMillis(); -+ final long lastReportDiff = now - lastReport; -+ if (lastReportDiff < 60000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ final long lastStartDiff = now - TimingsManager.timingStart; -+ if (lastStartDiff < 180000) { -+ listeners.sendMessage(ChatColor.RED + "Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)"); -+ listeners.done(); -+ return; -+ } -+ listeners.sendMessage(ChatColor.GREEN + "Preparing Timings Report..."); -+ lastReport = now; -+ Map parent = createObject( -+ // Get some basic system details about the server -+ pair("version", Bukkit.getVersion()), -+ pair("maxplayers", Bukkit.getMaxPlayers()), -+ pair("start", TimingsManager.timingStart / 1000), -+ pair("end", System.currentTimeMillis() / 1000), -+ pair("online-mode", Bukkit.getServer().getOnlineMode()), -+ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getResourcePackRepository().d(), pack -> { -+ // Don't feel like obf helper'ing these, non fatal if its temp missed. -+ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true))); -+ })) -+ ); -+ if (!TimingsManager.privacy) { -+ appendObjectData(parent, -+ pair("server", Bukkit.getUnsafe().getTimingsServerName()), -+ pair("motd", Bukkit.getServer().getMotd()), -+ pair("icon", Bukkit.getServer().getServerIcon().getData()) -+ ); -+ } -+ -+ final Runtime runtime = Runtime.getRuntime(); -+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); -+ -+ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); -+ -+ parent.put("system", createObject( -+ pair("timingcost", getCost()), -+ pair("loadavg", osInfo.getSystemLoadAverage()), -+ pair("name", System.getProperty("os.name")), -+ pair("version", System.getProperty("os.version")), -+ pair("jvmversion", System.getProperty("java.version")), -+ pair("arch", System.getProperty("os.arch")), -+ pair("maxmem", runtime.maxMemory()), -+ pair("memory", createObject( -+ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), -+ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), -+ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) -+ )), -+ pair("cpu", runtime.availableProcessors()), -+ pair("runtime", runtimeBean.getUptime()), -+ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), -+ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) -+ ) -+ ); -+ -+ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { -+ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorldData().getName(), createObject( -+ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { -+ return pair(rule, world.getWorld().getGameRuleValue(rule)); -+ })), -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ )); -+ })); -+ -+ Set tileEntityTypeSet = Sets.newHashSet(); -+ Set entityTypeSet = Sets.newHashSet(); -+ -+ int size = HISTORY.size(); -+ TimingHistory[] history = new TimingHistory[size + 1]; -+ int i = 0; -+ for (TimingHistory timingHistory : HISTORY) { -+ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); -+ entityTypeSet.addAll(timingHistory.entityTypeSet); -+ history[i++] = timingHistory; -+ } -+ -+ history[i] = new TimingHistory(); // Current snapshot -+ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); -+ entityTypeSet.addAll(history[i].entityTypeSet); -+ -+ -+ Map handlers = createObject(); -+ Map groupData; -+ synchronized (TimingIdentifier.GROUP_MAP) { -+ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { -+ synchronized (group.handlers) { -+ for (TimingHandler id : group.handlers) { -+ -+ if (!id.isTimed() && !id.isSpecial()) { -+ continue; -+ } -+ -+ String name = id.identifier.name; -+ if (name.startsWith("##")) { -+ name = name.substring(3); -+ } -+ handlers.put(id.id, toArray( -+ group.id, -+ name -+ )); -+ } -+ } -+ } -+ -+ groupData = toObjectMapper( -+ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); -+ } -+ -+ parent.put("idmap", createObject( -+ pair("groups", groupData), -+ pair("handlers", handlers), -+ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), -+ pair("tileentity", -+ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), -+ pair("entity", -+ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) -+ )); -+ -+ // Information about loaded plugins -+ -+ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), -+ plugin -> pair(plugin.getName(), createObject( -+ pair("version", plugin.getDescription().getVersion()), -+ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), -+ pair("website", plugin.getDescription().getWebsite()), -+ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) -+ )))); -+ -+ -+ -+ // Information on the users Config -+ -+ parent.put("config", createObject( -+ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), -+ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -+ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) -+ )); -+ -+ new TimingsExport(listeners, parent, history).start(); -+ } -+ -+ static long getCost() { -+ // Benchmark the users System.nanotime() for cost basis -+ int passes = 100; -+ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); -+ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); -+ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); -+ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); -+ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); -+ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); -+ -+ long start = System.nanoTime(); -+ for (int i = 0; i < passes; i++) { -+ SAMPLER1.startTiming(); -+ SAMPLER2.startTiming(); -+ SAMPLER3.startTiming(); -+ SAMPLER3.stopTiming(); -+ SAMPLER4.startTiming(); -+ SAMPLER5.startTiming(); -+ SAMPLER6.startTiming(); -+ SAMPLER6.stopTiming(); -+ SAMPLER5.stopTiming(); -+ SAMPLER4.stopTiming(); -+ SAMPLER2.stopTiming(); -+ SAMPLER1.stopTiming(); -+ } -+ long timingsCost = (System.nanoTime() - start) / passes / 6; -+ SAMPLER1.reset(true); -+ SAMPLER2.reset(true); -+ SAMPLER3.reset(true); -+ SAMPLER4.reset(true); -+ SAMPLER5.reset(true); -+ SAMPLER6.reset(true); -+ return timingsCost; -+ } -+ -+ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { -+ -+ JSONObject object = new JSONObject(); -+ for (String key : config.getKeys(false)) { -+ String fullKey = (parentKey != null ? parentKey + "." + key : key); -+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { -+ continue; -+ } -+ final Object val = config.get(key); -+ -+ object.put(key, valAsJSON(val, fullKey)); -+ } -+ return object; -+ } -+ -+ private static Object valAsJSON(Object val, final String parentKey) { -+ if (!(val instanceof MemorySection)) { -+ if (val instanceof List) { -+ Iterable v = (Iterable) val; -+ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); -+ } else { -+ return String.valueOf(val); -+ } -+ } else { -+ return mapAsJSON((ConfigurationSection) val, parentKey); -+ } -+ } -+ -+ @Override -+ public void run() { -+ out.put("data", toArrayMapper(history, TimingHistory::export)); -+ -+ -+ String response = null; -+ String timingsURL = null; -+ try { -+ HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); -+ con.setDoOutput(true); -+ String hostName = "BrokenHost"; -+ try { -+ hostName = InetAddress.getLocalHost().getHostName(); -+ } catch (Exception ignored) {} -+ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); -+ con.setRequestMethod("POST"); -+ con.setInstanceFollowRedirects(false); -+ -+ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ -+ this.def.setLevel(7); -+ }}; -+ -+ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); -+ request.close(); -+ -+ response = getResponse(con); -+ -+ if (con.getResponseCode() != 302) { -+ listeners.sendMessage( -+ ChatColor.RED + "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage()); -+ listeners.sendMessage(ChatColor.RED + "Check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ return; -+ } -+ -+ timingsURL = con.getHeaderField("Location"); -+ listeners.sendMessage(ChatColor.GREEN + "View Timings Report: " + timingsURL); -+ -+ if (response != null && !response.isEmpty()) { -+ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); -+ } -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); -+ } finally { -+ this.listeners.done(timingsURL); -+ } -+ } -+ -+ private String getResponse(HttpURLConnection con) throws IOException { -+ InputStream is = null; -+ try { -+ is = con.getInputStream(); -+ ByteArrayOutputStream bos = new ByteArrayOutputStream(); -+ -+ byte[] b = new byte[1024]; -+ int bytesRead; -+ while ((bytesRead = is.read(b)) != -1) { -+ bos.write(b, 0, bytesRead); -+ } -+ return bos.toString(); -+ -+ } catch (IOException ex) { -+ listeners.sendMessage(ChatColor.RED + "Error uploading timings, check your logs for more information"); -+ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); -+ return null; -+ } finally { -+ if (is != null) { -+ is.close(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +0,0 @@ -+package co.aikar.timings; -+ -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.World; -+import net.minecraft.world.level.storage.WorldDataServer; -+ -+/** -+ * Set of timers per world, to track world specific timings. -+ */ -+// TODO: Re-implement missing timers -+public class WorldTimingsHandler { -+ public final Timing mobSpawn; -+ public final Timing doChunkUnload; -+ public final Timing doPortalForcer; -+ public final Timing scheduledBlocks; -+ public final Timing scheduledBlocksCleanup; -+ public final Timing scheduledBlocksTicking; -+ public final Timing chunkTicks; -+ public final Timing lightChunk; -+ public final Timing chunkTicksBlocks; -+ public final Timing doVillages; -+ public final Timing doChunkMap; -+ public final Timing doChunkMapUpdate; -+ public final Timing doChunkMapToUpdate; -+ public final Timing doChunkMapSortMissing; -+ public final Timing doChunkMapSortSendToPlayers; -+ public final Timing doChunkMapPlayersNeedingChunks; -+ public final Timing doChunkMapPendingSendToPlayers; -+ public final Timing doChunkMapUnloadChunks; -+ public final Timing doChunkGC; -+ public final Timing doSounds; -+ public final Timing entityRemoval; -+ public final Timing entityTick; -+ public final Timing tileEntityTick; -+ public final Timing tileEntityPending; -+ public final Timing tracker1; -+ public final Timing tracker2; -+ public final Timing doTick; -+ public final Timing tickEntities; -+ public final Timing chunks; -+ public final Timing newEntities; -+ public final Timing raids; -+ public final Timing chunkProviderTick; -+ public final Timing broadcastChunkUpdates; -+ public final Timing countNaturalMobs; -+ -+ public final Timing chunkLoad; -+ public final Timing chunkLoadPopulate; -+ public final Timing syncChunkLoad; -+ public final Timing chunkLoadLevelTimer; -+ public final Timing chunkIO; -+ public final Timing chunkPostLoad; -+ public final Timing worldSave; -+ public final Timing worldSaveChunks; -+ public final Timing worldSaveLevel; -+ public final Timing chunkSaveData; -+ -+ -+ public final Timing miscMobSpawning; -+ -+ public WorldTimingsHandler(World server) { -+ String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; -+ -+ mobSpawn = Timings.ofSafe(name + "mobSpawn"); -+ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); -+ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); -+ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); -+ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); -+ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); -+ lightChunk = Timings.ofSafe(name + "Light Chunk"); -+ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); -+ doVillages = Timings.ofSafe(name + "doVillages"); -+ doChunkMap = Timings.ofSafe(name + "doChunkMap"); -+ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); -+ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); -+ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); -+ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); -+ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); -+ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); -+ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); -+ doSounds = Timings.ofSafe(name + "doSounds"); -+ doChunkGC = Timings.ofSafe(name + "doChunkGC"); -+ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); -+ entityTick = Timings.ofSafe(name + "entityTick"); -+ entityRemoval = Timings.ofSafe(name + "entityRemoval"); -+ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); -+ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); -+ -+ chunkLoad = Timings.ofSafe(name + "Chunk Load"); -+ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); -+ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); -+ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); -+ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); -+ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); -+ worldSave = Timings.ofSafe(name + "World Save"); -+ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); -+ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); -+ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); -+ -+ tracker1 = Timings.ofSafe(name + "tracker stage 1"); -+ tracker2 = Timings.ofSafe(name + "tracker stage 2"); -+ doTick = Timings.ofSafe(name + "doTick"); -+ tickEntities = Timings.ofSafe(name + "tickEntities"); -+ -+ chunks = Timings.ofSafe(name + "Chunks"); -+ newEntities = Timings.ofSafe(name + "New entity registration"); -+ raids = Timings.ofSafe(name + "Raids"); -+ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); -+ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); -+ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); -+ -+ -+ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ } -+ -+ public static Timing getTickList(WorldServer worldserver, String timingsType) { -+ return Timings.ofSafe(((WorldDataServer) worldserver.getWorldData()).getName() + " - Scheduled " + timingsType); -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -0,0 +0,0 @@ import java.util.concurrent.TimeUnit; - import java.util.logging.Level; - import java.util.regex.Pattern; - -+import com.google.common.collect.Lists; - import net.minecraft.server.MinecraftServer; - import org.bukkit.Bukkit; - import org.bukkit.command.Command; - import org.bukkit.configuration.ConfigurationSection; - import org.bukkit.configuration.InvalidConfigurationException; - import org.bukkit.configuration.file.YamlConfiguration; -+import co.aikar.timings.Timings; -+import co.aikar.timings.TimingsManager; - - public class PaperConfig { - -@@ -0,0 +0,0 @@ public class PaperConfig { - config.addDefault(path, def); - return config.getString(path, config.getString(path)); - } -+ -+ public static String timingsServerName; -+ private static void timings() { -+ boolean timings = getBoolean("timings.enabled", true); -+ boolean verboseTimings = getBoolean("timings.verbose", true); -+ TimingsManager.privacy = getBoolean("timings.server-name-privacy", false); -+ TimingsManager.hiddenConfigs = getList("timings.hidden-config-entries", Lists.newArrayList("database", "settings.bungeecord-addresses", "settings.velocity-support.secret")); -+ if (!TimingsManager.hiddenConfigs.contains("settings.velocity-support.secret")) { -+ TimingsManager.hiddenConfigs.add("settings.velocity-support.secret"); -+ } -+ int timingHistoryInterval = getInt("timings.history-interval", 300); -+ int timingHistoryLength = getInt("timings.history-length", 3600); -+ timingsServerName = getString("timings.server-name", "Unknown Server"); -+ -+ -+ Timings.setVerboseTimingsEnabled(verboseTimings); -+ Timings.setTimingsEnabled(timings); -+ Timings.setHistoryInterval(timingHistoryInterval * 20); -+ Timings.setHistoryLength(timingHistoryLength * 20); -+ -+ log("Timings: " + timings + -+ " - Verbose: " + verboseTimings + -+ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) + -+ " - Length: " + timeSummary(Timings.getHistoryLength() / 20) + -+ " - Server Name: " + timingsServerName); -+ } - } -diff --git a/src/main/java/net/minecraft/commands/CustomFunction.java b/src/main/java/net/minecraft/commands/CustomFunction.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/commands/CustomFunction.java -+++ b/src/main/java/net/minecraft/commands/CustomFunction.java -@@ -0,0 +0,0 @@ public class CustomFunction { - - private final CustomFunction.c[] a; - private final MinecraftKey b; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getCommandFunctionTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - - public CustomFunction(MinecraftKey minecraftkey, CustomFunction.c[] acustomfunction_c) { - this.b = minecraftkey; - this.a = acustomfunction_c; - } - -+ public final MinecraftKey getMinecraftKey() { return this.a(); } // Paper - OBFHELPER - public MinecraftKey a() { - return this.b; - } -diff --git a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PlayerConnectionUtils.java -@@ -0,0 +0,0 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.util.thread.IAsyncTaskHandler; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - // CraftBukkit start - import net.minecraft.server.MinecraftServer; -@@ -0,0 +0,0 @@ public class PlayerConnectionUtils { - - public static void ensureMainThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { - if (!iasynctaskhandler.isMainThread()) { -+ Timing timing = MinecraftTimings.getPacketTiming(packet); // Paper - timings - iasynctaskhandler.execute(() -> { - if (MinecraftServer.getServer().hasStopped() || (t0 instanceof PlayerConnection && ((PlayerConnection) t0).processedDisconnect)) return; // CraftBukkit, MC-142590 - if (t0.a().isConnected()) { -+ try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.a(t0); -+ } // Paper - timings - } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); - } -diff --git a/src/main/java/net/minecraft/server/CustomFunctionData.java b/src/main/java/net/minecraft/server/CustomFunctionData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/CustomFunctionData.java -+++ b/src/main/java/net/minecraft/server/CustomFunctionData.java -@@ -0,0 +0,0 @@ public class CustomFunctionData { - } else { - int j; - -- try { -+ try (co.aikar.timings.Timing timing = customfunction.getTiming().startTiming()) { // Paper - this.d = true; - int k = 0; - CustomFunction.c[] acustomfunction_c = customfunction.b(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.Main; - import org.bukkit.event.server.ServerLoadEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -- return !this.canSleepForTick(); -+ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick - }); - } - -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { -+ return !this.canOversleep(); -+ }); -+ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -+ // Paper end -+ - ++this.ticks; - this.b(booleansupplier); - if (i - this.T >= 5000000000L) { -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit -- SpigotTimings.worldSaveTimer.startTiming(); // Spigot - MinecraftServer.LOGGER.debug("Autosave started"); - this.methodProfiler.enter("save"); - this.playerList.savePlayers(); - this.saveChunks(true, false, false); - this.methodProfiler.exit(); - MinecraftServer.LOGGER.debug("Autosave finished"); -- SpigotTimings.worldSaveTimer.stopTiming(); // Spigot - } - - this.methodProfiler.enter("snooper"); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - // CraftBukkit start - fire RemoteServerCommandEvent -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - if (event.isCancelled()) { - return; - } -+ // Paper start -+ if (s.toLowerCase().startsWith("timings") && s.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { -+ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); -+ Waitable waitable = new Waitable() { -+ @Override -+ protected String evaluate() { -+ return sender.getBuffer(); -+ } -+ }; -+ waitableArray[0] = waitable; -+ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); -+ } else { -+ // Paper end - ServerCommand serverCommand = new ServerCommand(event.getCommand(), remoteControlCommandListener.getWrapper()); - server.dispatchServerCommand(remoteConsole, serverCommand); -+ } // Paper - // CraftBukkit end - }); -+ // Paper start -+ if (waitableArray[0] != null) { -+ //noinspection unchecked -+ Waitable waitable = waitableArray[0]; -+ try { -+ return waitable.get(); -+ } catch (java.util.concurrent.ExecutionException e) { -+ throw new RuntimeException("Exception processing rcon command " + s, e.getCause()); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // Maintain interrupted state -+ throw new RuntimeException("Interrupted processing rcon command " + s, e); -+ } -+ -+ } -+ // Paper end - return this.remoteControlCommandListener.getMessages(); - } - -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } - - gameprofilerfiller.c("getChunkCacheMiss"); -- world.timings.syncChunkLoadTimer.startTiming(); // Spigot - CompletableFuture> completablefuture = this.getChunkFutureMainThread(i, j, chunkstatus, flag); - -+ if (!completablefuture.isDone()) { // Paper -+ this.world.timings.syncChunkLoad.startTiming(); // Paper - this.serverThreadQueue.awaitTasks(completablefuture::isDone); -- world.timings.syncChunkLoadTimer.stopTiming(); // Spigot -+ this.world.timings.syncChunkLoad.stopTiming(); // Paper -+ } // Paper - ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { - return ichunkaccess1; - }, (playerchunk_failure) -> { -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - - public void save(boolean flag) { - this.tickDistanceManager(); -+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings - this.playerChunkMap.save(flag); -+ } // Paper - Timings - } - - @Override -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - this.tickDistanceManager(); - this.world.timings.doChunkMap.stopTiming(); // Spigot - this.world.getMethodProfiler().exitEnter("chunks"); -+ this.world.timings.chunks.startTiming(); // Paper - timings - this.tickChunks(); -+ this.world.timings.chunks.stopTiming(); // Paper - timings - this.world.timings.doChunkUnload.startTiming(); // Spigot - this.world.getMethodProfiler().exitEnter("unload"); - this.playerChunkMap.unloadChunks(booleansupplier); -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - boolean flag2 = world.ticksPerAnimalSpawns != 0L && worlddata.getTime() % world.ticksPerAnimalSpawns == 0L; // CraftBukkit - - this.world.getMethodProfiler().enter("naturalSpawnCount"); -+ this.world.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.chunkMapDistance.b(); - SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); -+ this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.p = spawnercreature_d; - this.world.getMethodProfiler().exit(); - //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper - //Collections.shuffle(list); // Paper -+ this.world.timings.chunkTicks.startTiming(); // Paper - this.playerChunkMap.f().forEach((playerchunk) -> { // Paper - no... just no... - Optional optional = ((Either) playerchunk.a().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - - if (optional.isPresent()) { - this.world.getMethodProfiler().enter("broadcast"); -+ this.world.timings.broadcastChunkUpdates.startTiming(); // Paper - timings - playerchunk.a((Chunk) optional.get()); -+ this.world.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings - this.world.getMethodProfiler().exit(); - Optional optional1 = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left(); - -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - SpawnerCreature.a(this.world, chunk, spawnercreature_d, this.allowAnimals, this.allowMonsters, flag2); - } - -- this.world.timings.doTickTiles.startTiming(); // Spigot -+ //this.world.timings.chunkTicks.startTiming(); // Spigot // Paper - this.world.a(chunk, k); -- this.world.timings.doTickTiles.stopTiming(); // Spigot -+ //this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper - } - } - } - }); -+ this.world.timings.chunkTicks.stopTiming(); // Paper - this.world.getMethodProfiler().enter("customSpawners"); - if (flag1) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.miscMobSpawning.startTiming()) { // Paper - timings - this.world.doMobSpawning(this.allowMonsters, this.allowAnimals); -+ } // Paper - timings - } - - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().exit(); - } - -- this.world.timings.tracker.startTiming(); // Spigot - this.playerChunkMap.g(); -- this.world.timings.tracker.stopTiming(); // Spigot - } - - private void a(long i, Consumer consumer) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.level; - -+import co.aikar.timings.Timing; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.Iterables; -+import com.google.common.collect.ComparisonChain; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Queues; - import com.google.common.collect.Sets; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { - return CompletableFuture.supplyAsync(() -> { -- try { -+ try (Timing ignored = this.world.timings.chunkLoad.startTimingIfSync()) { // Paper - this.world.getMethodProfiler().c("chunkLoad"); -- NBTTagCompound nbttagcompound = this.readChunkData(chunkcoordintpair); -+ NBTTagCompound nbttagcompound; // Paper -+ try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings -+ nbttagcompound = this.readChunkData(chunkcoordintpair); -+ } // Paper end - -- if (nbttagcompound != null) { -+ if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings - boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); - - if (flag) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair); -- } -+ }} // Paper - } catch (ReportedException reportedexception) { - Throwable throwable = reportedexception.getCause(); - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - return "chunkGenerate " + chunkstatus.d(); - }); - return completablefuture.thenComposeAsync((either) -> { -- return (CompletableFuture) either.map((list) -> { -+ return either.map((list) -> { // Paper - Shut up. - try { - CompletableFuture> completablefuture1 = chunkstatus.a(this.world, this.chunkGenerator, this.definedStructureManager, this.lightEngine, (ichunkaccess) -> { - return this.c(playerchunk); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkStatus chunkstatus = PlayerChunk.getChunkStatus(playerchunk.getTicketLevel()); - - return !chunkstatus.b(ChunkStatus.FULL) ? PlayerChunk.UNLOADED_CHUNK_ACCESS : either.mapLeft((ichunkaccess) -> { -+ try (Timing ignored = world.timings.chunkPostLoad.startTimingIfSync()) { // Paper - ChunkCoordIntPair chunkcoordintpair = playerchunk.i(); - Chunk chunk; - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - return chunk; -+ } // Paper - }); - }, (runnable) -> { - Mailbox mailbox = this.mailboxMain; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - PlayerChunkMap.EntityTracker playerchunkmap_entitytracker; - ObjectIterator objectiterator; -+ world.timings.tracker1.startTiming(); // Paper - - for (objectiterator = this.trackedEntities.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.trackerEntry.a()) { - playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - playerchunkmap_entitytracker.e = sectionposition1; - } - } -+ world.timings.tracker1.stopTiming(); // Paper - - if (!list.isEmpty()) { - objectiterator = this.trackedEntities.values().iterator(); - -+ world.timings.tracker2.startTiming(); // Paper - while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); - playerchunkmap_entitytracker.track(list); - } -+ world.timings.tracker2.stopTiming(); // Paper - } - -+ - } - - protected void broadcast(Entity entity, Packet packet) { -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ package net.minecraft.server.level; - - import com.google.common.annotations.VisibleForTesting; - import com.google.common.collect.Iterables; -+import co.aikar.timings.TimingHistory; // Paper -+import co.aikar.timings.Timings; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Queues; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.ITileEntity; - import net.minecraft.world.level.storage.WorldDataServer; - import org.bukkit.Bukkit; - import org.bukkit.WeatherType; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.craftbukkit.util.WorldUUID; - import org.bukkit.event.entity.CreatureSpawnEvent; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end - this.nextTickListBlock = new TickListServer<>(this, (block) -> { - return block == null || block.getBlockData().isAir(); -- }, IRegistry.BLOCK::getKey, this::b); -+ }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings - this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { - return fluidtype == null || fluidtype == FluidTypes.EMPTY; -- }, IRegistry.FLUID::getKey, this::a); -+ }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings - this.navigators = Sets.newHashSet(); - this.L = new ObjectLinkedOpenHashSet(); - this.Q = flag1; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.Q(); - this.b(); - gameprofilerfiller.exitEnter("chunkSource"); -+ this.timings.chunkProviderTick.startTiming(); // Paper - timings - this.getChunkProvider().tick(booleansupplier); -+ this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("tickPending"); -- timings.doTickPending.startTiming(); // Spigot -+ timings.scheduledBlocks.startTiming(); // Paper - if (!this.isDebugWorld()) { - this.nextTickListBlock.b(); - this.nextTickListFluid.b(); - } -- timings.doTickPending.stopTiming(); // Spigot -+ timings.scheduledBlocks.stopTiming(); // Paper - - gameprofilerfiller.exitEnter("raid"); -+ this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); -+ this.timings.raids.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("blockEvents"); - timings.doSounds.startTiming(); // Spigot - this.ak(); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - gameprofilerfiller.exitEnter("tickBlocks"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - if (i > 0) { - ChunkSection[] achunksection = chunk.getSections(); - int l = achunksection.length; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - } - } -- -+ timings.chunkTicksBlocks.stopTiming(); // Paper - gameprofilerfiller.exit(); - } - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) { - this.chunkCheck(entity); - } else { -+ ++TimingHistory.entityTicks; // Paper - timings - // Spigot start -+ co.aikar.timings.Timing timer; // Paper - if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { - entity.ticksLived++; -+ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); -+ } finally { timer.stopTiming(); } // Paper - return; - } - // Spigot end -- entity.tickTimer.startTiming(); // Spigot -+ // Paper start- timings -+ TimingHistory.activatedEntityTicks++; -+ timer = entity.getVehicle() != null ? entity.getEntityType().passengerTickTimer.startTiming() : entity.getEntityType().tickTimer.startTiming(); -+ try { -+ // Paper end - timings - entity.g(entity.locX(), entity.locY(), entity.locZ()); - entity.lastYaw = entity.yaw; - entity.lastPitch = entity.pitch; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.a(entity, entity1); - } - } -- entity.tickTimer.stopTiming(); // Spigot -+ } finally { timer.stopTiming(); } // Paper - timings - - } - } -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - if (!flag1) { - org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper - if (iprogressupdate != null) { - iprogressupdate.a(new ChatMessage("menu.savingLevel")); - } -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - iprogressupdate.c(new ChatMessage("menu.savingChunks")); - } - -+ timings.worldSaveChunks.startTiming(); // Paper - chunkproviderserver.save(flag); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ } // Paper - } - - // CraftBukkit start - moved from MinecraftServer.saveChunks -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ import org.bukkit.inventory.EquipmentSlot; - import org.bukkit.inventory.InventoryView; - import org.bukkit.inventory.SmithingInventory; - import org.bukkit.util.NumberConversions; -+import co.aikar.timings.MinecraftTimings; // Paper - // CraftBukkit end - - public class PlayerConnection implements PacketListenerPlayIn { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - public void tick() { -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot - this.syncPosition(); - this.player.lastX = this.player.locX(); - this.player.lastY = this.player.locY(); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.player.resetIdleTimer(); // CraftBukkit - SPIGOT-854 - this.disconnect(new ChatMessage("multiplayer.disconnect.idling")); - } -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot - - } - -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - // CraftBukkit end - - private void handleCommand(String s) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.startTiming(); // Paper - // CraftBukkit start - whole method - if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot - this.LOGGER.info(this.player.getName() + " issued server command: " + s); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - this.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - return; - } - -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - return; - } finally { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - } - // this.minecraftServer.getCommandDispatcher().a(this.player.getCommandListener(), s); - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.players; - -+import co.aikar.timings.MinecraftTimings; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void savePlayers() { -+ MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.savePlayerFile((EntityPlayer) this.players.get(i)); - } -- -+ MinecraftTimings.savePlayers.stopTiming(); // Paper - } - - public WhiteList getWhitelist() { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.event.CraftPortalEvent; - import org.bukkit.entity.Hanging; - import org.bukkit.entity.LivingEntity; - import org.bukkit.entity.Vehicle; --import org.spigotmc.CustomTimingsHandler; // Spigot - import org.bukkit.event.entity.EntityCombustByEntityEvent; - import org.bukkit.event.hanging.HangingBreakByEntityEvent; - import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only - public boolean forceExplosionKnockback; // SPIGOT-949 - public boolean persistentInvisibility = false; -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public void move(EnumMoveType enummovetype, Vec3D vec3d) { -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot - if (this.noclip) { - this.a(this.getBoundingBox().c(vec3d)); - this.recalcPosition(); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - this.world.getMethodProfiler().exit(); - } -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot - } - - protected BlockPosition ap() { -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class EntityLiving extends Entity { - -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - @Override - public void tick() { -- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot - super.tick(); - this.t(); - this.v(); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - } - -- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot - this.movementTick(); -- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot - double d0 = this.locX() - this.lastX; - double d1 = this.locZ() - this.lastZ; - float f = (float) (d0 * d0 + d1 * d1); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - if (this.isSleeping()) { - this.pitch = 0.0F; - } -- -- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot - } - - public void updateEquipment() { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - this.setMot(d4, d5, d6); - this.world.getMethodProfiler().enter("ai"); -- SpigotTimings.timerEntityAI.startTiming(); // Spigot - if (this.isFrozen()) { - this.jumping = false; - this.aR = 0.0F; -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.doTick(); - this.world.getMethodProfiler().exit(); - } -- SpigotTimings.timerEntityAI.stopTiming(); // Spigot - - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("jump"); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.r(); - AxisAlignedBB axisalignedbb = this.getBoundingBox(); - -- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper - this.g(new Vec3D((double) this.aR, (double) this.aS, (double) this.aT)); -- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot -+ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper - this.world.getMethodProfiler().exit(); - this.world.getMethodProfiler().enter("push"); - if (this.bf > 0) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - this.a(axisalignedbb, this.getBoundingBox()); - } - -- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot - this.collideNearby(); -- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot - this.world.getMethodProfiler().exit(); - if (!this.world.isClientSide && this.dO() && this.aG()) { - this.damageEntity(DamageSource.DROWN, 1.0F); -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ public class EntityTypes { - return IRegistry.ENTITY_TYPE.getOptional(MinecraftKey.a(s)); - } - -- public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { -+ public final String id; -+ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j) { this(entitytypes_b, enumcreaturetype, flag, flag1, flag2, flag3, immutableset, entitysize, i, j, "custom"); } // Paper - old signature -+ public EntityTypes(EntityTypes.b entitytypes_b, EnumCreatureType enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet immutableset, EntitySize entitysize, int i, int j, String id) { // Paper - add id - this.bf = entitytypes_b; - this.bg = enumcreaturetype; - this.bl = flag3; -@@ -0,0 +0,0 @@ public class EntityTypes { - this.br = entitysize; - this.bm = i; - this.bn = j; -+ -+ // Paper start - timings -+ this.id = id; -+ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); -+ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); -+ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); -+ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); -+ // Paper end - } - - @Nullable -@@ -0,0 +0,0 @@ public class EntityTypes { - return this.bn; - } - -+ // Paper start - timings -+ public final co.aikar.timings.Timing tickTimer; -+ public final co.aikar.timings.Timing inactiveTickTimer; -+ public final co.aikar.timings.Timing passengerTickTimer; -+ public final co.aikar.timings.Timing passengerInactiveTickTimer; -+ // Paper end - public boolean isDeltaTracking() { - return this != EntityTypes.PLAYER && this != EntityTypes.LLAMA_SPIT && this != EntityTypes.WITHER && this != EntityTypes.BAT && this != EntityTypes.ITEM_FRAME && this != EntityTypes.LEASH_KNOT && this != EntityTypes.PAINTING && this != EntityTypes.END_CRYSTAL && this != EntityTypes.EVOKER_FANGS; - } -@@ -0,0 +0,0 @@ public class EntityTypes { - SystemUtils.a(DataConverterTypes.ENTITY_TREE, s); - } - -- return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i); -+ return new EntityTypes<>(this.a, this.b, this.d, this.e, this.f, this.g, this.c, this.j, this.h, this.i, s); // Paper - add id - } - } - -diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/TickListServer.java -+++ b/src/main/java/net/minecraft/world/level/TickListServer.java -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - private final List> g = Lists.newArrayList(); - private final Consumer> h; - -- public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer) { -+ public TickListServer(WorldServer worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { // Paper - this.a = predicate; - this.b = function; - this.e = worldserver; - this.h = consumer; -+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); -+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); - } -+ private final co.aikar.timings.Timing timingCleanup; // Paper -+ private final co.aikar.timings.Timing timingTicking; // Paper -+ // Paper end - - public void b() { - int i = this.nextTickList.size(); -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - - this.e.getMethodProfiler().enter("cleaning"); - -+ this.timingCleanup.startTiming(); // Paper - NextTickListEntry nextticklistentry; - - while (i > 0 && iterator.hasNext()) { -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - --i; - } - } -+ this.timingCleanup.stopTiming(); // Paper - -+ this.timingTicking.startTiming(); // Paper - this.e.getMethodProfiler().exitEnter("ticking"); - - while ((nextticklistentry = (NextTickListEntry) this.f.poll()) != null) { -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { - } - } - -+ this.timingTicking.stopTiming(); // Paper - this.e.getMethodProfiler().exit(); - this.g.clear(); - this.f.clear(); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ import net.minecraft.server.level.WorldServer; - import net.minecraft.world.entity.item.EntityItem; - import net.minecraft.world.level.border.IWorldBorderListener; - import org.bukkit.Bukkit; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.block.CapturedBlockState; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper - -- public final SpigotTimings.WorldTimingsHandler timings; // Spigot -+ public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPosition lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public void c(WorldBorder worldborder, double d0) {} - }); - // CraftBukkit end -- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings -+ timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings - this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - timings.tileEntityPending.stopTiming(); // Spigot -+ co.aikar.timings.TimingHistory.tileEntityTicks += this.tileEntityListTick.size(); // Paper - gameprofilerfiller.exit(); - spigotConfig.currentPrimedTnt = 0; // Spigot - } - - public void a(Consumer consumer, Entity entity) { - try { -- SpigotTimings.tickEntityTimer.startTiming(); // Spigot - consumer.accept(entity); -- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Ticking entity"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being ticked"); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -0,0 +0,0 @@ public class Block extends BlockBase implements IMaterial { - }); - protected final BlockStateList blockStateList; - private IBlockData blockData; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - @Nullable - private String name; - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ import org.bukkit.inventory.InventoryHolder; - // CraftBukkit end - - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper - -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot -+ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper - // CraftBukkit start - data containers - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - public CraftPersistentDataContainer persistentDataContainer; -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration)); - - if (this.needsDecoration) { -+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkLoadPopulate.startTiming()) { // Paper - this.needsDecoration = false; - java.util.Random random = new java.util.Random(); - random.setSeed(world.getSeed()); -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - } - } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -+ } // Paper - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.chunk.storage; - -+import co.aikar.timings.Timings; - import com.google.common.collect.Maps; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; - import it.unimi.dsi.fastutil.longs.LongSet; -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - private static void loadEntities(NBTTagCompound nbttagcompound, Chunk chunk) { - NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); - World world = chunk.getWorld(); -- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot - - for (int i = 0; i < nbttaglist.size(); ++i) { - NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - chunk.d(true); - } - -- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot -- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot - NBTTagList nbttaglist1 = nbttagcompound.getList("TileEntities", 10); - - for (int j = 0; j < nbttaglist1.size(); ++j) { -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { - } - } - } -- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot -- - } - - private static NBTTagCompound a(ChunkCoordIntPair chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { - -+ @Deprecated - @Override - public YamlConfiguration getConfig() - { - return org.spigotmc.SpigotConfig.config; - } - -+ @Override -+ public YamlConfiguration getBukkitConfig() -+ { -+ return configuration; -+ } -+ -+ @Override -+ public YamlConfiguration getSpigotConfig() -+ { -+ return org.spigotmc.SpigotConfig.config; -+ } -+ -+ @Override -+ public YamlConfiguration getPaperConfig() -+ { -+ return com.destroystokyo.paper.PaperConfig.config; -+ } -+ - @Override - public void restart() { - org.spigotmc.RestartCommand.restart(); -diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -+++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -@@ -0,0 +0,0 @@ --package org.bukkit.craftbukkit; -- --import java.util.HashMap; --import net.minecraft.world.entity.Entity; --import net.minecraft.world.level.World; --import net.minecraft.world.level.block.entity.TileEntity; --import net.minecraft.world.level.storage.WorldDataServer; --import org.bukkit.craftbukkit.scheduler.CraftTask; --import org.bukkit.plugin.java.JavaPluginLoader; --import org.bukkit.scheduler.BukkitTask; --import org.spigotmc.CustomTimingsHandler; -- --public class SpigotTimings { -- -- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); -- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); -- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); -- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); -- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); -- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); -- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); -- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); -- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); -- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); -- -- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); -- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); -- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); -- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); -- -- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); -- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); -- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); -- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); -- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); -- -- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); -- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); -- -- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); -- -- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); -- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); -- -- public static final HashMap entityTypeTimingMap = new HashMap(); -- public static final HashMap tileEntityTypeTimingMap = new HashMap(); -- public static final HashMap pluginTaskTimingMap = new HashMap(); -- -- /** -- * Gets a timer associated with a plugins tasks. -- * @param task -- * @param period -- * @return -- */ -- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { -- if (!task.isSync()) { -- return null; -- } -- String plugin; -- final CraftTask ctask = (CraftTask) task; -- -- if (task.getOwner() != null) { -- plugin = task.getOwner().getDescription().getFullName(); -- } else { -- plugin = "Unknown"; -- } -- String taskname = ctask.getTaskName(); -- -- String name = "Task: " + plugin + " Runnable: " + taskname; -- if (period > 0) { -- name += "(interval:" + period + ")"; -- } else { -- name += "(Single)"; -- } -- CustomTimingsHandler result = pluginTaskTimingMap.get(name); -- if (result == null) { -- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); -- pluginTaskTimingMap.put(name, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getEntityTimings(Entity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); -- entityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified tile entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); -- tileEntityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Set of timers per world, to track world specific timings. -- */ -- public static class WorldTimingsHandler { -- public final CustomTimingsHandler mobSpawn; -- public final CustomTimingsHandler doChunkUnload; -- public final CustomTimingsHandler doTickPending; -- public final CustomTimingsHandler doTickTiles; -- public final CustomTimingsHandler doChunkMap; -- public final CustomTimingsHandler doSounds; -- public final CustomTimingsHandler entityTick; -- public final CustomTimingsHandler tileEntityTick; -- public final CustomTimingsHandler tileEntityPending; -- public final CustomTimingsHandler tracker; -- public final CustomTimingsHandler doTick; -- public final CustomTimingsHandler tickEntities; -- -- public final CustomTimingsHandler syncChunkLoadTimer; -- public final CustomTimingsHandler syncChunkLoadStructuresTimer; -- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; -- public final CustomTimingsHandler syncChunkLoadPostTimer; -- -- public WorldTimingsHandler(World server) { -- String name = ((WorldDataServer) server.worldData).getName() + " - "; -- -- mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); -- doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); -- doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); -- doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); -- doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); -- doSounds = new CustomTimingsHandler("** " + name + "doSounds"); -- entityTick = new CustomTimingsHandler("** " + name + "entityTick"); -- tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); -- tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); -- -- syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); -- syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); -- syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); -- syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); -- syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); -- syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); -- -- -- tracker = new CustomTimingsHandler(name + "tracker"); -- doTick = new CustomTimingsHandler(name + "doTick"); -- tickEntities = new CustomTimingsHandler(name + "tickEntities"); -- } -- } --} -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - packet.components = components; - getHandle().playerConnection.sendPacket(packet); - } -+ -+ // Paper start -+ @Override -+ public int getPing() -+ { -+ return getHandle().ping; -+ } -+ // Paper end - }; - - public Player.Spigot spigot() -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.scheduler; - -+import co.aikar.timings.MinecraftTimings; // Paper - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import java.util.ArrayList; - import java.util.Comparator; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - - public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { -- final CraftTask task = new CraftTask(run, nextId(), taskName); -+ final CraftTask task = new CraftTask(run, nextId(), "Internal - " + (taskName != null ? taskName : "Unknown")); -+ task.internal = true; - return handle(task, delay); - } - -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - return false; - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - } - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - if (task.isSync()) { - currentTask = task; - try { -- task.timings.startTiming(); // Spigot - task.run(); -- task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { - // Paper start - String msg = String.format( -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - runners.remove(task.getTaskId()); - } - } -+ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); - pending.addAll(temp); - temp.clear(); -+ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); - debugHead = debugHead.getNextHead(currentTick); - } - -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - - private void parsePending() { -+ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -+ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); - } - - private boolean isReady(final int currentTick) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.scheduler; - - import java.util.function.Consumer; -+ -+import co.aikar.timings.NullTimingHandler; - import org.bukkit.Bukkit; - import org.bukkit.plugin.Plugin; - import org.bukkit.scheduler.BukkitTask; - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public class CraftTask implements BukkitTask, Runnable { // Spigot - -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - */ - private volatile long period; - private long nextRun; -- private final Runnable rTask; -- private final Consumer cTask; -+ public final Runnable rTask; // Paper -+ public final Consumer cTask; // Paper -+ public Timing timings; // Paper - private final Plugin plugin; - private final int id; - -- final CustomTimingsHandler timings; // Spigot - CraftTask() { - this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.id = id; - this.period = CraftTask.NO_REPEATING; - this.taskName = taskName; -- this.timings = null; // Will be changed in later patch -+ this.timings = MinecraftTimings.getInternalTaskName(taskName); - } - // Paper end - -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - } - this.id = id; - this.period = period; -- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot -+ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - - @Override - public void run() { -+ try (Timing ignored = timings.startTiming()) { // Paper - if (rTask != null) { - rTask.run(); - } else { - cTask.accept(this); - } -+ } // Paper - } - - long getPeriod() { -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.next = next; - } - -- Class getTaskClass() { -+ public Class getTaskClass() { - return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); - } - -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - return true; - } - -- // Spigot start -- public String getTaskName() { -- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); -- } -- // Spigot end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -@@ -0,0 +0,0 @@ import org.bukkit.util.CachedServerIcon; - public class CraftIconCache implements CachedServerIcon { - public final String value; - -+ public String getData() { return value; } // Paper - public CraftIconCache(final String value) { - this.value = value; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } - // ======================================================================== -+ // Paper start -+ @Override -+ public void reportTimings() { -+ co.aikar.timings.TimingsExport.reportTimings(); -+ } -+ // Paper end - - public static byte toLegacyData(IBlockData data) { - return CraftLegacy.toLegacyData(data); -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - return clazz; - } - -+ // Paper start -+ @Override -+ public String getTimingsServerName() { -+ return com.destroystokyo.paper.PaperConfig.timingsServerName; -+ } -+ // Paper end -+ - /** - * This helper class represents the different NBT Tags. - *

    -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.raid.EntityRaider; - import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.phys.AxisAlignedBB; --import org.bukkit.craftbukkit.SpigotTimings; -+import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { -@@ -0,0 +0,0 @@ public class ActivationRange - /** - * These entities are excluded from Activation range checks. - * -- * @param entity -- * @param config -+ * @param entity Entity to initialize -+ * @param config Spigot config to determine ranges - * @return boolean If it should always tick. - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) -@@ -0,0 +0,0 @@ public class ActivationRange - */ - public static void activateEntities(World world) - { -- SpigotTimings.entityActivationCheckTimer.startTiming(); -+ MinecraftTimings.entityActivationCheckTimer.startTiming(); - final int miscActivationRange = world.spigotConfig.miscActivationRange; - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; -@@ -0,0 +0,0 @@ public class ActivationRange - } - } - } -- SpigotTimings.entityActivationCheckTimer.stopTiming(); -+ MinecraftTimings.entityActivationCheckTimer.stopTiming(); - } - - /** -@@ -0,0 +0,0 @@ public class ActivationRange - */ - public static boolean checkIfActive(Entity entity) - { -- SpigotTimings.checkIfActiveTimer.startTiming(); - // Never safe to skip fireworks or entities not yet added to chunk - if ( !entity.inChunk || entity instanceof EntityFireworks ) { -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return true; - } - -@@ -0,0 +0,0 @@ public class ActivationRange - { - isActive = false; - } -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return isActive; - } - } diff --git a/Spigot-Server-Patches/Toggle-for-removing-existing-dragon.patch b/Spigot-Server-Patches/Toggle-for-removing-existing-dragon.patch deleted file mode 100644 index 36919d8300..0000000000 --- a/Spigot-Server-Patches/Toggle-for-removing-existing-dragon.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mariell Hoversholm -Date: Wed, 30 Sep 2020 22:49:14 +0200 -Subject: [PATCH] Toggle for removing existing dragon - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - log("Using vanilla redstone algorithm."); - } - } -+ -+ public boolean shouldRemoveDragon = false; -+ private void shouldRemoveDragon() { -+ shouldRemoveDragon = getBoolean("should-remove-dragon", shouldRemoveDragon); -+ if (shouldRemoveDragon) { -+ log("The Ender Dragon will be removed if she already exists without a portal."); -+ } -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -0,0 +0,0 @@ public class EnderDragonBattle { - this.dragonUUID = entityenderdragon.getUniqueID(); - EnderDragonBattle.LOGGER.info("Found that there's a dragon still alive ({})", entityenderdragon); - this.dragonKilled = false; -- if (!flag) { -+ if (!flag && this.world.paperConfig.shouldRemoveDragon) { // Paper - EnderDragonBattle.LOGGER.info("But we didn't have a portal, let's remove it."); - entityenderdragon.die(); - this.dragonUUID = null; diff --git a/Spigot-Server-Patches/Toggleable-player-crits-helps-mitigate-hacked-client.patch b/Spigot-Server-Patches/Toggleable-player-crits-helps-mitigate-hacked-client.patch deleted file mode 100644 index 16884a84bc..0000000000 --- a/Spigot-Server-Patches/Toggleable-player-crits-helps-mitigate-hacked-client.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MiniDigger | Martin -Date: Sat, 10 Mar 2018 00:50:24 +0100 -Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); - } - -+ public boolean disablePlayerCrits; -+ private void disablePlayerCrits() { -+ disablePlayerCrits = getBoolean("game-mechanics.disable-player-crits", false); -+ } -+ - public boolean allChunksAreSlimeChunks; - private void allChunksAreSlimeChunks() { - allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - - boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.isClimbing() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && entity instanceof EntityLiving; - -+ flag2 = flag2 && !world.paperConfig.disablePlayerCrits; // Paper - flag2 = flag2 && !this.isSprinting(); - if (flag2) { - f *= 1.5F; diff --git a/Spigot-Server-Patches/Tracking-Range-Improvements.patch b/Spigot-Server-Patches/Tracking-Range-Improvements.patch deleted file mode 100644 index 280370212c..0000000000 --- a/Spigot-Server-Patches/Tracking-Range-Improvements.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Sat, 21 Dec 2019 15:22:09 -0500 -Subject: [PATCH] Tracking Range Improvements - -Sets tracking range of watermobs to animals instead of misc and simplifies code - -Also ignores Enderdragon, defaulting it to Mojang's setting - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - int j = entity.getEntityType().getChunkRange() * 16; -+ j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - - if (j > i) { - i = j; -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -0,0 +0,0 @@ public class TrackingRange - if ( entity instanceof EntityPlayer ) - { - return config.playerTrackingRange; -- } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) -- { -- return config.monsterTrackingRange; -- } else if ( entity instanceof EntityGhast ) -- { -- if ( config.monsterTrackingRange > config.monsterActivationRange ) -- { -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: - return config.monsterTrackingRange; -- } else -- { -- return config.monsterActivationRange; -- } -- } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) -- { -- return config.animalTrackingRange; -- } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return config.animalTrackingRange; -+ case MISC: -+ } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ // Paper end - { - return config.miscTrackingRange; - } else - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } diff --git a/Spigot-Server-Patches/Turtle-API.patch b/Spigot-Server-Patches/Turtle-API.patch deleted file mode 100644 index a3c1c74ebc..0000000000 --- a/Spigot-Server-Patches/Turtle-API.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: BillyGalbreath -Date: Sat, 29 Sep 2018 16:08:23 -0500 -Subject: [PATCH] Turtle API - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalGotoTarget.java -@@ -0,0 +0,0 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { - protected int c; - protected int d; - private int g; -- protected BlockPosition e; -+ protected BlockPosition e;public final BlockPosition getTargetPosition() { return this.e; } // Paper - OBFHELPER - private boolean h; - private final int i; - private final int j; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityTurtle.java -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.sounds.SoundCategory; -@@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { - this.datawatcher.set(EntityTurtle.bp, blockposition); - } - -- private BlockPosition getHomePos() { -+ public BlockPosition getHomePos() { // Paper - public - return (BlockPosition) this.datawatcher.get(EntityTurtle.bp); - } - -@@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { - return (Boolean) this.datawatcher.get(EntityTurtle.bq); - } - -- private void setHasEgg(boolean flag) { -+ public void setHasEgg(boolean flag) { // Paper - this.datawatcher.set(EntityTurtle.bq, flag); - } - -+ public final boolean isDigging() { return this.eL(); } // Paper - OBFHELPER - public boolean eL() { - return (Boolean) this.datawatcher.get(EntityTurtle.br); - } - -+ public final void setDigging(boolean digging) { this.u(digging); } // Paper - OBFHELPER - private void u(boolean flag) { - this.bv = flag ? 1 : 0; - this.datawatcher.set(EntityTurtle.br, flag); - } - -+ public final boolean isGoingHome() { return this.eU(); } // Paper - OBFHELPER - private boolean eU() { - return (Boolean) this.datawatcher.get(EntityTurtle.bt); - } - -+ public final void setGoingHome(boolean goingHome) { this.v(goingHome); } // Paper - OBFHELPER - private void v(boolean flag) { - this.datawatcher.set(EntityTurtle.bt, flag); - } - -+ public final boolean isTravelling() { return this.eV(); } // Paper - OBFHELPER - private boolean eV() { - return (Boolean) this.datawatcher.get(EntityTurtle.bu); - } - -+ public final void setTravelling(boolean travelling) { this.w(travelling); } // Paper - OBFHELPER - private void w(boolean flag) { - this.datawatcher.set(EntityTurtle.bu, flag); - } -@@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { - - if (!this.g.isInWater() && this.l()) { - if (this.g.bv < 1) { -- this.g.u(true); -+ this.g.setDigging(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.getTargetPosition())).callEvent()); // Paper - } else if (this.g.bv > 200) { - World world = this.g.world; - - // CraftBukkit start -- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1)).isCancelled()) { -+ // Paper start -+ int eggCount = this.g.random.nextInt(4) + 1; -+ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.g.getBukkitEntity(), MCUtil.toLocation(this.g.world, this.e.up()), eggCount); -+ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.g, this.e.up(), Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount())).isCancelled()) { - world.playSound((EntityHuman) null, blockposition, SoundEffects.ENTITY_TURTLE_LAY_EGG, SoundCategory.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); -- world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, this.g.random.nextInt(4) + 1), 3); -+ world.setTypeAndData(this.e.up(), (IBlockData) Blocks.TURTLE_EGG.getBlockData().set(BlockTurtleEgg.b, layEggEvent.getEggCount()), 3); - } - // CraftBukkit end - this.g.setHasEgg(false); -@@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { - - @Override - public boolean a() { -- return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))); -+ return this.a.isBaby() ? false : (this.a.hasEgg() ? true : (this.a.getRandom().nextInt(700) != 0 ? false : !this.a.getHomePos().a((IPosition) this.a.getPositionVector(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.a.getBukkitEntity()).callEvent(); // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -@@ -0,0 +0,0 @@ public class CraftTurtle extends CraftAnimals implements Turtle { - public EntityType getType() { - return EntityType.TURTLE; - } -+ -+ // Paper start -+ @Override -+ public org.bukkit.Location getHome() { -+ return net.minecraft.server.MCUtil.toLocation(getHandle().world, getHandle().getHomePos()); -+ } -+ -+ @Override -+ public void setHome(org.bukkit.Location location) { -+ getHandle().setHomePos(net.minecraft.server.MCUtil.toBlockPosition(location)); -+ } -+ -+ @Override -+ public boolean isGoingHome() { -+ return getHandle().isGoingHome(); -+ } -+ -+ @Override -+ public boolean isDigging() { -+ return getHandle().isDigging(); -+ } -+ -+ @Override -+ public boolean hasEgg() { -+ return getHandle().hasEgg(); -+ } -+ -+ @Override -+ public void setHasEgg(boolean hasEgg) { -+ getHandle().setHasEgg(hasEgg); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/Spigot-Server-Patches/Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch deleted file mode 100644 index 58597e5660..0000000000 --- a/Spigot-Server-Patches/Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 Jun 2018 01:18:49 -0400 -Subject: [PATCH] Unset Ignited flag on cancel of Explosion Event - -Otherwise the creeper infinite explodes - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -0,0 +0,0 @@ public class EntityCreeper extends EntityMonster { - - private static final DataWatcherObject b = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.b); - private static final DataWatcherObject POWERED = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); -- private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); -+ private static final DataWatcherObject d = DataWatcher.a(EntityCreeper.class, DataWatcherRegistry.i); private static final DataWatcherObject isIgnitedDW = d; // Paper OBFHELPER - private int bo; - public int fuseTicks; // PAIL - public int maxFuseTicks = 30; -@@ -0,0 +0,0 @@ public class EntityCreeper extends EntityMonster { - this.createEffectCloud(); - } else { - fuseTicks = 0; -+ this.datawatcher.set(isIgnitedDW, Boolean.valueOf(false)); // Paper - } - // CraftBukkit end - } diff --git a/Spigot-Server-Patches/Update-entity-Metadata-for-all-tracked-players.patch b/Spigot-Server-Patches/Update-entity-Metadata-for-all-tracked-players.patch deleted file mode 100644 index aa44593890..0000000000 --- a/Spigot-Server-Patches/Update-entity-Metadata-for-all-tracked-players.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: AgentTroll -Date: Fri, 22 Mar 2019 22:24:03 -0700 -Subject: [PATCH] Update entity Metadata for all tracked players - - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - return PacketPlayOutEntity.a(this.xLoc, this.yLoc, this.zLoc); - } - -+ // Paper start - Add broadcast method -+ void broadcast(Packet packet) { -+ this.getPacketConsumer().accept(packet); -+ } -+ // Paper end -+ - private void broadcastIncludingSelf(Packet packet) { - this.f.accept(packet); - if (this.tracker instanceof EntityPlayer) { -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - if (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem) { - // Refresh the current entity metadata -- this.sendPacket(new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true)); -+ // Paper start - update entity for all players -+ PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entity.getId(), entity.getDataWatcher(), true); -+ if (entity.tracker != null) { -+ entity.tracker.broadcast(packet); -+ } else { -+ this.sendPacket(packet); -+ } -+ // Paper end - } - - if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/Update-itemstack-legacy-name-and-lore.patch b/Spigot-Server-Patches/Update-itemstack-legacy-name-and-lore.patch deleted file mode 100644 index 9ddc416970..0000000000 --- a/Spigot-Server-Patches/Update-itemstack-legacy-name-and-lore.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Wed, 1 Jul 2020 11:57:40 -0500 -Subject: [PATCH] Update itemstack legacy name and lore - - -diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemStack.java -+++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -0,0 +0,0 @@ import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTBase; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; -+import net.minecraft.nbt.NBTTagString; - import net.minecraft.network.chat.ChatComponentText; - import net.minecraft.network.chat.ChatComponentUtils; - import net.minecraft.network.chat.ChatHoverable; -@@ -0,0 +0,0 @@ public final class ItemStack { - list.sort((Comparator) enchantSorter); // Paper - } catch (Exception ignored) {} - } -+ -+ private void processText() { -+ NBTTagCompound display = getSubTag("display"); -+ if (display != null) { -+ if (display.hasKeyOfType("Name", 8)) { -+ String json = display.getString("Name"); -+ if (json != null && json.contains("\u00A7")) { -+ try { -+ display.set("Name", convert(json)); -+ } catch (JsonParseException jsonparseexception) { -+ display.remove("Name"); -+ } -+ } -+ } -+ if (display.hasKeyOfType("Lore", 9)) { -+ NBTTagList list = display.getList("Lore", 8); -+ for (int index = 0; index < list.size(); index++) { -+ String json = list.getString(index); -+ if (json != null && json.contains("\u00A7")) { // Only try if it has legacy in the unparsed json -+ try { -+ list.set(index, convert(json)); -+ } catch (JsonParseException e) { -+ list.set(index, NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new ChatComponentText("")))); -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ private NBTTagString convert(String json) { -+ IChatBaseComponent component = IChatBaseComponent.ChatSerializer.jsonToComponent(json); -+ if (component instanceof ChatComponentText && component.getText().contains("\u00A7") && component.getSiblings().isEmpty()) { -+ // Only convert if the root component is a single comp with legacy in it, don't convert already normal components -+ component = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(component.getText())[0]; -+ } -+ return NBTTagString.create(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); -+ } - // Paper end - - public ItemStack(IMaterial imaterial) { -@@ -0,0 +0,0 @@ public final class ItemStack { - // CraftBukkit start - make defensive copy as this data may be coming from the save thread - this.tag = (NBTTagCompound) nbttagcompound.getCompound("tag").clone(); - processEnchantOrder(this.tag); // Paper -+ processText(); // Paper - this.getItem().b(this.tag); - // CraftBukkit end - } -@@ -0,0 +0,0 @@ public final class ItemStack { - } - } - -+ @Nullable public NBTTagCompound getSubTag(String s) { return b(s); } // Paper - OBFHELPER - @Nullable - public NBTTagCompound b(String s) { - return this.tag != null && this.tag.hasKeyOfType(s, 10) ? this.tag.getCompound(s) : null; diff --git a/Spigot-Server-Patches/Use-ConcurrentHashMap-in-JsonList.patch b/Spigot-Server-Patches/Use-ConcurrentHashMap-in-JsonList.patch deleted file mode 100644 index 675c2f0006..0000000000 --- a/Spigot-Server-Patches/Use-ConcurrentHashMap-in-JsonList.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: egg82 -Date: Tue, 7 Aug 2018 01:24:23 -0600 -Subject: [PATCH] Use ConcurrentHashMap in JsonList - -This is specifically aimed at fixing #471 - -Using a ConcurrentHashMap because thread safety -The performance benefit of Map over ConcurrentMap is negligabe at best in this scenaio, as most operations will be get and not add or remove -Even without considering the use-case the benefits are still negligable - -Original ideas for the system included an expiration policy and/or handler -The simpler solution was to use a computeIfPresent in the get method -This will simultaneously have an O(1) lookup time and automatically expire any values -Since the get method (nor other similar methods) don't seem to have a critical need to flush the map to disk at any of these points further processing is simply wasteful -Meaning the original function expired values unrelated to the current value without actually having any explicit need to - -The h method was heavily modified to be much more efficient in its processing -Also instead of being called on every get, it's now called just before a save -This will eliminate stale values being flushed to disk - -Modified isEmpty to use the isEmpty() method instead of the slightly confusing size() < 1 -The point of this is readability, but does have a side-benefit of a small microptimization - -Finally, added a couple obfhelpers for the modified code - -diff --git a/src/main/java/net/minecraft/server/players/JsonList.java b/src/main/java/net/minecraft/server/players/JsonList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/JsonList.java -+++ b/src/main/java/net/minecraft/server/players/JsonList.java -@@ -0,0 +0,0 @@ import java.io.BufferedReader; - import java.io.BufferedWriter; - import java.io.File; - import java.io.IOException; -+import java.lang.reflect.ParameterizedType; // Paper -+import java.lang.reflect.Type; // Paper - import java.nio.charset.StandardCharsets; - import java.util.Collection; - import java.util.Iterator; -@@ -0,0 +0,0 @@ public abstract class JsonList> { - protected static final Logger LOGGER = LogManager.getLogger(); - private static final Gson b = (new GsonBuilder()).setPrettyPrinting().create(); - private final File c; -- private final Map d = Maps.newHashMap(); -+ // Paper - replace HashMap is ConcurrentHashMap -+ private final Map d = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.d; } // Paper - OBFHELPER -+ private boolean e = true; -+ private static final ParameterizedType f = new ParameterizedType() { -+ public Type[] getActualTypeArguments() { -+ return new Type[]{JsonListEntry.class}; -+ } -+ -+ public Type getRawType() { -+ return List.class; -+ } -+ -+ public Type getOwnerType() { -+ return null; -+ } -+ }; - - public JsonList(File file) { - this.c = file; -@@ -0,0 +0,0 @@ public abstract class JsonList> { - - @Nullable - public V get(K k0) { -- this.g(); -- return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error -+ // Paper start -+ // this.g(); -+ // return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error -+ return (V) this.getBackingMap().computeIfPresent(this.getMappingKey(k0), (k, v) -> { -+ return v.hasExpired() ? null : v; -+ }); -+ // Paper end - } - - public void remove(K k0) { -@@ -0,0 +0,0 @@ public abstract class JsonList> { - // CraftBukkit end - - public boolean isEmpty() { -- return this.d.size() < 1; -+ // return this.d.size() < 1; // Paper -+ return this.getBackingMap().isEmpty(); // Paper - readability is the goal. As an aside, isEmpty() uses only sumCount() and a comparison. size() uses sumCount(), casts, and boolean logic - } - -+ protected final String getMappingKey(K k0) { return a(k0); } // Paper - OBFHELPER - protected String a(K k0) { - return k0.toString(); - } -@@ -0,0 +0,0 @@ public abstract class JsonList> { - return this.d.containsKey(this.a(k0)); - } - -+ private void removeStaleEntries() { g(); } // Paper - OBFHELPER - private void g() { -- List list = Lists.newArrayList(); -+ /*List list = Lists.newArrayList(); - Iterator iterator = this.d.values().iterator(); - - while (iterator.hasNext()) { -@@ -0,0 +0,0 @@ public abstract class JsonList> { - K k0 = (K) iterator.next(); // CraftBukkit - decompile error - - this.d.remove(this.a(k0)); -- } -+ }*/ - -+ this.getBackingMap().values().removeIf(JsonListEntry::hasExpired); -+ // Paper end - } - - protected abstract JsonListEntry a(JsonObject jsonobject); -@@ -0,0 +0,0 @@ public abstract class JsonList> { - } - - public void save() throws IOException { -+ this.removeStaleEntries(); // Paper - remove expired values before saving - JsonArray jsonarray = new JsonArray(); - - this.d.values().stream().map((jsonlistentry) -> { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } else if (!this.isWhitelisted(gameprofile, event)) { // Paper - //chatmessage = new ChatMessage("multiplayer.disconnect.not_whitelisted"); // Paper - //event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot // Paper - moved to isWhitelisted -- } else if (getIPBans().isBanned(socketaddress) && !getIPBans().get(socketaddress).hasExpired()) { -+ } else if (getIPBans().isBanned(socketaddress) && getIPBans().get(socketaddress) != null && !getIPBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans - IpBanEntry ipbanentry = this.l.get(socketaddress); - - chatmessage = new ChatMessage("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); diff --git a/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch b/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch deleted file mode 100644 index 029125f61a..0000000000 --- a/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch +++ /dev/null @@ -1,549 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Fri, 9 Jun 2017 19:03:43 +0200 -Subject: [PATCH] Use TerminalConsoleAppender for console improvements - -Rewrite console improvements (console colors, tab completion, -persistent input line, ...) using JLine 3.x and TerminalConsoleAppender. - -New features: - - Support console colors for Vanilla commands - - Add console colors for warnings and errors - - Server can now be turned off safely using CTRL + C. JLine catches - the signal and the implementation shuts down the server cleanly. - - Support console colors and persistent input line when running in - IntelliJ IDEA - -Other changes: - - Server starts 1-2 seconds faster thanks to optimizations in Log4j - configuration - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - compile - - -- jline -- jline -- 2.12.1 -- compile -+ net.minecrell -+ terminalconsoleappender -+ 1.2.0 -+ -+ -+ org.jline -+ jline-terminal-jansi -+ 3.12.1 -+ runtime -+ -+ -+ -+ org.apache.logging.log4j -+ log4j-core -+ runtime - - - org.apache.logging.log4j -@@ -0,0 +0,0 @@ - - META-INF/services/java.sql.Driver - -+ - - - - -+ -+ -+ com.github.edwgiz -+ maven-shade-plugin.log4j2-cachefile-transformer -+ 2.13.1 -+ -+ - - - org.apache.maven.plugins -diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.console; -+ -+import net.minecraft.server.dedicated.DedicatedServer; -+import net.minecrell.terminalconsole.SimpleTerminalConsole; -+import org.bukkit.craftbukkit.command.ConsoleCommandCompleter; -+import org.jline.reader.LineReader; -+import org.jline.reader.LineReaderBuilder; -+ -+public final class PaperConsole extends SimpleTerminalConsole { -+ -+ private final DedicatedServer server; -+ -+ public PaperConsole(DedicatedServer server) { -+ this.server = server; -+ } -+ -+ @Override -+ protected LineReader buildReader(LineReaderBuilder builder) { -+ return super.buildReader(builder -+ .appName("Paper") -+ .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) -+ .completer(new ConsoleCommandCompleter(this.server)) -+ ); -+ } -+ -+ @Override -+ protected boolean isRunning() { -+ return !this.server.isStopped() && this.server.isRunning(); -+ } -+ -+ @Override -+ protected void runCommand(String command) { -+ this.server.issueCommand(command, this.server.getServerCommandListener()); -+ } -+ -+ @Override -+ protected void shutdown() { -+ this.server.safeShutdown(false); -+ } -+ -+} -diff --git a/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/console/TerminalConsoleCommandSender.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.console; -+ -+import org.apache.logging.log4j.LogManager; -+import org.apache.logging.log4j.Logger; -+import org.bukkit.craftbukkit.command.CraftConsoleCommandSender; -+ -+public class TerminalConsoleCommandSender extends CraftConsoleCommandSender { -+ -+ private static final Logger LOGGER = LogManager.getRootLogger(); -+ -+ @Override -+ public void sendRawMessage(String message) { -+ // TerminalConsoleAppender supports color codes directly in log messages -+ LOGGER.info(message); -+ } -+ -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import com.mojang.datafixers.DataFixer; - import io.netty.buffer.ByteBuf; - import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; -+import io.papermc.paper.adventure.PaperAdventure; // Paper - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - import com.mojang.serialization.DynamicOps; - import com.mojang.serialization.Lifecycle; - import com.google.common.collect.ImmutableSet; --import jline.console.ConsoleReader; -+// import jline.console.ConsoleReader; // Paper - import joptsimple.OptionSet; - import net.minecraft.nbt.DynamicOpsNBT; - import net.minecraft.nbt.NBTBase; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant replacements = new EnumMap(ChatColor.class); - private final ChatColor[] colors = ChatColor.values(); -@@ -0,0 +0,0 @@ public class ColouredConsoleSender extends CraftConsoleCommandSender { - } else { - return new ColouredConsoleSender(); - } -- } -+ }*/ // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java -@@ -0,0 +0,0 @@ import java.util.Collections; - import java.util.List; - import java.util.concurrent.ExecutionException; - import java.util.logging.Level; --import jline.console.completer.Completer; -+import net.minecraft.server.dedicated.DedicatedServer; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.util.Waitable; -+ -+// Paper start - JLine update -+import org.jline.reader.Candidate; -+import org.jline.reader.Completer; -+import org.jline.reader.LineReader; -+import org.jline.reader.ParsedLine; -+// Paper end - import org.bukkit.event.server.TabCompleteEvent; - - public class ConsoleCommandCompleter implements Completer { -- private final CraftServer server; -+ private final DedicatedServer server; // Paper - CraftServer -> DedicatedServer - -- public ConsoleCommandCompleter(CraftServer server) { -+ public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer - this.server = server; - } - -+ // Paper start - Change method signature for JLine update - @Override -- public int complete(final String buffer, final int cursor, final List candidates) { -+ public void complete(LineReader reader, ParsedLine line, List candidates) { -+ final CraftServer server = this.server.server; -+ final String buffer = line.line(); -+ // Paper end - Waitable> waitable = new Waitable>() { - @Override - protected List evaluate() { -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { - return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); - } - }; -- this.server.getServer().processQueue.add(waitable); -+ server.getServer().processQueue.add(waitable); // Paper - Remove "this." - try { - List offers = waitable.get(); - if (offers == null) { -- return cursor; -+ return; // Paper - Method returns void -+ } -+ -+ // Paper start - JLine update -+ for (String completion : offers) { -+ if (completion.isEmpty()) { -+ continue; -+ } -+ -+ candidates.add(new Candidate(completion)); - } -- candidates.addAll(offers); -+ // Paper end - -+ // Paper start - JLine handles cursor now -+ /* - final int lastSpace = buffer.lastIndexOf(' '); - if (lastSpace == -1) { - return cursor - buffer.length(); - } else { - return cursor - (buffer.length() - lastSpace - 1); - } -+ */ -+ // Paper end - } catch (ExecutionException e) { -- this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); -+ server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e); // Paper - Remove "this." - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } -- return cursor; - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -0,0 +0,0 @@ public class ServerShutdownThread extends Thread { - server.close(); - } finally { - try { -- server.reader.getTerminal().restore(); -+ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender - } catch (Exception e) { - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/TerminalConsoleWriterThread.java -@@ -0,0 +0,0 @@ import java.io.IOException; - import java.io.OutputStream; - import java.util.logging.Level; - import java.util.logging.Logger; --import jline.console.ConsoleReader; -+//import jline.console.ConsoleReader; - import org.bukkit.craftbukkit.Main; --import org.fusesource.jansi.Ansi; --import org.fusesource.jansi.Ansi.Erase; -+//import org.fusesource.jansi.Ansi; -+//import org.fusesource.jansi.Ansi.Erase; - --public class TerminalConsoleWriterThread extends Thread { -+public class TerminalConsoleWriterThread /*extends Thread*/ {/* // Paper - disable - private final ConsoleReader reader; - private final OutputStream output; - -@@ -0,0 +0,0 @@ public class TerminalConsoleWriterThread extends Thread { - Logger.getLogger(TerminalConsoleWriterThread.class.getName()).log(Level.SEVERE, null, ex); - } - } -- } -+ }*/ - } -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/resources/log4j2.component.properties -@@ -0,0 +1 @@ -+log4j.skipJansi=true -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -0,0 +0,0 @@ - - - -- -- -- - - - -- -- -- -+ -+ -+ - -- -+ - - - -@@ -0,0 +0,0 @@ - - - -- - -- - -+ - - - diff --git a/Spigot-Server-Patches/Use-UserCache-for-player-heads.patch b/Spigot-Server-Patches/Use-UserCache-for-player-heads.patch deleted file mode 100644 index 4fa377ff8f..0000000000 --- a/Spigot-Server-Patches/Use-UserCache-for-player-heads.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Techcable -Date: Wed, 2 Mar 2016 23:42:37 -0600 -Subject: [PATCH] Use UserCache for player heads - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java -@@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - if (name == null) { - setProfile(null); - } else { -- setProfile(new GameProfile(null, name)); -+ // Paper start - Use Online Players Skull -+ GameProfile newProfile = null; -+ net.minecraft.server.EntityPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayer(name); -+ if (player != null) newProfile = player.getProfile(); -+ if (newProfile == null) newProfile = new GameProfile(null, name); -+ setProfile(newProfile); -+ // Paper end - } - - return true; diff --git a/Spigot-Server-Patches/Use-Vanilla-Minecart-Speeds.patch b/Spigot-Server-Patches/Use-Vanilla-Minecart-Speeds.patch deleted file mode 100644 index 303baa58c3..0000000000 --- a/Spigot-Server-Patches/Use-Vanilla-Minecart-Speeds.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 8 Nov 2018 21:33:09 -0500 -Subject: [PATCH] Use Vanilla Minecart Speeds - -CraftBukkit changed the values on flying speed, restore back to vanilla - -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityMinecartAbstract extends Entity { - private double derailedX = 0.5; - private double derailedY = 0.5; - private double derailedZ = 0.5; -- private double flyingX = 0.95; -- private double flyingY = 0.95; -- private double flyingZ = 0.95; -+ private double flyingX = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingY = 0.949999988079071D; // Paper - restore vanilla precision -+ private double flyingZ = 0.949999988079071D; // Paper - restore vanilla precision - public double maxSpeed = 0.4D; - // CraftBukkit end - diff --git a/Spigot-Server-Patches/Use-a-Queue-for-Queueing-Commands.patch b/Spigot-Server-Patches/Use-a-Queue-for-Queueing-Commands.patch deleted file mode 100644 index 21283b666f..0000000000 --- a/Spigot-Server-Patches/Use-a-Queue-for-Queueing-Commands.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 12 Aug 2018 02:33:39 -0400 -Subject: [PATCH] Use a Queue for Queueing Commands - -Lists are bad as Queues mmmkay. - -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 IMinecraftServer - - private static final Logger LOGGER = LogManager.getLogger(); - private static final Pattern k = Pattern.compile("^[a-fA-F0-9]{40}$"); -- private final List serverCommandQueue = Collections.synchronizedList(Lists.newArrayList()); -+ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue - private RemoteStatusListener remoteStatusListener; - public final RemoteControlCommandListener remoteControlCommandListener; - private RemoteControlListener remoteControlListener; -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - - public void handleCommandQueue() { - MinecraftTimings.serverCommandTimer.startTiming(); // Spigot -- while (!this.serverCommandQueue.isEmpty()) { -- ServerCommand servercommand = (ServerCommand) this.serverCommandQueue.remove(0); -+ // Paper start - use proper queue -+ ServerCommand servercommand; -+ while ((servercommand = this.serverCommandQueue.poll()) != null) { -+ // Paper end - - // CraftBukkit start - ServerCommand for preprocessing - ServerCommandEvent event = new ServerCommandEvent(console, servercommand.command); diff --git a/Spigot-Server-Patches/Use-a-Shared-Random-for-Entities.patch b/Spigot-Server-Patches/Use-a-Shared-Random-for-Entities.patch deleted file mode 100644 index 34cb1acd06..0000000000 --- a/Spigot-Server-Patches/Use-a-Shared-Random-for-Entities.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 22 Mar 2016 00:33:47 -0400 -Subject: [PATCH] Use a Shared Random for Entities - -Reduces memory usage and provides ensures more randomness, Especially since a lot of garbage entity objects get created. - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; - } - -+ // Paper start -+ public static Random SHARED_RANDOM = new Random() { -+ private boolean locked = false; -+ @Override -+ public synchronized void setSeed(long seed) { -+ if (locked) { -+ LogManager.getLogger().error("Ignoring setSeed on Entity.SHARED_RANDOM", new Throwable()); -+ } else { -+ super.setSeed(seed); -+ locked = true; -+ } -+ } -+ }; -+ // Paper end -+ - private CraftEntity bukkitEntity; - - public CraftEntity getBukkitEntity() { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - this.x = Vec3D.ORIGIN; - this.am = 1.0F; - this.an = 1.0F; -- this.random = new Random(); -+ this.random = SHARED_RANDOM; // Paper - this.fireTicks = -this.getMaxFireTicks(); - this.M = new Object2DoubleArrayMap(2); - this.justCreated = true; diff --git a/Spigot-Server-Patches/Use-asynchronous-Log4j-2-loggers.patch b/Spigot-Server-Patches/Use-asynchronous-Log4j-2-loggers.patch deleted file mode 100644 index 56d85b045d..0000000000 --- a/Spigot-Server-Patches/Use-asynchronous-Log4j-2-loggers.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Minecrell -Date: Tue, 17 Jul 2018 16:42:17 +0200 -Subject: [PATCH] Use asynchronous Log4j 2 loggers - - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - log4j-iostreams - compile - -+ -+ -+ com.lmax -+ disruptor -+ 3.4.2 -+ runtime -+ - - org.ow2.asm - asm -diff --git a/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/log/LogFullPolicy.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.log; -+ -+import org.apache.logging.log4j.Level; -+import org.apache.logging.log4j.core.async.AsyncQueueFullPolicy; -+import org.apache.logging.log4j.core.async.EventRoute; -+ -+public final class LogFullPolicy implements AsyncQueueFullPolicy { -+ -+ /* -+ * Prevents log calls being logged out of order when the log queue is full. -+ */ -+ -+ @Override -+ public EventRoute getRoute(final long backgroundThreadId, final Level level) { -+ return EventRoute.ENQUEUE; -+ } -+} -diff --git a/src/main/resources/log4j2.component.properties b/src/main/resources/log4j2.component.properties -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/log4j2.component.properties -+++ b/src/main/resources/log4j2.component.properties -@@ -1 +1,3 @@ -+Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -+log4j2.AsyncQueueFullPolicy="com.destroystokyo.paper.log.LogFullPolicy" - log4j.skipJansi=true diff --git a/Spigot-Server-Patches/Use-distance-map-to-optimise-entity-tracker.patch b/Spigot-Server-Patches/Use-distance-map-to-optimise-entity-tracker.patch deleted file mode 100644 index cb657d3f50..0000000000 --- a/Spigot-Server-Patches/Use-distance-map-to-optimise-entity-tracker.patch +++ /dev/null @@ -1,413 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 5 May 2020 20:18:05 -0700 -Subject: [PATCH] Use distance map to optimise entity tracker - -Use the distance map to find candidate players for tracking. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = this.tracker.getPassengers(); - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutMapChunk; - import net.minecraft.network.protocol.game.PacketPlayOutMount; - import net.minecraft.network.protocol.game.PacketPlayOutViewCentre; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.WorldLoadListener; - import net.minecraft.util.CSVWriter; - import net.minecraft.util.EntitySlice; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - // Paper start - distance maps - private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -+ // Paper start - use distance map to optimise tracker -+ public static boolean isLegacyTrackingEntity(Entity entity) { -+ return entity.isLegacyTrackingEntity; -+ } -+ -+ // inlined EnumMap, TrackingRange.TrackingRangeType -+ static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); -+ public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; -+ final int[] entityTrackerTrackRanges; -+ -+ private int convertSpigotRangeToVanilla(final int vanilla) { -+ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); -+ } -+ // Paper end - use distance map to optimise tracker - - void addPlayerToDistanceMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); - int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - void removePlayerFromDistanceMaps(EntityPlayer player) { -- -+ // Paper start - use distance map to optimise tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ this.playerEntityTrackerTrackMaps[i].remove(player); -+ } -+ // Paper end - use distance map to optimise tracker - } - - void updateMaps(EntityPlayer player) { - int chunkX = MCUtil.getChunkCoordinate(player.locX()); - int chunkZ = MCUtil.getChunkCoordinate(player.locZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -+ // Paper start - use distance map to optimise entity tracker -+ for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -+ com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -+ int trackRange = this.entityTrackerTrackRanges[i]; -+ -+ trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - // Paper end - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); - this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ // Paper start - use distance map to optimise entity tracker -+ this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; -+ this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; -+ -+ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.world.spigotConfig; -+ -+ for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { -+ org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; -+ int configuredSpigotValue; -+ switch (trackingRangeType) { -+ case PLAYER: -+ configuredSpigotValue = spigotWorldConfig.playerTrackingRange; -+ break; -+ case ANIMAL: -+ configuredSpigotValue = spigotWorldConfig.animalTrackingRange; -+ break; -+ case MONSTER: -+ configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; -+ break; -+ case MISC: -+ configuredSpigotValue = spigotWorldConfig.miscTrackingRange; -+ break; -+ case OTHER: -+ configuredSpigotValue = spigotWorldConfig.otherTrackingRange; -+ break; -+ case ENDERDRAGON: -+ configuredSpigotValue = EntityTypes.ENDER_DRAGON.getChunkRange() * 16; -+ break; -+ default: -+ throw new IllegalStateException("Missing case for enum " + trackingRangeType); -+ } -+ configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); -+ -+ int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); -+ this.entityTrackerTrackRanges[ordinal] = trackRange; -+ -+ this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ } -+ // Paper end - use distance map to optimise entity tracker - } - - public void updatePlayerMobTypeMap(Entity entity) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - public void movePlayer(EntityPlayer entityplayer) { -- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); -- -- while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -- -- if (playerchunkmap_entitytracker.tracker == entityplayer) { -- playerchunkmap_entitytracker.track(this.world.getPlayers()); -- } else { -- playerchunkmap_entitytracker.updatePlayer(entityplayer); -- } -- } -+ // Paper - delay this logic for the entity tracker tick, no need to duplicate it - - int i = MathHelper.floor(entityplayer.locX()) >> 4; - int j = MathHelper.floor(entityplayer.locZ()) >> 4; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.trackedEntities.put(entity.getId(), playerchunkmap_entitytracker); -- playerchunkmap_entitytracker.track(this.world.getPlayers()); -+ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players - if (entity instanceof EntityPlayer) { - EntityPlayer entityplayer = (EntityPlayer) entity; - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - entity.tracker = null; // Paper - We're no longer tracked - } - -+ // Paper start - optimised tracker -+ private final void processTrackQueue() { -+ this.world.timings.tracker1.startTiming(); -+ try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { -+ // update tracker entry -+ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); -+ } -+ } finally { -+ this.world.timings.tracker1.stopTiming(); -+ } -+ -+ -+ this.world.timings.tracker2.startTiming(); -+ try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { -+ tracker.trackerEntry.tick(); -+ } -+ } finally { -+ this.world.timings.tracker2.stopTiming(); -+ } -+ } -+ // Paper end - optimised tracker -+ - protected void g() { -+ // Paper start - optimized tracker -+ if (true) { -+ this.processTrackQueue(); -+ return; -+ } -+ // Paper end - optimized tracker - List list = Lists.newArrayList(); - List list1 = this.world.getPlayers(); - -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PacketDebug.a(this.world, chunk.getPos()); - List list = Lists.newArrayList(); - List list1 = Lists.newArrayList(); -- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); -+ // Paper start - optimise entity tracker -+ // use the chunk entity list, not the whole trackedEntities map... -+ Entity[] entities = chunk.entities.getRawData(); -+ for (int i = 0, size = chunk.entities.size(); i < size; ++i) { -+ Entity entity = entities[i]; -+ if (entity == entityplayer) { -+ continue; -+ } -+ PlayerChunkMap.EntityTracker tracker = this.trackedEntities.get(entity.getId()); -+ if (tracker != null) { // dumb plugins... move on... -+ tracker.updatePlayer(entityplayer); -+ } - -- while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -- Entity entity = playerchunkmap_entitytracker.tracker; -+ // keep the vanilla logic here - this is REQUIRED or else passengers and their vehicles disappear! -+ // (and god knows what the leash thing is) - -- if (entity != entityplayer && entity.chunkX == chunk.getPos().x && entity.chunkZ == chunk.getPos().z) { -- playerchunkmap_entitytracker.updatePlayer(entityplayer); -- if (entity instanceof EntityInsentient && ((EntityInsentient) entity).getLeashHolder() != null) { -- list.add(entity); -- } -+ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).getLeashHolder() != null) { -+ list.add(entity); -+ } - -- if (!entity.getPassengers().isEmpty()) { -- list1.add(entity); -- } -+ if (!entity.getPassengers().isEmpty()) { -+ list1.add(entity); - } - } -+ // Paper end - optimise entity tracker - - Iterator iterator; - Entity entity1; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - public class EntityTracker { - -- private final EntityTrackerEntry trackerEntry; -+ final EntityTrackerEntry trackerEntry; // Paper - private -> package private - private final Entity tracker; - private final int trackingDistance; - private SectionPosition e; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.e = SectionPosition.a(entity); - } - -+ // Paper start - use distance map to optimise tracker -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; -+ -+ final void updatePlayers(com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newTrackerCandidates) { -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet oldTrackerCandidates = this.lastTrackerCandidates; -+ this.lastTrackerCandidates = newTrackerCandidates; -+ -+ if (newTrackerCandidates != null) { -+ Object[] rawData = newTrackerCandidates.getBackingSet(); -+ for (int i = 0, len = rawData.length; i < len; ++i) { -+ Object raw = rawData[i]; -+ if (!(raw instanceof EntityPlayer)) { -+ continue; -+ } -+ EntityPlayer player = (EntityPlayer)raw; -+ this.updatePlayer(player); -+ } -+ } -+ -+ if (oldTrackerCandidates == newTrackerCandidates) { -+ // this is likely the case. -+ // means there has been no range changes, so we can just use the above for tracking. -+ return; -+ } -+ -+ // stuff could have been removed, so we need to check the trackedPlayers set -+ // for players that were removed -+ -+ for (EntityPlayer player : this.trackedPlayers.toArray(new EntityPlayer[0])) { // avoid CME -+ if (newTrackerCandidates == null || !newTrackerCandidates.contains(player)) { -+ this.updatePlayer(player); -+ } -+ } -+ } -+ // Paper end - use distance map to optimise tracker -+ - public boolean equals(Object object) { - return object instanceof PlayerChunkMap.EntityTracker ? ((PlayerChunkMap.EntityTracker) object).tracker.getId() == this.tracker.getId() : false; - } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int j = entity.getEntityType().getChunkRange() * 16; - j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - -- if (j > i) { -+ if (j < i) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic - i = j; - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunkMap; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - -+ // Paper start - optimise entity tracking -+ final org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = org.spigotmc.TrackingRange.getTrackingRangeType(this); -+ -+ public boolean isLegacyTrackingEntity = false; -+ -+ public final void setLegacyTrackingEntity(final boolean isLegacyTrackingEntity) { -+ this.isLegacyTrackingEntity = isLegacyTrackingEntity; -+ } -+ -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { -+ return ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] -+ .getObjectsInRange(MCUtil.getCoordinateKey(this)); -+ } -+ // Paper end - optimise entity tracking -+ - public Entity(EntityTypes entitytypes, World world) { - this.id = Entity.entityCount.incrementAndGet(); - this.passengers = Lists.newArrayList(); -diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/TrackingRange.java -+++ b/src/main/java/org/spigotmc/TrackingRange.java -@@ -0,0 +0,0 @@ public class TrackingRange - */ - public static int getEntityTrackingRange(Entity entity, int defaultRange) - { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return defaultRange; // Paper - enderdragon is exempt - SpigotWorldConfig config = entity.world.spigotConfig; - if ( entity instanceof EntityPlayer ) - { -@@ -0,0 +0,0 @@ public class TrackingRange - return config.miscTrackingRange; - } else - { -- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return ((net.minecraft.server.level.WorldServer)(entity.getWorld())).getChunkProvider().playerChunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt - return config.otherTrackingRange; - } - } -+ -+ // Paper start - optimise entity tracking -+ // copied from above, TODO check on update -+ public static TrackingRangeType getTrackingRangeType(Entity entity) -+ { -+ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EntityEnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt -+ if ( entity instanceof EntityPlayer ) -+ { -+ return TrackingRangeType.PLAYER; -+ // Paper start - Simplify and set water mobs to animal tracking range -+ } -+ switch (entity.activationType) { -+ case RAIDER: -+ case MONSTER: -+ case FLYING_MONSTER: -+ return TrackingRangeType.MONSTER; -+ case WATER: -+ case VILLAGER: -+ case ANIMAL: -+ return TrackingRangeType.ANIMAL; -+ case MISC: -+ } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) -+ // Paper end -+ { -+ return TrackingRangeType.MISC; -+ } else -+ { -+ return TrackingRangeType.OTHER; -+ } -+ } -+ -+ public static enum TrackingRangeType { -+ PLAYER, -+ ANIMAL, -+ MONSTER, -+ MISC, -+ OTHER, -+ ENDERDRAGON; -+ } -+ // Paper end - optimise entity tracking - } diff --git a/Spigot-Server-Patches/Use-getChunkIfLoadedImmediately-in-places.patch b/Spigot-Server-Patches/Use-getChunkIfLoadedImmediately-in-places.patch deleted file mode 100644 index f866293450..0000000000 --- a/Spigot-Server-Patches/Use-getChunkIfLoadedImmediately-in-places.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 8 Jul 2019 00:13:36 -0700 -Subject: [PATCH] Use getChunkIfLoadedImmediately in places - -This prevents us from hitting chunk loads for chunks at or less-than -ticket level 33 (yes getChunkIfLoaded will actually perform a chunk -load in that case). - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - } - - @Override public Chunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI -- return this.chunkProvider.getChunkAt(x, z, false); -+ return this.chunkProvider.getChunkAtIfLoadedImmediately(x, z); // Paper - } - - // Paper start - Asynchronous IO -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - speed = player.abilities.walkSpeed * 10f; - } - // Paper start - Prevent moving into unloaded chunks -- if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && !worldserver.isChunkLoaded((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { -+ if (player.world.paperConfig.preventMovingIntoUnloadedChunks && (this.player.locX() != toX || this.player.locZ() != toZ) && worldserver.getChunkIfLoadedImmediately((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4) == null) { // Paper - use getIfLoadedImmediately - this.internalTeleport(this.player.locX(), this.player.locY(), this.player.locZ(), this.player.yaw, this.player.pitch, Collections.emptySet()); - return; - } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return (CraftServer) Bukkit.getServer(); - } - -+ // Paper start -+ @Override -+ public boolean isChunkLoaded(int x, int z) { -+ return ((WorldServer)this).getChunkIfLoaded(x, z) != null; -+ } -+ // Paper end -+ - public ResourceKey getTypeKey() { - return typeKey; - } -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - } - - public boolean p(BlockPosition blockposition) { -- return isOutsideWorld(blockposition) ? false : this.getChunkProvider().b(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return isOutsideWorld(blockposition) ? false : isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - } - - public boolean a(BlockPosition blockposition, Entity entity, EnumDirection enumdirection) { - if (isOutsideWorld(blockposition)) { - return false; - } else { -- IChunkAccess ichunkaccess = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); -+ IChunkAccess ichunkaccess = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - - return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a((IBlockAccess) this, blockposition, entity, enumdirection); - } -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - for (int i1 = i; i1 < j; ++i1) { - for (int j1 = k; j1 < l; ++j1) { -- Chunk chunk = ichunkprovider.a(i1, j1); -+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper - - if (chunk != null) { - chunk.a(oclass, axisalignedbb, list, predicate); -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- if ( world.getWorld().isChunkLoaded( i1, j1 ) ) -+ Chunk chunk = (Chunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ if ( chunk != null ) - { -- activateChunkEntities( world.getChunkAt( i1, j1 ) ); -+ activateChunkEntities( chunk ); - } - } - } diff --git a/Spigot-Server-Patches/Use-proper-max-length-when-serialising-BungeeCord-te.patch b/Spigot-Server-Patches/Use-proper-max-length-when-serialising-BungeeCord-te.patch deleted file mode 100644 index 6f67cca092..0000000000 --- a/Spigot-Server-Patches/Use-proper-max-length-when-serialising-BungeeCord-te.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park -Date: Wed, 20 Mar 2019 21:19:29 -0700 -Subject: [PATCH] Use proper max length when serialising BungeeCord text - component - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutChat.java -@@ -0,0 +0,0 @@ import net.minecraft.network.chat.IChatBaseComponent; - import net.minecraft.network.protocol.Packet; - - public class PacketPlayOutChat implements Packet { -- -+ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper - private IChatBaseComponent a; - public net.kyori.adventure.text.Component adventure$message; // Paper - public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot -@@ -0,0 +0,0 @@ public class PacketPlayOutChat implements Packet { - //packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(components)); // Paper - comment, replaced with below - // Paper start - don't nest if we don't need to so that we can preserve formatting - if (this.components.length == 1) { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length - } else { -- packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); -+ packetdataserializer.a(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length - } - // Paper end - } else { diff --git a/Spigot-Server-Patches/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/Spigot-Server-Patches/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch deleted file mode 100644 index 6e9a979007..0000000000 --- a/Spigot-Server-Patches/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 7 Jun 2020 19:25:13 -0400 -Subject: [PATCH] Use seed based lookup for Treasure Maps - Fixes lag from - carto/sunken maps - - -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - this.worldDataServer.setThundering(flag1); - } - -- @Override -- public BiomeBase a(int i, int j, int k) { -+ public BiomeBase getBiomeBySeed(int i, int j, int k) { return a(i, j, k); } // Paper - OBFHELPER -+ @Override public BiomeBase a(int i, int j, int k) { - return this.getChunkProvider().getChunkGenerator().getWorldChunkManager().getBiome(i, j, k); - } - -diff --git a/src/main/java/net/minecraft/world/item/ItemWorldMap.java b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemWorldMap.java -+++ b/src/main/java/net/minecraft/world/item/ItemWorldMap.java -@@ -0,0 +0,0 @@ public class ItemWorldMap extends ItemWorldMapBase { - - for (l = 0; l < 128 * i; ++l) { - for (i1 = 0; i1 < 128 * i; ++i1) { -- abiomebase[l * 128 * i + i1] = worldserver.getBiome(new BlockPosition((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); -+ abiomebase[l * 128 * i + i1] = worldserver.getBiomeBySeed((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper - } - } - diff --git a/Spigot-Server-Patches/Validate-PickItem-Packet-and-kick-for-invalid.patch b/Spigot-Server-Patches/Validate-PickItem-Packet-and-kick-for-invalid.patch deleted file mode 100644 index 25b736c299..0000000000 --- a/Spigot-Server-Patches/Validate-PickItem-Packet-and-kick-for-invalid.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 2 May 2020 03:09:46 -0400 -Subject: [PATCH] Validate PickItem Packet and kick for invalid - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - @Override - public void a(PacketPlayInPickItem packetplayinpickitem) { - PlayerConnectionUtils.ensureMainThread(packetplayinpickitem, this, this.player.getWorldServer()); -- this.player.inventory.c(packetplayinpickitem.b()); -+ // Paper start - validate pick item position -+ if (!(packetplayinpickitem.b() >= 0 && packetplayinpickitem.b() < this.player.inventory.items.size())) { -+ PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", this.player.getDisplayName().getString()); -+ this.disconnect("Invalid hotbar selection (Hacking?)"); -+ return; -+ } -+ this.player.inventory.c(packetplayinpickitem.b()); // Paper - Diff above if changed -+ // Paper end - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, this.player.inventory.itemInHandIndex, this.player.inventory.getItem(this.player.inventory.itemInHandIndex))); - this.player.playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, packetplayinpickitem.b(), this.player.inventory.getItem(packetplayinpickitem.b()))); - this.player.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(this.player.inventory.itemInHandIndex)); diff --git a/Spigot-Server-Patches/Validate-tripwire-hook-placement-before-update.patch b/Spigot-Server-Patches/Validate-tripwire-hook-placement-before-update.patch deleted file mode 100644 index fe65c99477..0000000000 --- a/Spigot-Server-Patches/Validate-tripwire-hook-placement-before-update.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sat, 7 Mar 2020 00:07:51 +0000 -Subject: [PATCH] Validate tripwire hook placement before update - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockTripwireHook.java -@@ -0,0 +0,0 @@ public class BlockTripwireHook extends Block { - - this.a(world, blockposition, flag4, flag5, flag2, flag3); - if (!flag) { -+ if (world.getType(blockposition).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate - world.setTypeAndData(blockposition, (IBlockData) iblockdata3.set(BlockTripwireHook.FACING, enumdirection), 3); - if (flag1) { - this.a(world, blockposition, enumdirection); diff --git a/Spigot-Server-Patches/Vanished-players-don-t-have-rights.patch b/Spigot-Server-Patches/Vanished-players-don-t-have-rights.patch deleted file mode 100644 index a13342fd2b..0000000000 --- a/Spigot-Server-Patches/Vanished-players-don-t-have-rights.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Hugo Manrique -Date: Mon, 23 Jul 2018 14:22:26 +0200 -Subject: [PATCH] Vanished players don't have rights - - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private static double e = 1.0D; - private final EntityTypes f; - private int id; -- public boolean i; -+ public boolean i; public final boolean blocksEntitySpawning() { return this.i; } // Paper - OBFHELPER - public final List passengers; - protected int j; - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/IProjectile.java -@@ -0,0 +0,0 @@ import java.util.Iterator; - import java.util.UUID; - import javax.annotation.Nullable; - import net.minecraft.nbt.NBTTagCompound; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.util.MathHelper; - import net.minecraft.world.entity.Entity; -@@ -0,0 +0,0 @@ public abstract class IProjectile extends Entity { - protected boolean a(Entity entity) { - if (!entity.isSpectator() && entity.isAlive() && entity.isInteractable()) { - Entity entity1 = this.getShooter(); -- -+ // Paper start - Cancel hit for vanished players -+ if (entity1 instanceof EntityPlayer && entity instanceof EntityPlayer) { -+ org.bukkit.entity.Player collided = (org.bukkit.entity.Player) entity.getBukkitEntity(); -+ org.bukkit.entity.Player shooter = (org.bukkit.entity.Player) entity1.getBukkitEntity(); -+ if (!shooter.canSee(collided)) return false; -+ } - return entity1 == null || this.d || !entity1.isSameVehicle(entity); -+ // Paper end - } else { - return false; - } -diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemBlock.java -+++ b/src/main/java/net/minecraft/world/item/ItemBlock.java -@@ -0,0 +0,0 @@ public class ItemBlock extends Item { - EntityHuman entityhuman = blockactioncontext.getEntity(); - VoxelShapeCollision voxelshapecollision = entityhuman == null ? VoxelShapeCollision.a() : VoxelShapeCollision.a((Entity) entityhuman); - // CraftBukkit start - store default return -- boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && blockactioncontext.getWorld().a(iblockdata, blockactioncontext.getClickPosition(), voxelshapecollision); -+ World world = blockactioncontext.getWorld(); // Paper -+ boolean defaultReturn = (!this.isCheckCollisions() || iblockdata.canPlace(blockactioncontext.getWorld(), blockactioncontext.getClickPosition())) && world.checkEntityCollision(iblockdata, entityhuman, voxelshapecollision, blockactioncontext.getClickPosition(), true); // Paper - org.bukkit.entity.Player player = (blockactioncontext.getEntity() instanceof EntityPlayer) ? (org.bukkit.entity.Player) blockactioncontext.getEntity().getBukkitEntity() : null; - - BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(blockactioncontext.getWorld(), blockactioncontext.getClickPosition()), player, CraftBlockData.fromData(iblockdata), defaultReturn); -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.ResourceKey; - import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.PlayerChunk; - import net.minecraft.sounds.SoundCategory; - import net.minecraft.sounds.SoundEffect; -@@ -0,0 +0,0 @@ import net.minecraft.world.level.saveddata.maps.WorldMap; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.level.storage.WorldDataMutable; - import net.minecraft.world.phys.AxisAlignedBB; -+import net.minecraft.world.phys.shapes.OperatorBoolean; -+import net.minecraft.world.phys.shapes.VoxelShape; -+import net.minecraft.world.phys.shapes.VoxelShapeCollision; -+import net.minecraft.world.phys.shapes.VoxelShapes; - import net.minecraft.world.scores.Scoreboard; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); - } - -+ // Paper start -+ // ret true if no collision -+ public final boolean checkEntityCollision(IBlockData data, Entity source, VoxelShapeCollision voxelshapedcollision, -+ BlockPosition position, boolean checkCanSee) { -+ // Copied from IWorldReader#a(IBlockData, BlockPosition, VoxelShapeCollision) & EntityAccess#a(Entity, VoxelShape) -+ VoxelShape voxelshape = data.getCollisionShape(this, position, voxelshapedcollision); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ voxelshape = voxelshape.offset((double) position.getX(), (double) position.getY(), (double) position.getZ()); -+ if (voxelshape.isEmpty()) { -+ return true; -+ } -+ -+ List entities = this.getEntities(null, voxelshape.getBoundingBox()); -+ for (int i = 0, len = entities.size(); i < len; ++i) { -+ Entity entity = entities.get(i); -+ -+ if (checkCanSee && source instanceof EntityPlayer && entity instanceof EntityPlayer -+ && !((EntityPlayer) source).getBukkitEntity().canSee(((EntityPlayer) entity).getBukkitEntity())) { -+ continue; -+ } -+ -+ // !entity1.dead && entity1.i && (entity == null || !entity1.x(entity)); -+ // elide the last check since vanilla calls with entity = null -+ // only we care about the source for the canSee check -+ if (entity.dead || !entity.blocksEntitySpawning()) { -+ continue; -+ } -+ -+ if (VoxelShapes.applyOperation(voxelshape, VoxelShapes.of(entity.getBoundingBox()), OperatorBoolean.AND)) { -+ return false; -+ } -+ } -+ -+ return true; -+ } -+ // Paper end -+ - @Override - public boolean s_() { - return this.isClientSide; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -0,0 +0,0 @@ public abstract class BlockBase { - return this.a != null ? this.a.b : this.b(iblockaccess, blockposition, VoxelShapeCollision.a()); - } - -+ public final VoxelShape getCollisionShape(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { return this.b(iblockaccess, blockposition, voxelshapecollision); } // Paper - OBFHELPER - public VoxelShape b(IBlockAccess iblockaccess, BlockPosition blockposition, VoxelShapeCollision voxelshapecollision) { - return this.getBlock().c(this.p(), iblockaccess, blockposition, voxelshapecollision); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShape.java -@@ -0,0 +0,0 @@ public abstract class VoxelShape { - return this.a.a(); - } - -+ public final VoxelShape offset(double x, double y, double z) { return this.a(x, y, z); } // Paper - OBFHELPER - public VoxelShape a(double d0, double d1, double d2) { - return (VoxelShape) (this.isEmpty() ? VoxelShapes.a() : new VoxelShapeArray(this.a, new DoubleListOffset(this.a(EnumDirection.EnumAxis.X), d0), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Y), d1), new DoubleListOffset(this.a(EnumDirection.EnumAxis.Z), d2))); - } -diff --git a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -+++ b/src/main/java/net/minecraft/world/phys/shapes/VoxelShapes.java -@@ -0,0 +0,0 @@ public final class VoxelShapes { - return a(new AxisAlignedBB(d0, d1, d2, d3, d4, d5)); - } - -+ public static final VoxelShape of(AxisAlignedBB axisAlignedbb) { return VoxelShapes.a(axisAlignedbb); } // Paper - OBFHELPER - public static VoxelShape a(AxisAlignedBB axisalignedbb) { - int i = a(axisalignedbb.minX, axisalignedbb.maxX); - int j = a(axisalignedbb.minY, axisalignedbb.maxY); -@@ -0,0 +0,0 @@ public final class VoxelShapes { - } - } - -+ public static final boolean applyOperation(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { return VoxelShapes.c(voxelshape, voxelshape1, operatorboolean); } // Paper - OBFHELPER - public static boolean c(VoxelShape voxelshape, VoxelShape voxelshape1, OperatorBoolean operatorboolean) { - if (operatorboolean.apply(false, false)) { - throw (IllegalArgumentException) SystemUtils.c((Throwable) (new IllegalArgumentException())); -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - Projectile projectile = (Projectile) entity.getBukkitEntity(); - org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity(); - com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided); -+ -+ if (projectile.getShooter() instanceof Player && collided instanceof Player) { -+ if (!((Player) projectile.getShooter()).canSee((Player) collided)) { -+ event.setCancelled(true); -+ return event; -+ } -+ } -+ - Bukkit.getPluginManager().callEvent(event); - return event; - } diff --git a/Spigot-Server-Patches/Vex-getSummoner-API.patch b/Spigot-Server-Patches/Vex-getSummoner-API.patch deleted file mode 100644 index 8e6eba25ae..0000000000 --- a/Spigot-Server-Patches/Vex-getSummoner-API.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 4 Jul 2018 15:30:22 -0400 -Subject: [PATCH] Vex#getSummoner API - -Get's the NPC that summoned this Vex - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityVex.java -@@ -0,0 +0,0 @@ public class EntityVex extends EntityMonster { - - } - -+ public EntityInsentient getOwner() { return eK(); } // Paper - OBFHELPER - public EntityInsentient eK() { - return this.c; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -@@ -0,0 +0,0 @@ public class CraftVex extends CraftMonster implements Vex { - return (EntityVex) super.getHandle(); - } - -+ // Paper start -+ public org.bukkit.entity.Mob getSummoner() { -+ net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); -+ return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; -+ } -+ // Paper end -+ - @Override - public String toString() { - return "CraftVex"; diff --git a/Spigot-Server-Patches/Villager-Restocks-API.patch b/Spigot-Server-Patches/Villager-Restocks-API.patch deleted file mode 100644 index fd1bf493cd..0000000000 --- a/Spigot-Server-Patches/Villager-Restocks-API.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: zbk -Date: Sun, 26 Apr 2020 23:49:01 -0400 -Subject: [PATCH] Villager Restocks API - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java -@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation - private long bA; - private int bB; - private long bC; -- private int bD; -+ private int bD; public int getRestocksToday(){ return this.bD; } public void setRestocksToday(int restocksToday){ this.bD = restocksToday; } // Paper OBFHELPER - private long bE; - private boolean bF; - private static final ImmutableList> bG = ImmutableList.of(MemoryModuleType.HOME, MemoryModuleType.JOB_SITE, MemoryModuleType.POTENTIAL_JOB_SITE, MemoryModuleType.MEETING_POINT, MemoryModuleType.MOBS, MemoryModuleType.VISIBLE_MOBS, MemoryModuleType.VISIBLE_VILLAGER_BABIES, MemoryModuleType.NEAREST_PLAYERS, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_TARGETABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.WALK_TARGET, new MemoryModuleType[]{MemoryModuleType.LOOK_TARGET, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.BREED_TARGET, MemoryModuleType.PATH, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_BED, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.SECONDARY_JOB_SITE, MemoryModuleType.HIDING_PLACE, MemoryModuleType.HEARD_BELL_TIME, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.LAST_SLEPT, MemoryModuleType.LAST_WOKEN, MemoryModuleType.LAST_WORKED_AT_POI, MemoryModuleType.GOLEM_DETECTED_RECENTLY}); -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -0,0 +0,0 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { - getHandle().setExperience(experience); - } - -+ // Paper start -+ @Override -+ public int getRestocksToday() { -+ return getHandle().getRestocksToday(); -+ } -+ -+ @Override -+ public void setRestocksToday(int restocksToday) { -+ getHandle().setRestocksToday(restocksToday); -+ } -+ // Paper end -+ - @Override - public boolean sleep(Location location) { - Preconditions.checkArgument(location != null, "Location cannot be null"); diff --git a/Spigot-Server-Patches/Villager-resetOffers.patch b/Spigot-Server-Patches/Villager-resetOffers.patch deleted file mode 100644 index e9f74fb34f..0000000000 --- a/Spigot-Server-Patches/Villager-resetOffers.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Mon, 7 Oct 2019 00:15:37 -0500 -Subject: [PATCH] Villager#resetOffers - - -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return this.tradingPlayer != null; - } - -+ // Paper start -+ public void resetOffers() { -+ this.trades = new MerchantRecipeList(); -+ this.updateTrades(); -+ } -+ // Paper end -+ - @Override - public MerchantRecipeList getOffers() { - if (this.trades == null) { -@@ -0,0 +0,0 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - return this.world; - } - -+ protected final void updateTrades() { eW(); } // Paper - OBFHELPER - protected abstract void eW(); - - protected void a(MerchantRecipeList merchantrecipelist, VillagerTrades.IMerchantRecipeOption[] avillagertrades_imerchantrecipeoption, int i) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -@@ -0,0 +0,0 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla - public HumanEntity getTrader() { - return getMerchant().getTrader(); - } -+ -+ // Paper start -+ @Override -+ public void resetOffers() { -+ getHandle().resetOffers(); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/Wait-for-Async-Tasks-during-shutdown.patch b/Spigot-Server-Patches/Wait-for-Async-Tasks-during-shutdown.patch deleted file mode 100644 index 0a4383c036..0000000000 --- a/Spigot-Server-Patches/Wait-for-Async-Tasks-during-shutdown.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 10 May 2020 22:16:17 -0400 -Subject: [PATCH] Wait for Async Tasks during shutdown - -Server.reload() had this logic to give time for tasks to shutdown, -however shutdown did not... - -Adds a 5 second grace period for any async tasks to finish and warns -if any are still running after that delay just as reload does. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0) { -+ try { -+ Thread.sleep(100); -+ } catch (InterruptedException e) {} -+ pollCount++; -+ } -+ -+ List overdueWorkers = getScheduler().getActiveWorkers(); -+ for (BukkitWorker worker : overdueWorkers) { -+ Plugin plugin = worker.getOwner(); -+ String author = ""; -+ if (plugin.getDescription().getAuthors().size() > 0) { -+ author = plugin.getDescription().getAuthors().get(0); -+ } -+ getLogger().log(Level.SEVERE, String.format( -+ "Nag author: '%s' of '%s' about the following: %s", -+ author, -+ plugin.getDescription().getName(), -+ "This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies." -+ )); -+ } -+ } -+ // Paper end -+ - @Override - public void reloadData() { - CommandReload.reload(console); diff --git a/Spigot-Server-Patches/WitchConsumePotionEvent.patch b/Spigot-Server-Patches/WitchConsumePotionEvent.patch deleted file mode 100644 index 42c57e080b..0000000000 --- a/Spigot-Server-Patches/WitchConsumePotionEvent.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:35:16 -0400 -Subject: [PATCH] WitchConsumePotionEvent - -Fires when a witch consumes the potion in their hand - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - - this.setSlot(EnumItemSlot.MAINHAND, ItemStack.b); - if (itemstack.getItem() == Items.POTION) { -- List list = PotionUtil.getEffects(itemstack); -+ // Paper start -+ com.destroystokyo.paper.event.entity.WitchConsumePotionEvent event = new com.destroystokyo.paper.event.entity.WitchConsumePotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); -+ -+ List list = event.callEvent() ? PotionUtil.getEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; -+ // Paper end - - if (list != null) { - Iterator iterator = list.iterator(); diff --git a/Spigot-Server-Patches/WitchReadyPotionEvent.patch b/Spigot-Server-Patches/WitchReadyPotionEvent.patch deleted file mode 100644 index 91078d117b..0000000000 --- a/Spigot-Server-Patches/WitchReadyPotionEvent.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 5 Jun 2018 22:47:26 -0400 -Subject: [PATCH] WitchReadyPotionEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - } - - if (potionregistry != null) { -- this.setSlot(EnumItemSlot.MAINHAND, PotionUtil.a(new ItemStack(Items.POTION), potionregistry)); -+ // Paper start -+ ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); -+ org.bukkit.inventory.ItemStack bukkitStack = com.destroystokyo.paper.event.entity.WitchReadyPotionEvent.process((org.bukkit.entity.Witch) this.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ this.setSlot(EnumItemSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); -+ // Paper end - this.bq = this.getItemInMainHand().k(); - this.v(true); - if (!this.isSilent()) { diff --git a/Spigot-Server-Patches/WitchThrowPotionEvent.patch b/Spigot-Server-Patches/WitchThrowPotionEvent.patch deleted file mode 100644 index 8b56223c86..0000000000 --- a/Spigot-Server-Patches/WitchThrowPotionEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 16 May 2018 20:44:58 -0400 -Subject: [PATCH] WitchThrowPotionEvent - -Fired when a witch throws a potion at a player - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityWitch.java -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - potionregistry = Potions.WEAKNESS; - } - -+ // Paper start -+ ItemStack potion = PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry); -+ com.destroystokyo.paper.event.entity.WitchThrowPotionEvent event = new com.destroystokyo.paper.event.entity.WitchThrowPotionEvent((org.bukkit.entity.Witch) this.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); -+ if (!event.callEvent()) { -+ return; -+ } -+ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); - EntityPotion entitypotion = new EntityPotion(this.world, this); -- -- entitypotion.setItem(PotionUtil.a(new ItemStack(Items.SPLASH_POTION), potionregistry)); -+ entitypotion.setItem(potion); -+ // Paper end - entitypotion.pitch -= -20.0F; - entitypotion.shoot(d0, d1 + (double) (f1 * 0.2F), d2, 0.75F, 8.0F); - if (!this.isSilent()) { diff --git a/Spigot-Server-Patches/Workaround-for-Client-Lag-Spikes-MC-162253.patch b/Spigot-Server-Patches/Workaround-for-Client-Lag-Spikes-MC-162253.patch deleted file mode 100644 index 6409f2945f..0000000000 --- a/Spigot-Server-Patches/Workaround-for-Client-Lag-Spikes-MC-162253.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 12 May 2020 23:02:43 +0200 -Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) - -When crossing certain chunk boundaries, the client needlessly -calculates light maps for chunk neighbours. In some specific map -configurations, these calculations cause a 500ms+ freeze on the Client. - -This patch basically serves as a workaround by sending light maps -to the client, so that it doesn't attempt to calculate them. -This mitigates the frametime impact to a minimum (but it's still there). - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.World; - import net.minecraft.world.level.chunk.Chunk; - import net.minecraft.world.level.chunk.ChunkConverter; - import net.minecraft.world.level.chunk.ChunkGenerator; -+import net.minecraft.world.level.chunk.ChunkSection; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.IChunkAccess; - import net.minecraft.world.level.chunk.ILightAccess; -@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public final void sendChunk(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { this.a(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void a(EntityPlayer entityplayer, Packet[] apacket, Chunk chunk) { - if (apacket[0] == null) { -+ // Paper start - add 8 for light fix workaround -+ if (apacket.length != 10) { // in case Plugins call sendChunk, resize -+ apacket = new Packet[10]; -+ } -+ // Paper end - apacket[0] = new PacketPlayOutMapChunk(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(entityplayer, chunk, 65535)); // Paper - Anti-Xray - Bypass - apacket[1] = new PacketPlayOutLightUpdate(chunk.getPos(), this.lightEngine, true); -+ -+ // Paper start - Fix MC-162253 -+ final int lightMask = getLightMask(chunk); -+ int i = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++i; -+ -+ if (!chunk.isNeighbourLoaded(x, z)) { -+ continue; -+ } -+ -+ final Chunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); -+ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); -+ -+ if (updateLightMask == 0) { -+ continue; -+ } -+ -+ apacket[i] = new PacketPlayOutLightUpdate(new ChunkCoordIntPair(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); -+ } -+ } -+ } -+ -+ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(entityplayer); -+ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(entityplayer); -+ -+ int j = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++j; -+ -+ Packet packet = apacket[j]; -+ if (packet == null) { -+ continue; -+ } -+ -+ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); -+ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); -+ -+ if (Math.max(distX, distZ) > viewDistance) { -+ continue; -+ } -+ entityplayer.playerConnection.sendPacket(packet); -+ } - } -+ // Paper end - Fix MC-162253 - - entityplayer.a(chunk.getPos(), apacket[0], apacket[1]); - PacketDebug.a(this.world, chunk.getPos()); -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - - // broadcast - Object[] backingSet = inRange.getBackingSet(); -- Packet[] chunkPackets = new Packet[2]; -+ Packet[] chunkPackets = new Packet[10]; - for (int index = 0, len = backingSet.length; index < len; ++index) { - Object temp = backingSet[index]; - if (!(temp instanceof EntityPlayer)) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkSection.java -@@ -0,0 +0,0 @@ public class ChunkSection { - return this.nonEmptyBlockCount == 0; - } - -+ public static boolean isEmpty(@Nullable ChunkSection chunksection) { return a(chunksection) ; } // Paper - OBFHELPER - public static boolean a(@Nullable ChunkSection chunksection) { - return chunksection == Chunk.a || chunksection.c(); - } diff --git a/Spigot-Server-Patches/Workaround-for-setting-passengers-on-players.patch b/Spigot-Server-Patches/Workaround-for-setting-passengers-on-players.patch deleted file mode 100644 index 1ff477848c..0000000000 --- a/Spigot-Server-Patches/Workaround-for-setting-passengers-on-players.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown <1254957+zachbr@users.noreply.github.com> -Date: Sun, 10 Apr 2016 03:23:32 -0500 -Subject: [PATCH] Workaround for setting passengers on players - -SPIGOT-1915 & GH-114 - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - return true; - } - -+ // Paper start - Ugly workaround for SPIGOT-1915 & GH-114 -+ @Override -+ public boolean setPassenger(org.bukkit.entity.Entity passenger) { -+ boolean wasSet = super.setPassenger(passenger); -+ if (wasSet) { -+ this.getHandle().playerConnection.sendPacket(new net.minecraft.network.protocol.game.PacketPlayOutMount(this.getHandle())); -+ } -+ return wasSet; -+ } -+ // Paper end -+ - @Override - public void setSneaking(boolean sneak) { - getHandle().setSneaking(sneak); diff --git a/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch deleted file mode 100644 index ecbdab0838..0000000000 --- a/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: connorhartley -Date: Mon, 7 Jan 2019 14:43:48 -0600 -Subject: [PATCH] Workaround for vehicle tracking issue on disconnect - - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public void p() { - this.ch = true; - this.ejectPassengers(); -+ -+ // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. -+ if (this.isPassenger() && this.getVehicle() instanceof EntityPlayer) { -+ this.stopRiding(); -+ } -+ // Paper end -+ - if (this.isSleeping()) { - this.wakeup(true, false); - } diff --git a/Spigot-Server-Patches/Zombie-API-breaking-doors.patch b/Spigot-Server-Patches/Zombie-API-breaking-doors.patch deleted file mode 100644 index ac8e982fca..0000000000 --- a/Spigot-Server-Patches/Zombie-API-breaking-doors.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 18 Nov 2020 11:32:46 -0800 -Subject: [PATCH] Zombie API - breaking doors - - -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityZombie.java -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - return (Boolean) this.getDataWatcher().get(EntityZombie.DROWN_CONVERTING); - } - -+ public boolean canBreakDoors() { return this.eU(); } // Paper - OBFHELPER - public boolean eU() { - return this.bs; - } - -+ public void setCanBreakDoors(boolean canBreakDoors) { this.u(canBreakDoors); } // Paper - OBFHELPER - public void u(boolean flag) { - if (this.eK() && PathfinderGoalUtil.a(this)) { - if (this.bs != flag) { -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -@@ -0,0 +0,0 @@ public class CraftZombie extends CraftMonster implements Zombie { - public void setShouldBurnInDay(boolean shouldBurnInDay) { - getHandle().setShouldBurnInDay(shouldBurnInDay); - } -+ -+ @Override -+ public boolean canBreakDoors() { -+ return getHandle().canBreakDoors(); -+ } -+ -+ @Override -+ public void setCanBreakDoors(boolean canBreakDoors) { -+ getHandle().setCanBreakDoors(canBreakDoors); -+ } - // Paper end - - @Override diff --git a/Spigot-Server-Patches/add-DragonEggFormEvent.patch b/Spigot-Server-Patches/add-DragonEggFormEvent.patch deleted file mode 100644 index ddca427665..0000000000 --- a/Spigot-Server-Patches/add-DragonEggFormEvent.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Mon, 25 Jan 2021 14:53:57 +0100 -Subject: [PATCH] add DragonEggFormEvent - - -diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -+++ b/src/main/java/net/minecraft/world/level/dimension/end/EnderDragonBattle.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature - import net.minecraft.world.phys.AxisAlignedBB; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -+import io.papermc.paper.event.block.DragonEggFormEvent; // Paper - DragonEggFormEvent - - public class EnderDragonBattle { - -@@ -0,0 +0,0 @@ public class EnderDragonBattle { - this.bossBattle.setVisible(false); - this.generateExitPortal(true); - this.n(); -+ // Paper start - DragonEggFormEvent -+ BlockPosition eggPosition = this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.getPosition()); -+ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.world, eggPosition); -+ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); -+ eggState.setData(Blocks.DRAGON_EGG.getBlockData()); -+ DragonEggFormEvent eggEvent = new DragonEggFormEvent(eggBlock, eggState, -+ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); -+ // Paper end - DragonEggFormEvent - if (this.world.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg -- this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ // Paper start - DragonEggFormEvent -+ //this.world.setTypeUpdate(this.world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, WorldGenEndTrophy.a), Blocks.DRAGON_EGG.getBlockData()); -+ } else { -+ eggEvent.setCancelled(true); -+ } -+ if (eggEvent.callEvent()) { -+ eggEvent.getNewState().update(true); - } -+ // Paper end - DragonEggFormEvent - - this.previouslyKilled = true; - this.dragonKilled = true; -diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/WorldGenEndTrophy.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.feature.configurations.WorldGenFeature - - public class WorldGenEndTrophy extends WorldGenerator { - -- public static final BlockPosition a = BlockPosition.ZERO; -+ public static final BlockPosition a = BlockPosition.ZERO; public static BlockPosition getPosition() { return a; } // Paper - OBFHELPER - private final boolean ab; - - public WorldGenEndTrophy(boolean flag) { -@@ -0,0 +0,0 @@ public class WorldGenEndTrophy extends WorldGenerator -Date: Thu, 22 Apr 2021 17:17:47 -0700 -Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent - - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - case PERFORM_RESPAWN: - if (this.player.viewingCredits) { - this.player.viewingCredits = false; -- this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, true); -+ this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, this.minecraftServer.getWorldServer(this.player.getSpawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument - CriterionTriggers.v.a(this.player, World.THE_END, World.OVERWORLD); - } else { - if (this.player.getHealth() > 0.0F) { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - return this.moveToWorld(entityplayer, this.server.getWorldServer(entityplayer.getSpawnDimension()), flag, null, true); - } - -+ // Paper start - public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation) { -+ return moveToWorld(entityplayer, worldserver, flag, location, avoidSuffocation, new org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag[0]); -+ } -+ -+ public EntityPlayer moveToWorld(EntityPlayer entityplayer, WorldServer worldserver, boolean flag, Location location, boolean avoidSuffocation, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { -+ // Paper end - entityplayer.stopRiding(); // CraftBukkit - this.players.remove(entityplayer); - this.playersByName.remove(entityplayer.getName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - Player respawnPlayer = cserver.getPlayer(entityplayer1); -- PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn); // Paper - Fix anchor respawn acting as a bed respawn from the end portal -+ PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !isAnchorSpawn, isAnchorSpawn, com.google.common.collect.ImmutableSet.builder().add(respawnFlags)); // Paper - Fix anchor respawn acting as a bed respawn from the end portal - cserver.getPluginManager().callEvent(respawnEvent); - // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { diff --git a/Spigot-Server-Patches/add-consumeFuel-to-FurnaceBurnEvent.patch b/Spigot-Server-Patches/add-consumeFuel-to-FurnaceBurnEvent.patch deleted file mode 100644 index 8be25a778a..0000000000 --- a/Spigot-Server-Patches/add-consumeFuel-to-FurnaceBurnEvent.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 16:45:28 -0700 -Subject: [PATCH] add consumeFuel to FurnaceBurnEvent - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityFurnace.java -@@ -0,0 +0,0 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I - if (this.isBurning() && furnaceBurnEvent.isBurning()) { - // CraftBukkit end - flag1 = true; -- if (!itemstack.isEmpty()) { -+ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper - Item item = itemstack.getItem(); - - itemstack.subtract(1); diff --git a/Spigot-Server-Patches/add-get-set-drop-chance-to-EntityEquipment.patch b/Spigot-Server-Patches/add-get-set-drop-chance-to-EntityEquipment.patch deleted file mode 100644 index 9b432c03f3..0000000000 --- a/Spigot-Server-Patches/add-get-set-drop-chance-to-EntityEquipment.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 22 Apr 2021 00:28:11 -0700 -Subject: [PATCH] add get-set drop chance to EntityEquipment - - -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java -@@ -0,0 +0,0 @@ public class CraftEntityEquipment implements EntityEquipment { - public void setBootsDropChance(float chance) { - setDropChance(EnumItemSlot.FEET, chance); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return getDropChance(CraftEquipmentSlot.getNMS(slot)); -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ setDropChance(CraftEquipmentSlot.getNMS(slot), chance); -+ } -+ // Paper end - - private void setDropChance(EnumItemSlot slot, float chance) { - if (slot == EnumItemSlot.MAINHAND || slot == EnumItemSlot.OFFHAND) { -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java -@@ -0,0 +0,0 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i - public void setBootsDropChance(float chance) { - throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); - } -+ // Paper start -+ @Override -+ public float getDropChance(EquipmentSlot slot) { -+ return 1; -+ } -+ -+ @Override -+ public void setDropChance(EquipmentSlot slot, float chance) { -+ throw new UnsupportedOperationException("Cannot set drop chance for PlayerInventory"); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/add-hand-to-BlockMultiPlaceEvent.patch b/Spigot-Server-Patches/add-hand-to-BlockMultiPlaceEvent.patch deleted file mode 100644 index 074230b73f..0000000000 --- a/Spigot-Server-Patches/add-hand-to-BlockMultiPlaceEvent.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sun, 1 Mar 2020 22:43:24 +0100 -Subject: [PATCH] add hand to BlockMultiPlaceEvent - - -diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -0,0 +0,0 @@ public class CraftEventFactory { - } - - org.bukkit.inventory.ItemStack item; -+ //Paper start - add hand to BlockMultiPlaceEvent -+ EquipmentSlot equipmentSlot; - if (hand == EnumHand.MAIN_HAND) { - item = player.getInventory().getItemInMainHand(); -+ equipmentSlot = EquipmentSlot.HAND; - } else { - item = player.getInventory().getItemInOffHand(); -+ equipmentSlot = EquipmentSlot.OFF_HAND; - } - -- BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild); -+ BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, item, player, canBuild, equipmentSlot); -+ //Paper end - craftServer.getPluginManager().callEvent(event); - - return event; diff --git a/Spigot-Server-Patches/add-isDeeplySleeping-to-HumanEntity.patch b/Spigot-Server-Patches/add-isDeeplySleeping-to-HumanEntity.patch deleted file mode 100644 index 527787e29d..0000000000 --- a/Spigot-Server-Patches/add-isDeeplySleeping-to-HumanEntity.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 8 Apr 2021 17:36:10 -0700 -Subject: [PATCH] add isDeeplySleeping to HumanEntity - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - } - } - -+ // Paper start -+ @Override -+ public boolean isDeeplySleeping() { -+ return getHandle().isDeeplySleeping(); -+ } -+ // Paper end -+ - @Override - public int getSleepTicks() { - return getHandle().sleepTicks; diff --git a/Spigot-Server-Patches/add-more-information-to-Entity.toString.patch b/Spigot-Server-Patches/add-more-information-to-Entity.toString.patch deleted file mode 100644 index 47eff4262d..0000000000 --- a/Spigot-Server-Patches/add-more-information-to-Entity.toString.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 19 Jul 2018 01:13:28 -0400 -Subject: [PATCH] add more information to Entity.toString() - -UUID, ticks lived, valid, dead - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public String toString() { -- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getDisplayName().getString(), this.id, this.world == null ? "~NULL~" : this.world.toString(), this.locX(), this.locY(), this.locZ()); -+ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cx=%d, cz=%d, tl=%d, v=%b, d=%b]", new Object[] { this.getClass().getSimpleName(), this.getDisplayName().getString(), Integer.valueOf(this.id), this.uniqueID.toString(), this.world == null ? "~NULL~" : this.world.toString(), Double.valueOf(this.locX()), Double.valueOf(this.locY()), Double.valueOf(this.locZ()), chunkX, chunkZ, this.ticksLived, this.valid, this.dead}); // Paper - add more information - } - - public boolean isInvulnerable(DamageSource damagesource) { diff --git a/Spigot-Server-Patches/add-per-world-spawn-limits.patch b/Spigot-Server-Patches/add-per-world-spawn-limits.patch deleted file mode 100644 index 4f20bb5ca2..0000000000 --- a/Spigot-Server-Patches/add-per-world-spawn-limits.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chase -Date: Wed, 2 Dec 2020 22:43:39 -0800 -Subject: [PATCH] add per world spawn limits - -Taken from #2982. Credit to Chasewhip8 - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); - } - -+ public int spawnLimitMonsters = -1; -+ public int spawnLimitAnimals = -1; -+ public int spawnLimitWaterAnimals = -1; -+ public int spawnLimitWaterAmbient = -1; -+ public int spawnLimitAmbient = -1; -+ private void perWorldSpawnLimits() { -+ spawnLimitMonsters = getInt("spawn-limits.monsters", spawnLimitMonsters); -+ spawnLimitAnimals = getInt("spawn-limits.animals", spawnLimitAnimals); -+ spawnLimitWaterAnimals = getInt("spawn-limits.water-animals", spawnLimitWaterAnimals); -+ spawnLimitWaterAmbient = getInt("spawn-limits.water-ambient", spawnLimitWaterAmbient); -+ spawnLimitAmbient = getInt("spawn-limits.ambient", spawnLimitAmbient); -+ } -+ - public int lightQueueSize = 20; - private void lightQueueSize() { - lightQueueSize = getInt("light-queue-size", lightQueueSize); -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - this.generator = gen; - - environment = env; -+ // Paper start - per world spawn limits -+ this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; -+ this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; -+ this.waterAnimalSpawn = this.world.paperConfig.spawnLimitWaterAnimals; -+ this.waterAmbientSpawn = this.world.paperConfig.spawnLimitWaterAmbient; -+ this.ambientSpawn = this.world.paperConfig.spawnLimitAmbient; -+ // Paper end - } - - @Override diff --git a/Spigot-Server-Patches/added-PlayerNameEntityEvent.patch b/Spigot-Server-Patches/added-PlayerNameEntityEvent.patch deleted file mode 100644 index fa726857e7..0000000000 --- a/Spigot-Server-Patches/added-PlayerNameEntityEvent.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 00:33:54 -0700 -Subject: [PATCH] added PlayerNameEntityEvent - - -diff --git a/src/main/java/net/minecraft/world/item/ItemNameTag.java b/src/main/java/net/minecraft/world/item/ItemNameTag.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/item/ItemNameTag.java -+++ b/src/main/java/net/minecraft/world/item/ItemNameTag.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.item; - -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.world.EnumHand; - import net.minecraft.world.EnumInteractionResult; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; - import net.minecraft.world.entity.player.EntityHuman; - -+// Paper start -+import io.papermc.paper.adventure.PaperAdventure; -+import io.papermc.paper.event.player.PlayerNameEntityEvent; -+// Paper end -+ - public class ItemNameTag extends Item { - - public ItemNameTag(Item.Info item_info) { -@@ -0,0 +0,0 @@ public class ItemNameTag extends Item { - public EnumInteractionResult a(ItemStack itemstack, EntityHuman entityhuman, EntityLiving entityliving, EnumHand enumhand) { - if (itemstack.hasName() && !(entityliving instanceof EntityHuman)) { - if (!entityhuman.world.isClientSide && entityliving.isAlive()) { -- entityliving.setCustomName(itemstack.getName()); -- if (entityliving instanceof EntityInsentient) { -- ((EntityInsentient) entityliving).setPersistent(); -+ // Paper start -+ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((EntityPlayer) entityhuman).getBukkitEntity(), entityliving.getBukkitLivingEntity(), PaperAdventure.asAdventure(itemstack.getName()), true); -+ if (!event.callEvent()) return EnumInteractionResult.PASS; -+ EntityLiving newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); -+ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); -+ if (event.isPersistent() && newEntityLiving instanceof EntityInsentient) { -+ ((EntityInsentient) newEntityLiving).setPersistent(); - } -- -+ // Paper end - itemstack.subtract(1); - } - diff --git a/Spigot-Server-Patches/added-PlayerTradeEvent.patch b/Spigot-Server-Patches/added-PlayerTradeEvent.patch deleted file mode 100644 index a78595915d..0000000000 --- a/Spigot-Server-Patches/added-PlayerTradeEvent.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 2 Jul 2020 16:12:10 -0700 -Subject: [PATCH] added PlayerTradeEvent - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java -+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java -@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityUnleashEvent.UnleashReason; - public abstract class EntityInsentient extends EntityLiving { - - private static final DataWatcherObject b = DataWatcher.a(EntityInsentient.class, DataWatcherRegistry.a); -- public int e; -+ public int e;public void setAmbientSoundTime(int time) { this.e = time; } // Paper - OBFHELPER - protected int f; - protected ControllerLook lookController; - protected ControllerMove moveController; -@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { - this.datawatcher.register(EntityInsentient.b, (byte) 0); - } - -+ public int getAmbientSoundInterval() { return D(); } // Paper - OBFHELPER - public int D() { - return 80; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillagerAbstract.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.inventory.CraftMerchantRecipe; - import org.bukkit.entity.AbstractVillager; - import org.bukkit.event.entity.VillagerAcquireTradeEvent; - // CraftBukkit end -+// Paper start -+import io.papermc.paper.event.player.PlayerTradeEvent; -+// Paper end - - public abstract class EntityVillagerAbstract extends EntityAgeable implements NPC, IMerchant { - -@@ -0,0 +0,0 @@ public abstract class EntityVillagerAbstract extends EntityAgeable implements NP - - @Override - public void a(MerchantRecipe merchantrecipe) { -- merchantrecipe.increaseUses(); -- this.e = -this.D(); -- this.b(merchantrecipe); -+ // Paper - moved down -+ // Paper start - if (this.tradingPlayer instanceof EntityPlayer) { -- CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, merchantrecipe.getSellingItem()); -+ PlayerTradeEvent event = new PlayerTradeEvent(((EntityPlayer) this.tradingPlayer).getBukkitEntity(), (AbstractVillager) this.getBukkitEntity(), merchantrecipe.asBukkit(), true, true); -+ event.callEvent(); -+ if (!event.isCancelled()) { -+ MerchantRecipe recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); -+ if (event.willIncreaseTradeUses()) recipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ if (event.isRewardingExp()) this.rewardTradeXp(recipe); -+ CriterionTriggers.s.a((EntityPlayer) this.tradingPlayer, this, recipe.getSellingItem()); -+ } -+ } else { -+ merchantrecipe.increaseUses(); -+ this.setAmbientSoundTime(-getAmbientSoundInterval()); -+ this.rewardTradeXp(merchantrecipe); - } -- -+ // Paper end - } - -- protected abstract void b(MerchantRecipe merchantrecipe); -+ protected abstract void b(MerchantRecipe merchantrecipe); public void rewardTradeXp(MerchantRecipe merchantrecipe) { this.b(merchantrecipe); } // Paper - OBFHELPER - - @Override - public boolean isRegularVillager() { diff --git a/Spigot-Server-Patches/added-Wither-API.patch b/Spigot-Server-Patches/added-Wither-API.patch deleted file mode 100644 index 4473f7889e..0000000000 --- a/Spigot-Server-Patches/added-Wither-API.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sun, 5 Jul 2020 15:39:19 -0700 -Subject: [PATCH] added Wither API - - -diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -+++ b/src/main/java/net/minecraft/world/entity/boss/wither/EntityWither.java -@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - return entityliving.getMonsterType() != EnumMonsterType.UNDEAD && entityliving.ei(); - }; - private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); -+ // Paper start -+ private boolean canPortal = false; -+ -+ public void setCanTravelThroughPortals(boolean canPortal) { this.canPortal = canPortal; } -+ // Paper end - - public EntityWither(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - this.datawatcher.set((DataWatcherObject) EntityWither.bo.get(i), j); - } - -+ public final boolean isPowered() { return this.S_(); } // Paper - OBFHELPER - public boolean S_() { - return this.getHealth() <= this.getMaxHealth() / 2.0F; - } -@@ -0,0 +0,0 @@ public class EntityWither extends EntityMonster implements IRangedEntity { - - @Override - public boolean canPortal() { -- return false; -+ return super.canPortal() && canPortal; // Paper - } - - @Override -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -@@ -0,0 +0,0 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok - public BossBar getBossBar() { - return bossBar; - } -+ -+ // Paper start -+ @Override -+ public boolean isCharged() { -+ return getHandle().isPowered(); -+ } -+ -+ @Override -+ public int getInvulnerableTicks() { -+ return getHandle().getInvul(); -+ } -+ -+ @Override -+ public void setInvulnerableTicks(int ticks) { -+ getHandle().setInvul(ticks); -+ } -+ -+ @Override -+ public boolean canTravelThroughPortals() { -+ return getHandle().canPortal(); -+ } -+ -+ @Override -+ public void setCanTravelThroughPortals(boolean value) { -+ getHandle().setCanTravelThroughPortals(value); -+ } -+ // Paper end - } diff --git a/Spigot-Server-Patches/added-option-to-disable-pathfinding-updates-on-block.patch b/Spigot-Server-Patches/added-option-to-disable-pathfinding-updates-on-block.patch deleted file mode 100644 index 389d10bd76..0000000000 --- a/Spigot-Server-Patches/added-option-to-disable-pathfinding-updates-on-block.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Mon, 25 Jan 2021 14:37:57 +0100 -Subject: [PATCH] added option to disable pathfinding updates on block changes - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void enderDragonsDeathAlwaysPlacesDragonEgg() { - enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); - } -+ -+ public boolean updatePathfindingOnBlockUpdate = true; -+ private void setUpdatePathfindingOnBlockUpdate() { -+ updatePathfindingOnBlockUpdate = getBoolean("update-pathfinding-on-block-update", this.updatePathfindingOnBlockUpdate); -+ } - } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - @Override - public void notify(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) { - this.getChunkProvider().flagDirty(blockposition); -+ if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates - VoxelShape voxelshape = iblockdata.getCollisionShape(this, blockposition); - VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - - this.tickingEntities = wasTicking; // Paper - } -+ } // Paper - } - - @Override diff --git a/Spigot-Server-Patches/additions-to-PlayerGameModeChangeEvent.patch b/Spigot-Server-Patches/additions-to-PlayerGameModeChangeEvent.patch deleted file mode 100644 index 97d40eb493..0000000000 --- a/Spigot-Server-Patches/additions-to-PlayerGameModeChangeEvent.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Sat, 15 May 2021 10:04:43 -0700 -Subject: [PATCH] additions to PlayerGameModeChangeEvent - - -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamemode.java b/src/main/java/net/minecraft/server/commands/CommandGamemode.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamemode.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamemode.java -@@ -0,0 +0,0 @@ public class CommandGamemode { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { -- entityplayer.a(enumgamemode); -- // CraftBukkit start - handle event cancelling the change -- if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { -- commandcontext.getSource().sendFailureMessage(new net.minecraft.network.chat.ChatComponentText("Failed to set the gamemode of '" + entityplayer.getName() + "'")); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ commandcontext.getSource().sendMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); - continue; - } -- // CraftBukkit end -+ // Paper end - a((CommandListenerWrapper) commandcontext.getSource(), entityplayer, enumgamemode); - ++i; - } -diff --git a/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java b/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java -+++ b/src/main/java/net/minecraft/server/commands/CommandGamemodeDefault.java -@@ -0,0 +0,0 @@ public class CommandGamemodeDefault { - EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - - if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) { -- entityplayer.a(enumgamemode); -+ // Paper start - handle event cancelling the change -+ org.bukkit.event.player.PlayerGameModeChangeEvent event = entityplayer.setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.text("Failed to set the gamemode of '" + entityplayer.getName() + "'", net.kyori.adventure.text.format.NamedTextColor.RED)); -+ if (event != null && event.isCancelled()) { -+ commandlistenerwrapper.sendMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); -+ continue; -+ } -+ // Paper end - ++i; - } - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - if (this.locY() > 300) this.setPositionRaw(locX(), 257, locZ()); // Paper - bring down to a saner Y level if out of world - if (nbttagcompound.hasKeyOfType("playerGameType", 99)) { - if (this.getMinecraftServer().getForceGamemode()) { -+ // Paper start - call PlayerGameModeChangeEvent on join for players that do not have the correct gamemode -+ if (this.getMinecraftServer().getGamemode() != EnumGamemode.getById(nbttagcompound.getInt("playerGameType"))) { -+ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.getMinecraftServer().getGamemode().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { - this.playerInteractManager.a(this.getMinecraftServer().getGamemode(), EnumGamemode.NOT_SET); -+ } else { -+ this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); // copied from below; if cancelled, set gamemode normally -+ } -+ } else { -+ this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); // copied from below; if no change needed, set gamemode normally -+ } // Paper end - } else { - this.playerInteractManager.a(EnumGamemode.getById(nbttagcompound.getInt("playerGameType")), nbttagcompound.hasKeyOfType("previousPlayerGameType", 3) ? EnumGamemode.getById(nbttagcompound.getInt("previousPlayerGameType")) : EnumGamemode.NOT_SET); - } -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - @Override - public void a(EnumGamemode enumgamemode) { -+ // Paper start - Add cause and nullable message to event -+ setGamemode(enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); -+ } -+ -+ public PlayerGameModeChangeEvent setGamemode(EnumGamemode enumgamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { -+ // Paper end - // CraftBukkit start - if (enumgamemode == this.playerInteractManager.getGameMode()) { -- return; -+ return null; // Paper - } - -- PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId())); -+ PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(getBukkitEntity(), GameMode.getByValue(enumgamemode.getId()), cause, message); // Paper - world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- return; -+ return event; // Paper - } - // CraftBukkit end - -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - this.updateAbilities(); - this.dU(); -+ return event; // Paper - } - - @Override -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, false); - if (this.minecraftServer.isHardcore()) { -- this.player.a(EnumGamemode.SPECTATOR); -+ this.player.setGamemode(EnumGamemode.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - ((GameRules.GameRuleBoolean) this.player.getWorldServer().getGameRules().get(GameRules.SPECTATORS_GENERATE_CHUNKS)).a(false, this.minecraftServer); - } - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - throw new IllegalArgumentException("Mode cannot be null"); - } - -- getHandle().a(EnumGamemode.getById(mode.getValue())); -+ getHandle().setGamemode(EnumGamemode.getById(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper - } - - @Override diff --git a/Spigot-Server-Patches/call-PortalCreateEvent-players-and-end-platform.patch b/Spigot-Server-Patches/call-PortalCreateEvent-players-and-end-platform.patch deleted file mode 100644 index f152b79cea..0000000000 --- a/Spigot-Server-Patches/call-PortalCreateEvent-players-and-end-platform.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Wed, 12 May 2021 03:21:22 -0700 -Subject: [PATCH] call PortalCreateEvent players and end platform - - -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPosition.java -+++ b/src/main/java/net/minecraft/core/BlockPosition.java -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - return this.d(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); - } - -+ public BlockPosition.MutableBlockPosition withOffset(int x, int y, int z) { return e(x, y, z); } // Paper - OBFHELPER - public BlockPosition.MutableBlockPosition e(int i, int j, int k) { - return this.d(this.getX() + i, this.getY() + j, this.getZ() + k); - } -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - private void a(WorldServer worldserver, BlockPosition blockposition) { - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i(); - -+ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver); // Paper - for (int i = -2; i <= 2; ++i) { - for (int j = -2; j <= 2; ++j) { - for (int k = -1; k < 3; ++k) { - IBlockData iblockdata = k == -1 ? Blocks.OBSIDIAN.getBlockData() : Blocks.AIR.getBlockData(); - -- worldserver.setTypeUpdate(blockposition_mutableblockposition.g(blockposition).e(j, k, i), iblockdata); -+ blockList.setTypeAndData(blockposition_mutableblockposition.setValues(blockposition).withOffset(j, k, i), iblockdata, 3); // Paper - } - } - } -+ // Paper start -+ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), worldserver.getWorld(), this.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM).callEvent()) { -+ blockList.updateList(); -+ } -+ // Paper end - - } - diff --git a/Spigot-Server-Patches/copy-TESign-isEditable-from-snapshots.patch b/Spigot-Server-Patches/copy-TESign-isEditable-from-snapshots.patch deleted file mode 100644 index 9a05a49b11..0000000000 --- a/Spigot-Server-Patches/copy-TESign-isEditable-from-snapshots.patch +++ /dev/null @@ -1,18 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 23 Mar 2021 06:43:30 +0000 -Subject: [PATCH] copy TESign#isEditable from snapshots - - -diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java -@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockEntityState implements - } - // Paper end - } -+ sign.isEditable = getSnapshot().isEditable; // Paper - copy manually - } - - // Paper start diff --git a/Spigot-Server-Patches/do-not-create-unnecessary-copies-of-passenger-list.patch b/Spigot-Server-Patches/do-not-create-unnecessary-copies-of-passenger-list.patch deleted file mode 100644 index 36905563ca..0000000000 --- a/Spigot-Server-Patches/do-not-create-unnecessary-copies-of-passenger-list.patch +++ /dev/null @@ -1,239 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: lukas81298 -Date: Sun, 13 Dec 2020 13:42:55 +0100 -Subject: [PATCH] do not create unnecessary copies of passenger list - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutMount.java -@@ -0,0 +0,0 @@ public class PacketPlayOutMount implements Packet { - - public PacketPlayOutMount(Entity entity) { - this.a = entity.getId(); -- List list = entity.getPassengers(); -+ List list = entity.passengers; // Paper - do not create a copy of the list - - this.b = new int[list.size()]; - -diff --git a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -+++ b/src/main/java/net/minecraft/server/level/EntityTrackerEntry.java -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - - public final void tick() { this.a(); } // Paper - OBFHELPER - public void a() { -- List list = this.tracker.getPassengers(); -+ List list = this.tracker.passengers; // Paper - do not copy list - - if (!list.equals(this.p)) { -- this.p = list; -+ this.p = com.google.common.collect.ImmutableList.copyOf(list); // Paper - only copy list if something has changed - this.broadcastIncludingSelf(new PacketPlayOutMount(this.tracker)); // CraftBukkit - } - -@@ -0,0 +0,0 @@ public class EntityTrackerEntry { - } - } - -- if (!this.tracker.getPassengers().isEmpty()) { -+ if (!this.tracker.passengers.isEmpty()) { // Paper - do not create copy of list - consumer.accept(new PacketPlayOutMount(this.tracker)); - } - -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - list.add(entity); - } - -- if (!entity.getPassengers().isEmpty()) { -+ if (!entity.passengers.isEmpty()) { // Paper - do not copy list - list1.add(entity); - } - } -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - protected boolean q(Entity entity) { -- return this.getPassengers().size() < 1; -+ return this.passengers.size() < 1; // Paper - do not copy list - } - - public final float getCollisionBorderSize() { return bg(); } // Paper - OBFHELPER -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean isVehicle() { -- return !this.getPassengers().isEmpty(); -+ return !this.passengers.isEmpty(); // Paper - do not copy list - } - - public boolean bt() { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean w(Entity entity) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity1; - -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - - public boolean a(Class oclass) { -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - Entity entity; - -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - public Collection getAllPassengers() { - Set set = Sets.newHashSet(); -- Iterator iterator = this.getPassengers().iterator(); -+ Iterator iterator = this.passengers.iterator(); // Paper - do not copy list - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - private void a(boolean flag, Set set) { - Entity entity; - -- for (Iterator iterator = this.getPassengers().iterator(); iterator.hasNext(); entity.a(flag, set)) { -+ for (Iterator iterator = this.passengers.iterator(); iterator.hasNext(); entity.a(flag, set)) { // Paper - do not copy list - entity = (Entity) iterator.next(); - if (!flag || EntityPlayer.class.isAssignableFrom(entity.getClass())) { - set.add(entity); -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalTame.java -@@ -0,0 +0,0 @@ public class PathfinderGoalTame extends PathfinderGoal { - @Override - public void e() { - if (!this.entity.isTamed() && this.entity.getRandom().nextInt(50) == 0) { -- Entity entity = (Entity) this.entity.getPassengers().get(0); -+ Entity entity = this.entity.passengers.isEmpty() ? null : this.entity.passengers.get(0); // Paper - do not copy list, fixed array out of bounds exception as well - - if (entity == null) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -+++ b/src/main/java/net/minecraft/world/entity/animal/EntityPig.java -@@ -0,0 +0,0 @@ public class EntityPig extends EntityAnimal implements ISteerable, ISaddleable { - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/EntityHorseAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityHorseAbstract extends EntityAnimal implements IInven - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Nullable -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityRavager.java -@@ -0,0 +0,0 @@ public class EntityRavager extends EntityRaider { - @Nullable - @Override - public Entity getRidingPassenger() { -- return this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ return this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - super.tick(); - this.r(); - if (this.cs()) { -- if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof EntityHuman)) { -+ if (this.passengers.isEmpty() || !(this.passengers.get(0) instanceof EntityHuman)) { // Paper - do not copy list - this.a(false, false); - } - -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - Entity entity = (Entity) list.get(j); - - if (!entity.w(this)) { -- if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { -+ if (flag && this.passengers.size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof EntityLiving && !(entity instanceof EntityWaterAnimal) && !(entity instanceof EntityHuman)) { // Paper - do not copy passenger list - entity.startRiding(this); - } else { - this.collide(entity); -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - float f = 0.0F; - float f1 = (float) ((this.dead ? 0.009999999776482582D : this.bc()) + entity.bb()); - -- if (this.getPassengers().size() > 1) { -- int i = this.getPassengers().indexOf(entity); -+ if (this.passengers.size() > 1) { // Paper - do not copy list -+ int i = this.passengers.indexOf(entity); // Paper - do not copy list - - if (i == 0) { - f = 0.2F; -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - entity.yaw += this.ak; - entity.setHeadRotation(entity.getHeadRotation() + this.ak); - this.a(entity); -- if (entity instanceof EntityAnimal && this.getPassengers().size() > 1) { -+ if (entity instanceof EntityAnimal && this.passengers.size() > 1) { // Paper - do not copy list - int j = entity.getId() % 2 == 0 ? 90 : 270; - - entity.n(((EntityAnimal) entity).aA + (float) j); -@@ -0,0 +0,0 @@ public class EntityBoat extends Entity { - - @Override - protected boolean q(Entity entity) { -- return this.getPassengers().size() < 2 && !this.a((Tag) TagsFluid.WATER); -+ return this.passengers.size() < 2 && !this.a((Tag) TagsFluid.WATER); // Paper - do not copy list - } - - @Nullable - @Override - public Entity getRidingPassenger() { -- List list = this.getPassengers(); -+ List list = this.passengers; // Paper - do not copy list - - return list.isEmpty() ? null : (Entity) list.get(0); - } -diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartAbstract.java -@@ -0,0 +0,0 @@ public abstract class EntityMinecartAbstract extends Entity { - - vec3d1 = new Vec3D(d8 * d4 / d6, vec3d1.y, d8 * d5 / d6); - this.setMot(vec3d1); -- Entity entity = this.getPassengers().isEmpty() ? null : (Entity) this.getPassengers().get(0); -+ Entity entity = this.passengers.isEmpty() ? null : (Entity) this.passengers.get(0); // Paper - do not copy list - - if (entity instanceof EntityHuman) { - Vec3D vec3d2 = entity.getMot(); diff --git a/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch deleted file mode 100644 index 3a8d4ae75f..0000000000 --- a/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 24 Mar 2019 18:09:20 -0400 -Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items - -vanilla checks for == 0 - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityItem.java b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityItem.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityItem.java -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { - // CraftBukkit start - Use wall time for pickup and despawn timers - int elapsedTicks = MinecraftServer.currentTick - this.lastTick; - if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; -+ this.pickupDelay = Math.max(0, this.pickupDelay); // Paper - don't go below 0 - if (this.age != -32768) this.age += elapsedTicks; - this.lastTick = MinecraftServer.currentTick; - // CraftBukkit end diff --git a/Spigot-Server-Patches/don-t-throw-when-loading-invalid-TEs.patch b/Spigot-Server-Patches/don-t-throw-when-loading-invalid-TEs.patch deleted file mode 100644 index 13776f1d01..0000000000 --- a/Spigot-Server-Patches/don-t-throw-when-loading-invalid-TEs.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 20 Apr 2021 01:15:04 +0100 -Subject: [PATCH] don't throw when loading invalid TEs - - -diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; - import net.minecraft.CrashReportSystemDetails; -+import net.minecraft.ResourceKeyInvalidException; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; -@@ -0,0 +0,0 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { / - public static TileEntity create(IBlockData iblockdata, NBTTagCompound nbttagcompound) { - String s = nbttagcompound.getString("id"); - -- return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(new MinecraftKey(s)).map((tileentitytypes) -> { -+ // Paper -+ MinecraftKey minecraftKey = null; -+ try { -+ minecraftKey = new MinecraftKey(s); -+ } catch (ResourceKeyInvalidException ex) {} -+ // Paper end -+ return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(minecraftKey).map((tileentitytypes) -> { - try { - return tileentitytypes.a(); - } catch (Throwable throwable) { diff --git a/Spigot-Server-Patches/fix-PigZombieAngerEvent-cancellation.patch b/Spigot-Server-Patches/fix-PigZombieAngerEvent-cancellation.patch deleted file mode 100644 index 3ccb0867cf..0000000000 --- a/Spigot-Server-Patches/fix-PigZombieAngerEvent-cancellation.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Thu, 18 Mar 2021 21:38:01 +0100 -Subject: [PATCH] fix PigZombieAngerEvent cancellation - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java -@@ -0,0 +0,0 @@ public abstract class PathfinderGoal { - - public void c() { this.start(); } public void start() {} // Paper - OBFHELPER - -+ public final void onTaskResetObfHelper() { d(); } // Paper - OBFHELPER - public void d() { - onTaskReset(); // Paper - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityPigZombie.java -@@ -0,0 +0,0 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - private UUID br; - private static final IntRange bs = TimeRange.a(4, 6); - private int bt; -+ private PathfinderGoalHurtByTarget pathfinderGoalHurtByTarget; // Paper - - public EntityPigZombie(EntityTypes entitytypes, World world) { - super(entitytypes, world); -@@ -0,0 +0,0 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - protected void m() { - this.goalSelector.a(2, new PathfinderGoalZombieAttack(this, 1.0D, false)); - this.goalSelector.a(7, new PathfinderGoalRandomStrollLand(this, 1.0D)); -- this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error -+ this.targetSelector.a(1, pathfinderGoalHurtByTarget = new PathfinderGoalHurtByTarget(this).a(new Class[0])); // CraftBukkit - decompile error // Paper - assign field - this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, 10, true, false, this::a_)); - this.targetSelector.a(3, new PathfinderGoalUniversalAngerReset<>(this, true)); - } -@@ -0,0 +0,0 @@ public class EntityPigZombie extends EntityZombie implements IEntityAngerable { - this.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.setAngerTarget(null); -+ pathfinderGoalHurtByTarget.onTaskResetObfHelper(); // Paper - clear goalTargets to fix cancellation - return; - } - this.setAnger(event.getNewAnger()); diff --git a/Spigot-Server-Patches/fix-PlayerItemHeldEvent-firing-twice.patch b/Spigot-Server-Patches/fix-PlayerItemHeldEvent-firing-twice.patch deleted file mode 100644 index 1cff7cb8ef..0000000000 --- a/Spigot-Server-Patches/fix-PlayerItemHeldEvent-firing-twice.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: chickeneer -Date: Thu, 22 Apr 2021 19:02:07 -0700 -Subject: [PATCH] fix PlayerItemHeldEvent firing twice - - -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInHeldItemSlot.java -@@ -0,0 +0,0 @@ public class PacketPlayInHeldItemSlot implements Packet { - packetlistenerplayin.a(this); - } - -+ public int getItemInHandIndex() { return b(); } // Paper - OBFHELPER - public int b() { - return this.itemInHandIndex; - } -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.getWorldServer()); - if (this.player.isFrozen()) return; // CraftBukkit - if (packetplayinhelditemslot.b() >= 0 && packetplayinhelditemslot.b() < PlayerInventory.getHotbarSize()) { -+ if (packetplayinhelditemslot.getItemInHandIndex() == this.player.inventory.itemInHandIndex) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change - PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getPlayer(), this.player.inventory.itemInHandIndex, packetplayinhelditemslot.b()); - this.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/fix-cancelling-block-falling-causing-client-desync.patch b/Spigot-Server-Patches/fix-cancelling-block-falling-causing-client-desync.patch deleted file mode 100644 index f49855476d..0000000000 --- a/Spigot-Server-Patches/fix-cancelling-block-falling-causing-client-desync.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 11:13:30 +0100 -Subject: [PATCH] fix cancelling block falling causing client desync - - -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -+++ b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity; - import net.minecraft.network.syncher.DataWatcher; - import net.minecraft.network.syncher.DataWatcherObject; - import net.minecraft.network.syncher.DataWatcherRegistry; -+import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; - import net.minecraft.tags.TagsFluid; -@@ -0,0 +0,0 @@ import net.minecraft.world.phys.MovingObjectPosition; - import net.minecraft.world.phys.MovingObjectPositionBlock; - import net.minecraft.world.phys.Vec3D; - -+import org.bukkit.craftbukkit.block.CraftBlock; - import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit - - public class EntityFallingBlock extends Entity { -@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity { - - if (this.ticksLived++ == 0) { - blockposition = this.getChunkCoordinates(); -- if (this.world.getType(blockposition).a(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { -- this.world.a(blockposition, false); -+ // Paper start - fix cancelling block falling causing client desync -+ if (this.world.getType(blockposition).isSameInstance(block)) { -+ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.getBlockData()).isCancelled()) { -+ if (this.world.getType(blockposition).isSameInstance(block)) { //if listener didn't update the block -+ ((WorldServer) world).getChunkProvider().flagDirty(blockposition); -+ } -+ this.die(); -+ return; -+ } else { -+ this.world.setAir(blockposition, false); -+ } -+ // Paper end - fix cancelling block falling causing client desync - } else if (!this.world.isClientSide) { - this.die(); - return; -diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java -@@ -0,0 +0,0 @@ public abstract class BlockBase { - return this.getBlock().a(tag) && predicate.test(this); - } - -+ public final boolean isSameInstance(Block block) { return a(block); } // Paper - OBFHELPER - public boolean a(Block block) { - return this.getBlock().a(block); - } diff --git a/Spigot-Server-Patches/fix-converting-txt-to-json-file.patch b/Spigot-Server-Patches/fix-converting-txt-to-json-file.patch deleted file mode 100644 index af2d3905a7..0000000000 --- a/Spigot-Server-Patches/fix-converting-txt-to-json-file.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Mon, 4 Jan 2021 19:49:15 -0800 -Subject: [PATCH] fix converting txt to json file - - -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java -@@ -0,0 +0,0 @@ public class DedicatedPlayerList extends PlayerList { - - this.a(dedicatedserverproperties.viewDistance); - super.setHasWhitelist((Boolean) dedicatedserverproperties.whiteList.get()); -+ // Paper start - moved from constructor -+ } -+ @Override -+ public void loadAndSaveFiles() { -+ // Paper end - this.y(); - this.w(); - this.x(); -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 IMinecraftServer - org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); - org.spigotmc.SpigotConfig.registerCommands(); - // Spigot end -+ // Paper start - moved up to right after PlayerList creation but before file load/save -+ if (this.convertNames()) { -+ this.getUserCache().save(false); // Paper -+ } -+ this.getPlayerList().loadAndSaveFiles(); // Must be after convertNames -+ // Paper end - // Paper start - try { - com.destroystokyo.paper.PaperConfig.init((java.io.File) options.valueOf("paper-settings")); -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer - DedicatedServer.LOGGER.warn("To change this, set \"online-mode\" to \"true\" in the server.properties file."); - } - -- if (this.convertNames()) { -- this.getUserCache().b(false); // Paper -- } -- - if (!NameReferencingFileConverter.e(this)) { - return false; - } else { -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { - this.maxPlayers = i; - this.playerFileData = worldnbtstorage; - } -+ abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor - - public void a(NetworkManager networkmanager, EntityPlayer entityplayer) { - EntityPlayer prev = pendingPlayers.put(entityplayer.getUniqueID(), entityplayer);// Paper -diff --git a/src/main/java/net/minecraft/server/players/UserCache.java b/src/main/java/net/minecraft/server/players/UserCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/UserCache.java -+++ b/src/main/java/net/minecraft/server/players/UserCache.java -@@ -0,0 +0,0 @@ public class UserCache { - return arraylist; - } - -+ public void save(boolean asyncSave) { b(asyncSave); } // Paper - OBFHELPER - public void b(boolean asyncSave) { // Paper - JsonArray jsonarray = new JsonArray(); - DateFormat dateformat = e(); diff --git a/Spigot-Server-Patches/fix-dead-slime-setSize-invincibility.patch b/Spigot-Server-Patches/fix-dead-slime-setSize-invincibility.patch deleted file mode 100644 index f98f485947..0000000000 --- a/Spigot-Server-Patches/fix-dead-slime-setSize-invincibility.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Fri, 5 Feb 2021 22:12:13 +0100 -Subject: [PATCH] fix dead slime setSize invincibility - - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -@@ -0,0 +0,0 @@ public class CraftSlime extends CraftMob implements Slime { - - @Override - public void setSize(int size) { -- getHandle().setSize(size, true); -+ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility - } - - @Override diff --git a/Spigot-Server-Patches/force-entity-dismount-during-teleportation.patch b/Spigot-Server-Patches/force-entity-dismount-during-teleportation.patch deleted file mode 100644 index 9c49c2044b..0000000000 --- a/Spigot-Server-Patches/force-entity-dismount-during-teleportation.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 15 Nov 2018 13:38:37 +0000 -Subject: [PATCH] force entity dismount during teleportation - -Entities must be dismounted before teleportation in order to avoid -multiple issues in the server with regards to teleportation, shamefully, -too many plugins rely on the events firing, which means that not firing -these events caues more issues than it solves; - -In order to counteract this, Entity dismount/exit vehicle events have -been modified to supress cancellation (and has a method to allow plugins -to check if this has been set), noting that cancellation will be silently -surpressed given that plugins are not expecting this event to not be cancellable. - -This is a far from ideal scenario, however: given the current state of this -event and other alternatives causing issues elsewhere, I believe that -this is going to be the best soultion all around. - -Improvements/suggestions welcome! - -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - } - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - Entity entity1 = this.getVehicle(); - - if (entity1 != entity && this.playerConnection != null) { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - - } - -- public void bf() { -+ // Paper start -+ public void bf() { stopRiding(false); } -+ public void stopRiding(boolean suppressCancellation) { -+ // Paper end - if (this.vehicle != null) { - Entity entity = this.vehicle; - - this.vehicle = null; -- if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit -+ if (!entity.removePassenger(this, suppressCancellation)) this.vehicle = entity; // CraftBukkit // Paper - } - - } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - return true; // CraftBukkit - } - -- protected boolean removePassenger(Entity entity) { // CraftBukkit -+ // Paper start -+ protected boolean removePassenger(Entity entity) { return removePassenger(entity, false);} -+ protected boolean removePassenger(Entity entity, boolean suppressCancellation) { // CraftBukkit -+ // Paper end - if (entity.getVehicle() == this) { - throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); - } else { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - if (getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { - VehicleExitEvent event = new VehicleExitEvent( - (Vehicle) getBukkitEntity(), -- (LivingEntity) entity.getBukkitEntity() -+ (LivingEntity) entity.getBukkitEntity(), !suppressCancellation // Paper - ); - // Suppress during worldgen - if (this.valid) { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne - } - // CraftBukkit end - // Spigot start -- org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity()); -+ org.spigotmc.event.entity.EntityDismountEvent event = new org.spigotmc.event.entity.EntityDismountEvent(entity.getBukkitEntity(), this.getBukkitEntity(), !suppressCancellation); // Paper - // Suppress during worldgen - if (this.valid) { - Bukkit.getPluginManager().callEvent(event); -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - return ((Byte) this.datawatcher.get(EntityLiving.ag) & 4) != 0; - } - -- @Override -- public void stopRiding() { -+ // Paper start -+ @Override public void stopRiding() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end - Entity entity = this.getVehicle(); - -- super.stopRiding(); -+ super.stopRiding(suppressCancellation); // Paper - suppress - if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { - this.a(entity); - } -diff --git a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -+++ b/src/main/java/net/minecraft/world/entity/player/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - return -0.35D; - } - -- @Override -- public void bf() { -- super.bf(); -+ // Paper start -+ @Override public void bf() { stopRiding(false); } -+ @Override public void stopRiding(boolean suppressCancellation) { -+ // Paper end -+ super.stopRiding(suppressCancellation); // Paper - suppress - this.j = 0; - } - diff --git a/Spigot-Server-Patches/forced-whitelist-use-configurable-kick-message.patch b/Spigot-Server-Patches/forced-whitelist-use-configurable-kick-message.patch deleted file mode 100644 index d50d69451c..0000000000 --- a/Spigot-Server-Patches/forced-whitelist-use-configurable-kick-message.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Sat, 27 Mar 2021 09:24:23 +0100 -Subject: [PATCH] forced whitelist: use configurable kick message - - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Thu, 22 Mar 2018 01:40:24 -0400 -Subject: [PATCH] getPlayerUniqueId API - -Gets the unique ID of the player currently known as the specified player name -In Offline Mode, will return an Offline UUID - -This is a more performant way to obtain a UUID for a name than loading an OfflinePlayer - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return recipients.size(); - } - -+ // Paper start -+ @Nullable -+ public UUID getPlayerUniqueId(String name) { -+ Player player = Bukkit.getPlayerExact(name); -+ if (player != null) { -+ return player.getUniqueId(); -+ } -+ GameProfile profile; -+ // Only fetch an online UUID in online mode -+ if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) { -+ profile = console.getUserCache().getProfile( name ); -+ } else { -+ // Make an OfflinePlayer using an offline mode UUID since the name has no profile -+ profile = new GameProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)), name); -+ } -+ return profile != null ? profile.getId() : null; -+ } -+ // Paper end -+ - @Override - @Deprecated - public OfflinePlayer getOfflinePlayer(String name) { diff --git a/Spigot-Server-Patches/handle-NaN-health-absorb-values-and-repair-bad-data.patch b/Spigot-Server-Patches/handle-NaN-health-absorb-values-and-repair-bad-data.patch deleted file mode 100644 index 9437809c91..0000000000 --- a/Spigot-Server-Patches/handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 27 Sep 2015 01:18:02 -0400 -Subject: [PATCH] handle NaN health/absorb values and repair bad data - - -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityLiving.java -+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - - @Override - public void loadData(NBTTagCompound nbttagcompound) { -- this.setAbsorptionHearts(nbttagcompound.getFloat("AbsorptionAmount")); -+ // Paper start - jvm keeps optimizing the setter -+ float absorptionAmount = nbttagcompound.getFloat("AbsorptionAmount"); -+ if (Float.isNaN(absorptionAmount)) { -+ absorptionAmount = 0; -+ } -+ this.setAbsorptionHearts(absorptionAmount); -+ // Paper end - if (nbttagcompound.hasKeyOfType("Attributes", 9) && this.world != null && !this.world.isClientSide) { - this.getAttributeMap().a(nbttagcompound.getList("Attributes", 10)); - } -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - public void setHealth(float f) { -+ // Paper start -+ if (Float.isNaN(f)) { f = getMaxHealth(); if (this.valid) { -+ System.err.println("[NAN-HEALTH] " + getName() + " had NaN health set"); -+ } } // Paper end - // CraftBukkit start - Handle scaled health - if (this instanceof EntityPlayer) { - org.bukkit.craftbukkit.entity.CraftPlayer player = ((EntityPlayer) this).getBukkitEntity(); -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - } - - public void setAbsorptionHearts(float f) { -- if (f < 0.0F) { -+ if (f < 0.0F || Float.isNaN(f)) { // Paper - f = 0.0F; - } - -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - } - - public void setRealHealth(double health) { -+ if (Double.isNaN(health)) {return;} // Paper - this.health = health; - } - diff --git a/Spigot-Server-Patches/handle-PacketPlayInKeepAlive-async.patch b/Spigot-Server-Patches/handle-PacketPlayInKeepAlive-async.patch deleted file mode 100644 index b85929f2db..0000000000 --- a/Spigot-Server-Patches/handle-PacketPlayInKeepAlive-async.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 5 Oct 2017 01:54:07 +0100 -Subject: [PATCH] handle PacketPlayInKeepAlive async - -In 1.12.2, Mojang moved the processing of PacketPlayInKeepAlive off the main -thread, while entirely correct for the server, this causes issues with -plugins which are expecting the PlayerQuitEvent on the main thread. - -In order to counteract some bad behavior, we will post handling of the -disconnection to the main thread, but leave the actual processing of the packet -off the main thread. - -also adding some additional logging in order to help work out what is causing -random disconnections for clients. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - - @Override - public void a(PacketPlayInKeepAlive packetplayinkeepalive) { -- PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit -+ //PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit // Paper - This shouldn't be on the main thread - if (this.awaitingKeepAlive && packetplayinkeepalive.b() == this.h) { - int i = (int) (SystemUtils.getMonotonicMillis() - this.lastKeepAlive); - - this.player.ping = (this.player.ping * 3 + i) / 4; - this.awaitingKeepAlive = false; - } else if (!this.isExemptPlayer()) { -+ // Paper start - This needs to be handled on the main thread for plugins -+ minecraftServer.scheduleOnMain(() -> { - this.disconnect(new ChatMessage("disconnect.timeout")); -+ }); -+ // Paper end - } - - } diff --git a/Spigot-Server-Patches/implement-optional-per-player-mob-spawns.patch b/Spigot-Server-Patches/implement-optional-per-player-mob-spawns.patch deleted file mode 100644 index c616567c91..0000000000 --- a/Spigot-Server-Patches/implement-optional-per-player-mob-spawns.patch +++ /dev/null @@ -1,848 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -Date: Mon, 19 Aug 2019 01:27:58 +0500 -Subject: [PATCH] implement optional per player mob spawns - - -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +0,0 @@ public class WorldTimingsHandler { - - - public final Timing miscMobSpawning; -+ public final Timing playerMobDistanceMapUpdate; - - public final Timing poiUnload; - public final Timing chunkUnload; -@@ -0,0 +0,0 @@ public class WorldTimingsHandler { - - - miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update"); - - poiUnload = Timings.ofSafe(name + "Chunk unload - POI"); - chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk"); -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - } - } - } -+ -+ public boolean perPlayerMobSpawns = false; -+ private void perPlayerMobSpawns() { -+ perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PlayerMobDistanceMap.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.util.List; -+import java.util.Map; -+import net.minecraft.core.SectionPosition; -+import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.world.level.ChunkCoordIntPair; -+import org.spigotmc.AsyncCatcher; -+import java.util.HashMap; -+ -+/** @author Spottedleaf */ -+public final class PlayerMobDistanceMap { -+ -+ private static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); -+ -+ private final Map players = new HashMap<>(); -+ // we use linked for better iteration. -+ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); -+ private int viewDistance; -+ -+ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkCoordIntPair chunkPos) { -+ return this.getPlayersInRange(chunkPos.x, chunkPos.z); -+ } -+ -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { -+ return this.playerMap.getOrDefault(ChunkCoordIntPair.pair(chunkX, chunkZ), EMPTY_SET); -+ } -+ -+ public void update(final List currentPlayers, final int newViewDistance) { -+ AsyncCatcher.catchOp("Distance map update"); -+ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); -+ -+ final int oldViewDistance = this.viewDistance; -+ this.viewDistance = newViewDistance; -+ -+ for (final EntityPlayer player : currentPlayers) { -+ if (player.isSpectator() || !player.affectsSpawning) { -+ continue; // will be left in 'gone' (or not added at all) -+ } -+ -+ gone.remove(player); -+ -+ final SectionPosition newPosition = player.getPlayerMapSection(); -+ final SectionPosition oldPosition = this.players.put(player, newPosition); -+ -+ if (oldPosition == null) { -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } else { -+ this.updatePlayer(player, oldPosition, newPosition, oldViewDistance, newViewDistance); -+ } -+ //this.validatePlayer(player, newViewDistance); // debug only -+ } -+ -+ for (final EntityPlayer player : gone) { -+ final SectionPosition oldPosition = this.players.remove(player); -+ if (oldPosition != null) { -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ } -+ } -+ } -+ -+ // expensive op, only for debug -+ private void validatePlayer(final EntityPlayer player, final int viewDistance) { -+ int entiesGot = 0; -+ int expectedEntries = (2 * viewDistance + 1); -+ expectedEntries *= expectedEntries; -+ -+ final SectionPosition currPosition = player.getPlayerMapSection(); -+ -+ final int centerX = currPosition.getX(); -+ final int centerZ = currPosition.getZ(); -+ -+ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { -+ final long key = entry.getLongKey(); -+ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); -+ -+ if (map.referenceCount == 0) { -+ throw new IllegalStateException("Invalid map"); -+ } -+ -+ if (map.set.contains(player)) { -+ ++entiesGot; -+ -+ final int chunkX = ChunkCoordIntPair.getX(key); -+ final int chunkZ = ChunkCoordIntPair.getZ(key); -+ -+ final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); -+ -+ if (dist > viewDistance) { -+ throw new IllegalStateException("Expected view distance " + viewDistance + ", got " + dist); -+ } -+ } -+ } -+ -+ if (entiesGot != expectedEntries) { -+ throw new IllegalStateException("Expected " + expectedEntries + ", got " + entiesGot); -+ } -+ } -+ -+ private void addPlayerTo(final EntityPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ if (players == null) { -+ return player.cachedSingleMobDistanceMap; -+ } else { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWith(players, player); -+ } -+ }); -+ } -+ -+ private void removePlayerFrom(final EntityPlayer player, final int chunkX, final int chunkZ) { -+ this.playerMap.compute(ChunkCoordIntPair.pair(chunkX, chunkZ), (final Long keyInMap, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { -+ return PlayerMobDistanceMap.this.pooledHashSets.findMapWithout(players, player); // rets null instead of an empty map -+ }); -+ } -+ -+ private void updatePlayer(final EntityPlayer player, final SectionPosition oldPosition, final SectionPosition newPosition, final int oldViewDistance, final int newViewDistance) { -+ final int toX = newPosition.getX(); -+ final int toZ = newPosition.getZ(); -+ final int fromX = oldPosition.getX(); -+ final int fromZ = oldPosition.getZ(); -+ -+ final int dx = toX - fromX; -+ final int dz = toZ - fromZ; -+ -+ final int totalX = Math.abs(fromX - toX); -+ final int totalZ = Math.abs(fromZ - toZ); -+ -+ if (Math.max(totalX, totalZ) > (2 * oldViewDistance)) { -+ // teleported? -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ return; -+ } -+ -+ // x axis is width -+ // z axis is height -+ // right refers to the x axis of where we moved -+ // top refers to the z axis of where we moved -+ -+ if (oldViewDistance == newViewDistance) { -+ // same view distance -+ -+ // used for relative positioning -+ final int up = 1 | (dz >> (Integer.SIZE - 1)); // 1 if dz >= 0, -1 otherwise -+ final int right = 1 | (dx >> (Integer.SIZE - 1)); // 1 if dx >= 0, -1 otherwise -+ -+ // The area excluded by overlapping the two view distance squares creates four rectangles: -+ // Two on the left, and two on the right. The ones on the left we consider the "removed" section -+ // and on the right the "added" section. -+ // https://i.imgur.com/MrnOBgI.png is a reference image. Note that the outside border is not actually -+ // exclusive to the regions they surround. -+ -+ // 4 points of the rectangle -+ int maxX; // exclusive -+ int minX; // inclusive -+ int maxZ; // exclusive -+ int minZ; // inclusive -+ -+ if (dx != 0) { -+ // handle right addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX + (oldViewDistance * right) + right; // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle up addition -+ -+ maxX = toX + (oldViewDistance * right) + right; // exclusive -+ minX = toX - (oldViewDistance * right); // inclusive -+ maxZ = toZ + (oldViewDistance * up) + up; // exclusive -+ minZ = fromZ + (oldViewDistance * up) + up; // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.addPlayerTo(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dx != 0) { -+ // handle left removal -+ -+ maxX = toX - (oldViewDistance * right); // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = fromZ + (oldViewDistance * up) + up; // exclusive -+ minZ = toZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ -+ if (dz != 0) { -+ // handle down removal -+ -+ maxX = fromX + (oldViewDistance * right) + right; // exclusive -+ minX = fromX - (oldViewDistance * right); // inclusive -+ maxZ = toZ - (oldViewDistance * up); // exclusive -+ minZ = fromZ - (oldViewDistance * up); // inclusive -+ -+ for (int currX = minX; currX != maxX; currX += right) { -+ for (int currZ = minZ; currZ != maxZ; currZ += up) { -+ this.removePlayerFrom(player, currX, currZ); -+ } -+ } -+ } -+ } else { -+ // different view distance -+ // for now :) -+ this.removePlayer(player, oldPosition, oldViewDistance); -+ this.addNewPlayer(player, newPosition, newViewDistance); -+ } -+ } -+ -+ private void removePlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.removePlayerFrom(player, x + xoff, z + zoff); -+ } -+ } -+ } -+ -+ private void addNewPlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { -+ final int x = position.getX(); -+ final int z = position.getZ(); -+ -+ for (int xoff = -viewDistance; xoff <= viewDistance; ++xoff) { -+ for (int zoff = -viewDistance; zoff <= viewDistance; ++zoff) { -+ this.addPlayerTo(player, x + xoff, z + zoff); -+ } -+ } -+ } -+} -diff --git a/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/com/destroystokyo/paper/util/PooledHashSets.java -@@ -0,0 +0,0 @@ -+package com.destroystokyo.paper.util; -+ -+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -+import java.lang.ref.WeakReference; -+import java.util.Iterator; -+ -+/** @author Spottedleaf */ -+public class PooledHashSets { -+ -+ // we really want to avoid that equals() check as much as possible... -+ protected final Object2ObjectOpenHashMap, PooledObjectLinkedOpenHashSet> mapPool = new Object2ObjectOpenHashMap<>(64, 0.25f); -+ -+ protected void decrementReferenceCount(final PooledObjectLinkedOpenHashSet current) { -+ if (current.referenceCount == 0) { -+ throw new IllegalStateException("Cannot decrement reference count for " + current); -+ } -+ if (current.referenceCount == -1 || --current.referenceCount > 0) { -+ return; -+ } -+ -+ this.mapPool.remove(current); -+ return; -+ } -+ -+ public PooledObjectLinkedOpenHashSet findMapWith(final PooledObjectLinkedOpenHashSet current, final E object) { -+ final PooledObjectLinkedOpenHashSet cached = current.getAddCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.add(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.remove(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.remove(object); -+ } -+ -+ current.updateAddCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ // rets null if current.size() == 1 -+ public PooledObjectLinkedOpenHashSet findMapWithout(final PooledObjectLinkedOpenHashSet current, final E object) { -+ if (current.set.size() == 1) { -+ decrementReferenceCount(current); -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet cached = current.getRemoveCache(object); -+ -+ if (cached != null) { -+ if (cached.referenceCount != -1) { -+ ++cached.referenceCount; -+ } -+ -+ decrementReferenceCount(current); -+ -+ return cached; -+ } -+ -+ if (!current.remove(object)) { -+ return current; -+ } -+ -+ // we use get/put since we use a different key on put -+ PooledObjectLinkedOpenHashSet ret = this.mapPool.get(current); -+ -+ if (ret == null) { -+ ret = new PooledObjectLinkedOpenHashSet<>(current); -+ current.add(object); -+ this.mapPool.put(ret, ret); -+ ret.referenceCount = 1; -+ } else { -+ if (ret.referenceCount != -1) { -+ ++ret.referenceCount; -+ } -+ current.add(object); -+ } -+ -+ current.updateRemoveCache(object, ret); -+ -+ decrementReferenceCount(current); -+ return ret; -+ } -+ -+ public static final class PooledObjectLinkedOpenHashSet implements Iterable { -+ -+ private static final WeakReference NULL_REFERENCE = new WeakReference(null); -+ -+ final ObjectLinkedOpenHashSet set; -+ int referenceCount; // -1 if special -+ int hash; // optimize hashcode -+ -+ // add cache -+ WeakReference lastAddObject = NULL_REFERENCE; -+ WeakReference> lastAddMap = NULL_REFERENCE; -+ -+ // remove cache -+ WeakReference lastRemoveObject = NULL_REFERENCE; -+ WeakReference> lastRemoveMap = NULL_REFERENCE; -+ -+ public PooledObjectLinkedOpenHashSet() { -+ this.set = new ObjectLinkedOpenHashSet<>(2, 0.6f); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final E single) { -+ this(); -+ this.referenceCount = -1; -+ this.add(single); -+ } -+ -+ public PooledObjectLinkedOpenHashSet(final PooledObjectLinkedOpenHashSet other) { -+ this.set = other.set.clone(); -+ this.hash = other.hash; -+ } -+ -+ // from https://github.com/Spottedleaf/ConcurrentUtil/blob/master/src/main/java/ca/spottedleaf/concurrentutil/util/IntegerUtil.java -+ // generated by https://github.com/skeeto/hash-prospector -+ static int hash0(int x) { -+ x *= 0x36935555; -+ x ^= x >>> 16; -+ return x; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getAddCache(final E element) { -+ final E currentAdd = this.lastAddObject.get(); -+ -+ if (currentAdd == null || !(currentAdd == element || currentAdd.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastAddMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public PooledObjectLinkedOpenHashSet getRemoveCache(final E element) { -+ final E currentRemove = this.lastRemoveObject.get(); -+ -+ if (currentRemove == null || !(currentRemove == element || currentRemove.equals(element))) { -+ return null; -+ } -+ -+ final PooledObjectLinkedOpenHashSet map = this.lastRemoveMap.get(); -+ if (map == null || map.referenceCount == 0) { -+ // we need to ret null if ref count is zero as calling code will assume the map is in use -+ return null; -+ } -+ -+ return map; -+ } -+ -+ public void updateAddCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastAddObject = new WeakReference<>(element); -+ this.lastAddMap = new WeakReference<>(map); -+ } -+ -+ public void updateRemoveCache(final E element, final PooledObjectLinkedOpenHashSet map) { -+ this.lastRemoveObject = new WeakReference<>(element); -+ this.lastRemoveMap = new WeakReference<>(map); -+ } -+ -+ boolean add(final E element) { -+ boolean added = this.set.add(element); -+ -+ if (added) { -+ this.hash += hash0(element.hashCode()); -+ } -+ -+ return added; -+ } -+ -+ boolean remove(Object element) { -+ boolean removed = this.set.remove(element); -+ -+ if (removed) { -+ this.hash -= hash0(element.hashCode()); -+ } -+ -+ return removed; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return this.set.iterator(); -+ } -+ -+ @Override -+ public int hashCode() { -+ return this.hash; -+ } -+ -+ @Override -+ public boolean equals(final Object other) { -+ if (!(other instanceof PooledObjectLinkedOpenHashSet)) { -+ return false; -+ } -+ if (this.referenceCount == 0) { -+ return other == this; -+ } else { -+ if (other == this) { -+ // Unfortunately we are never equal to our own instance while in use! -+ return false; -+ } -+ return this.hash == ((PooledObjectLinkedOpenHashSet)other).hash && this.set.equals(((PooledObjectLinkedOpenHashSet)other).set); -+ } -+ } -+ -+ @Override -+ public String toString() { -+ return "PooledHashSet: size: " + this.set.size() + ", reference count: " + this.referenceCount + ", hash: " + -+ this.hashCode() + ", identity: " + System.identityHashCode(this) + " map: " + this.set.toString(); -+ } -+ } -+} -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - this.world.getMethodProfiler().enter("naturalSpawnCount"); - this.world.timings.countNaturalMobs.startTiming(); // Paper - timings - int l = this.chunkMapDistance.b(); -- SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.A(), this::a); -+ // Paper start - per player mob spawning -+ SpawnerCreature.d spawnercreature_d; // moved down -+ if (this.playerChunkMap.playerMobDistanceMap != null) { -+ // update distance map -+ this.world.timings.playerMobDistanceMapUpdate.startTiming(); -+ this.playerChunkMap.playerMobDistanceMap.update(this.world.players, this.playerChunkMap.viewDistance); -+ this.world.timings.playerMobDistanceMapUpdate.stopTiming(); -+ // re-set mob counts -+ for (EntityPlayer player : this.world.players) { -+ Arrays.fill(player.mobCounts, 0); -+ } -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, true); -+ } else { -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, false); -+ } -+ // Paper end - this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.p = spawnercreature_d; -diff --git a/src/main/java/net/minecraft/server/level/EntityPlayer.java b/src/main/java/net/minecraft/server/level/EntityPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/EntityPlayer.java -+++ b/src/main/java/net/minecraft/server/level/EntityPlayer.java -@@ -0,0 +0,0 @@ import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityLiving; -+import net.minecraft.world.entity.EnumCreatureType; - import net.minecraft.world.entity.EnumMainHand; - import net.minecraft.world.entity.IEntityAngerable; - import net.minecraft.world.entity.animal.horse.EntityHorseAbstract; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; - // Paper end -+ // Paper start - mob spawning rework -+ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = EnumCreatureType.values().length; -+ public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper -+ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; -+ // Paper end - - // CraftBukkit start - public String displayName; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getName()); // Paper - this.canPickUpLoot = true; - this.maxHealthCache = this.getMaxHealth(); -+ this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper - } - - // Yes, this doesn't match Vanilla, but it's the best we can do for now. -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - - } - -+ public final SectionPosition getPlayerMapSection() { return this.O(); } // Paper - OBFHELPER - public SectionPosition O() { - return this.cj; - } -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.util.thread.ThreadedMailbox; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityInsentient; - import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.entity.EnumCreatureType; - import net.minecraft.world.entity.ai.village.poi.VillagePlace; - import net.minecraft.world.entity.boss.EntityComplexPart; - import net.minecraft.world.entity.player.EntityHuman; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - public final Int2ObjectMap trackedEntities; - private final Long2ByteMap z; - private final Queue A; private final Queue getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER -- private int viewDistance; -+ int viewDistance; // Paper - private -> package private -+ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper - - // CraftBukkit start - recursion-safe executor for Chunk loadCallback() and unloadCallback() - public final CallbackExecutor callbackExecutor = new CallbackExecutor(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.l = supplier; - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper - this.setViewDistance(i); -+ this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper -+ } -+ -+ public void updatePlayerMobTypeMap(Entity entity) { -+ if (!this.world.paperConfig.perPlayerMobSpawns) { -+ return; -+ } -+ int chunkX = (int)Math.floor(entity.locX()) >> 4; -+ int chunkZ = (int)Math.floor(entity.locZ()) >> 4; -+ int index = entity.getEntityType().getEnumCreatureType().ordinal(); -+ -+ for (EntityPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { -+ ++player.mobCounts[index]; -+ } -+ } -+ -+ public int getMobCountNear(EntityPlayer entityPlayer, EnumCreatureType enumCreatureType) { -+ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; - } - - private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityTypes.java b/src/main/java/net/minecraft/world/entity/EntityTypes.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityTypes.java -+++ b/src/main/java/net/minecraft/world/entity/EntityTypes.java -@@ -0,0 +0,0 @@ public class EntityTypes { - return this.bl; - } - -+ public final EnumCreatureType getEnumCreatureType() { return this.e(); } // Paper - OBFHELPER - public EnumCreatureType e() { - return this.bg; - } -diff --git a/src/main/java/net/minecraft/world/level/SpawnerCreature.java b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/SpawnerCreature.java -+++ b/src/main/java/net/minecraft/world/level/SpawnerCreature.java -@@ -0,0 +0,0 @@ import net.minecraft.core.IPosition; - import net.minecraft.core.IRegistry; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.EntityPlayer; - import net.minecraft.server.level.WorldServer; - import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - }); - - public static SpawnerCreature.d a(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b) { -+ // Paper start - add countMobs parameter -+ return countMobs(i, iterable, spawnercreature_b, false); -+ } -+ public static SpawnerCreature.d countMobs(int i, Iterable iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) { -+ // Paper end - add countMobs parameter - SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities(); - Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); - Iterator iterator = iterable.iterator(); -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - } - - object2intopenhashmap.addTo(enumcreaturetype, 1); -+ // Paper start -+ if (countMobs) { -+ ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity); -+ } -+ // Paper end - }); - } - } -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - continue; - } - -- if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && spawnercreature_d.a(enumcreaturetype, limit)) { -+ // Paper start - only allow spawns upto the limit per chunk and update count afterwards -+ int currEntityCount = spawnercreature_d.getEntityCountsByType().getInt(enumcreaturetype); -+ int k1 = limit * spawnercreature_d.getSpawnerChunks() / SpawnerCreature.b; -+ int difference = k1 - currEntityCount; -+ -+ if (worldserver.paperConfig.perPlayerMobSpawns) { -+ int minDiff = Integer.MAX_VALUE; -+ for (EntityPlayer entityplayer : worldserver.getChunkProvider().playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { -+ minDiff = Math.min(limit - worldserver.getChunkProvider().playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff); -+ } -+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; -+ } -+ // Paper end -+ -+ // Paper start - per player mob spawning -+ if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && difference > 0) { - // CraftBukkit end -- a(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { -+ int spawnCount = spawnMobs(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> { - return spawnercreature_d.a(entitytypes, blockposition, ichunkaccess); - }, (entityinsentient, ichunkaccess) -> { - spawnercreature_d.a(entityinsentient, ichunkaccess); -- }); -+ }, -+ difference, worldserver.paperConfig.perPlayerMobSpawns ? worldserver.getChunkProvider().playerChunkMap::updatePlayerMobTypeMap : null); -+ spawnercreature_d.getEntityCountsByType().mergeInt(enumcreaturetype, spawnCount, Integer::sum); -+ // Paper end - per player mob spawning - } - } - -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - } - - public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { -+ // Paper start - add parameters and int ret type -+ spawnMobs(enumcreaturetype, worldserver, chunk, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add parameters and int ret type - BlockPosition blockposition = getRandomPosition(worldserver, chunk); - - if (blockposition.getY() >= 1) { -- a(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a); -+ return spawnMobsInternal(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity); - } -+ return 0; // Paper - } - - public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) { -+ // Paper start - add maxSpawns parameter and return spawned mobs -+ spawnMobsInternal(enumcreaturetype, worldserver, ichunkaccess, blockposition, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null); -+ } -+ public static int spawnMobsInternal(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { -+ // Paper end - add maxSpawns parameter and return spawned mobs - StructureManager structuremanager = worldserver.getStructureManager(); - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); - int i = blockposition.getY(); - IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn -+ int j = 0; // Paper - moved up - - if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn - BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); -- int j = 0; -+ // Paper - moved up - int k = 0; - - while (k < 3) { -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - // Paper start - Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); - if (doSpawning == null) { -- return; -+ return j; // Paper - } - if (doSpawning && spawnercreature_c.test(biomesettingsmobs_c.c, blockposition_mutableblockposition, ichunkaccess)) { - // Paper end -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - - - if (entityinsentient == null) { -- return; -+ return j; // Paper - } - - entityinsentient.setPositionRotation(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F); -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - // CraftBukkit start - worldserver.addAllEntities(entityinsentient, SpawnReason.NATURAL); - if (!entityinsentient.dead) { -- ++j; -+ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned - ++k1; - spawnercreature_a.run(entityinsentient, ichunkaccess); -+ // Paper start -+ if (trackEntity != null) { -+ trackEntity.accept(entityinsentient); -+ } -+ // Paper end - } - // CraftBukkit end -- if (j >= entityinsentient.getMaxSpawnGroup()) { -- return; -+ if (j >= entityinsentient.getMaxSpawnGroup() || j >= maxSpawns) { // Paper -+ return j; // Paper - } - - if (entityinsentient.c(k1)) { -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - } - - } -+ return j; // Paper - } - - private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) { -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - - public static class d { - -- private final int a; -- private final Object2IntOpenHashMap b; -+ private final int a; final int getSpawnerChunks() { return this.a; } // Paper - OBFHELPER -+ private final Object2IntOpenHashMap b; final Object2IntMap getEntityCountsByType() { return this.b; } // Paper - OBFHELPER - private final SpawnerCreatureProbabilities c; - private final Object2IntMap d; - @Nullable -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - - // CraftBukkit start - private boolean a(EnumCreatureType enumcreaturetype, int limit) { -- int i = limit * this.a / SpawnerCreature.b; -+ int i = limit * this.a / SpawnerCreature.b; // Paper - diff on change, needed in the spawn method - // CraftBukkit end - - return this.b.getInt(enumcreaturetype) < i; diff --git a/Spigot-Server-Patches/improve-CraftWorld-isChunkLoaded.patch b/Spigot-Server-Patches/improve-CraftWorld-isChunkLoaded.patch deleted file mode 100644 index 013b83f911..0000000000 --- a/Spigot-Server-Patches/improve-CraftWorld-isChunkLoaded.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 21 May 2019 02:34:04 +0100 -Subject: [PATCH] improve CraftWorld#isChunkLoaded - -getChunkAt will request the chunk using vanillas chunk loading system, -which while we're not going to load the chunk, does involve the server -waiting for the execution queue to get to our request; We can just query -the chunk status and get a response now, vs having to wait - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkLoaded(int x, int z) { -- return world.getChunkProvider().isChunkLoaded(x, z); -+ return world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; // Paper - } - - @Override - public boolean isChunkGenerated(int x, int z) { - try { -- return isChunkLoaded(x, z) || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; -+ return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed) - } catch (IOException ex) { - throw new RuntimeException(ex); - } diff --git a/Spigot-Server-Patches/incremental-chunk-saving.patch b/Spigot-Server-Patches/incremental-chunk-saving.patch deleted file mode 100644 index d5718fcd1c..0000000000 --- a/Spigot-Server-Patches/incremental-chunk-saving.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 9 Jun 2019 03:53:22 +0100 -Subject: [PATCH] incremental chunk saving - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); - log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); - } -+ -+ public int autoSavePeriod = -1; -+ private void autoSavePeriod() { -+ autoSavePeriod = getInt("auto-save-interval", -1); -+ if (autoSavePeriod > 0) { -+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); -+ } else if (autoSavePeriod < 0) { -+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; -+ } -+ } -+ -+ public int maxAutoSaveChunksPerTick = 24; -+ private void maxAutoSaveChunksPerTick() { -+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); -+ } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); - public int autosavePeriod; -+ public boolean serverAutoSave = false; // Paper - public CommandDispatcher vanillaCommandDispatcher; - private boolean forceTicks; - // CraftBukkit end -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit -- MinecraftServer.LOGGER.debug("Autosave started"); -+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down -+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper -+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper - this.methodProfiler.enter("save"); -+ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper - this.playerList.savePlayers(); -- this.saveChunks(true, false, false); -+ }// Paper -+ // Paper start -+ for (WorldServer world : getWorlds()) { -+ if (world.paperConfig.autoSavePeriod > 0) { -+ world.saveIncrementally(serverAutoSave); -+ } -+ } -+ // Paper end -+ - this.methodProfiler.exit(); -- MinecraftServer.LOGGER.debug("Autosave finished"); -- } -+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper -+ //} // Paper - - this.methodProfiler.enter("snooper"); - if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - } // Paper - Timings - } - -+ // Paper start - duplicate save, but call incremental -+ public void saveIncrementally() { -+ this.tickDistanceManager(); -+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings -+ this.playerChunkMap.saveIncrementally(); -+ } // Paper - Timings -+ } -+ // Paper end -+ - @Override - public void close() throws IOException { - // CraftBukkit start -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunk.java b/src/main/java/net/minecraft/server/level/PlayerChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunk.java -@@ -0,0 +0,0 @@ public class PlayerChunk { - - private final PlayerChunkMap chunkMap; // Paper - -+ long lastAutoSaveTime; // Paper - incremental autosave -+ long inactiveTimeStart; // Paper - incremental autosave -+ - public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) { - this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size()); - this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE; -@@ -0,0 +0,0 @@ public class PlayerChunk { - boolean flag2 = playerchunk_state.isAtLeast(PlayerChunk.State.BORDER); - boolean flag3 = playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER); - -+ boolean prevHasBeenLoaded = this.hasBeenLoaded; // Paper - this.hasBeenLoaded |= flag3; -+ // Paper start - incremental autosave -+ if (this.hasBeenLoaded & !prevHasBeenLoaded) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } -+ // Paper end - if (!flag2 && flag3) { - // Paper start - cache ticking ready status - int expectCreateCount = ++this.fullChunkCreateCount; -@@ -0,0 +0,0 @@ public class PlayerChunk { - } - - public void m() { -+ boolean prev = this.hasBeenLoaded; // Paper -+ this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); -+ // Paper start - incremental autosave -+ if (prev != this.hasBeenLoaded) { -+ if (this.hasBeenLoaded) { -+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; -+ if (timeSinceAutoSave < 0) { -+ // safest bet is to assume autosave is needed here -+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod; -+ } -+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave; -+ this.chunkMap.autoSaveQueue.add(this); -+ } else { -+ this.inactiveTimeStart = this.chunkMap.world.getTime(); -+ this.chunkMap.autoSaveQueue.remove(this); -+ } -+ } -+ // Paper end -+ } -+ -+ // Paper start - incremental autosave -+ public boolean setHasBeenLoaded() { - this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER); -+ return this.hasBeenLoaded; - } -+ // Paper end - - public void a(ProtoChunkExtension protochunkextension) { - for (int i = 0; i < this.statusFutures.length(); ++i) { -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStruct - import net.minecraft.world.level.storage.Convertable; - import net.minecraft.world.level.storage.WorldPersistentData; - import net.minecraft.world.phys.Vec3D; -+import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - } - -+ // Paper start - incremental autosave -+ final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> { -+ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime); -+ if (timeCompare != 0) { -+ return timeCompare; -+ } -+ -+ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.location), MCUtil.getCoordinateKey(playerchunk2.location)); -+ }); -+ -+ protected void saveIncrementally() { -+ int savedThisTick = 0; -+ // optimized since we search far less chunks to hit ones that need to be saved -+ List reschedule = new java.util.ArrayList<>(this.world.paperConfig.maxAutoSaveChunksPerTick); -+ long currentTick = this.world.getTime(); -+ long maxSaveTime = currentTick - this.world.paperConfig.autoSavePeriod; -+ -+ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { -+ PlayerChunk playerchunk = iterator.next(); -+ if (playerchunk.lastAutoSaveTime > maxSaveTime) { -+ break; -+ } -+ -+ iterator.remove(); -+ -+ IChunkAccess ichunkaccess = playerchunk.getChunkSave().getNow(null); -+ if (ichunkaccess instanceof Chunk) { -+ boolean shouldSave = ((Chunk)ichunkaccess).lastSaved <= maxSaveTime; -+ -+ if (shouldSave && this.saveChunk(ichunkaccess)) { -+ ++savedThisTick; -+ -+ if (!playerchunk.setHasBeenLoaded()) { -+ // do not fall through to reschedule logic -+ playerchunk.inactiveTimeStart = currentTick; -+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ continue; -+ } -+ } -+ } -+ -+ reschedule.add(playerchunk); -+ -+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) { -+ break; -+ } -+ } -+ -+ for (int i = 0, len = reschedule.size(); i < len; ++i) { -+ PlayerChunk playerchunk = reschedule.get(i); -+ playerchunk.lastAutoSaveTime = this.world.getTime(); -+ this.autoSaveQueue.add(playerchunk); -+ } -+ } -+ // Paper end -+ - protected void save(boolean flag) { - if (flag) { - List list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList()); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - - this.world.unloadChunk(chunk); - } -+ this.autoSaveQueue.remove(playerchunk); // Paper - - this.lightEngine.a(ichunkaccess.getPos()); - this.lightEngine.queueUpdate(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - playerchunk.a(new ProtoChunkExtension(chunk)); - } - -+ chunk.setLastSaved(this.world.getTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks -+ - chunk.a(() -> { - return PlayerChunk.getChunkState(playerchunk.getTicketLevel()); - }); -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/WorldServer.java -+++ b/src/main/java/net/minecraft/server/level/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - return !this.server.a(this, blockposition, entityhuman) && this.getWorldBorder().a(blockposition); - } - -+ // Paper start - derived from below -+ public void saveIncrementally(boolean doFull) { -+ ChunkProviderServer chunkproviderserver = this.getChunkProvider(); -+ -+ if (doFull) { -+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); -+ } -+ -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { -+ if (doFull) { -+ this.saveData(); -+ } -+ -+ timings.worldSaveChunks.startTiming(); // Paper -+ if (!this.isSavingDisabled()) chunkproviderserver.saveIncrementally(); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ -+ -+ // Copied from save() -+ // CraftBukkit start - moved from MinecraftServer.saveChunks -+ if (doFull) { // Paper -+ WorldServer worldserver1 = this; -+ -+ worldDataServer.a(worldserver1.getWorldBorder().t()); -+ worldDataServer.setCustomBossEvents(this.server.getBossBattleCustomData().save()); -+ convertable.a(this.server.customRegistry, this.worldDataServer, this.server.getPlayerList().save()); -+ } -+ // CraftBukkit end -+ } -+ } -+ // Paper end -+ - public void save(@Nullable IProgressUpdate iprogressupdate, boolean flag, boolean flag1) { - ChunkProviderServer chunkproviderserver = this.getChunkProvider(); - -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - // CraftBukkit end - } - -+ private void saveData() { this.aj(); } // Paper - OBFHELPER - private void aj() { - if (this.dragonBattle != null) { - this.worldDataServer.a(this.dragonBattle.a()); // CraftBukkit -diff --git a/src/main/java/net/minecraft/world/level/chunk/Chunk.java b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/Chunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/Chunk.java -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { - private TickList o; - private TickList p; - private boolean q; -- private long lastSaved; -+ public long lastSaved; // Paper - private volatile boolean s; - private long inhabitedTime; - @Nullable diff --git a/Spigot-Server-Patches/living-entity-allow-attribute-registration.patch b/Spigot-Server-Patches/living-entity-allow-attribute-registration.patch deleted file mode 100644 index a6bf271d9e..0000000000 --- a/Spigot-Server-Patches/living-entity-allow-attribute-registration.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: ysl3000 -Date: Sat, 24 Oct 2020 16:37:44 +0200 -Subject: [PATCH] living entity allow attribute registration - - -diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMapBase.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - public class AttributeMapBase { - - private static final Logger LOGGER = LogManager.getLogger(); -- private final Map b = Maps.newHashMap(); -+ private final Map b = Maps.newHashMap(); private final Map attributeMap = b; // Paper - OBFHELPER - private final Set c = Sets.newHashSet(); - private final AttributeProvider d; - -@@ -0,0 +0,0 @@ public class AttributeMapBase { - } - - } -+ -+ // Paper - start -+ public void registerAttribute(AttributeBase attributeBase) { -+ AttributeModifiable attributeModifiable = new AttributeModifiable(attributeBase, AttributeModifiable::getAttribute); -+ attributeMap.put(attributeBase, attributeModifiable); -+ } -+ // Paper - end -+ - } -diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java -@@ -0,0 +0,0 @@ public class CraftAttributeMap implements Attributable { - return (nms == null) ? null : new CraftAttributeInstance(nms, attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ Preconditions.checkArgument(attribute != null, "attribute"); -+ handle.registerAttribute(CraftAttributeMap.toMinecraft(attribute)); -+ } -+ // Paper end -+ - public static AttributeBase toMinecraft(Attribute attribute) { - return IRegistry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { - return getHandle().craftAttributes.getAttribute(attribute); - } - -+ // Paper start -+ @Override -+ public void registerAttribute(Attribute attribute) { -+ getHandle().craftAttributes.registerAttribute(attribute); -+ } -+ // Paper end -+ - @Override - public void setAI(boolean ai) { - if (this.getHandle() instanceof EntityInsentient) { diff --git a/Spigot-Server-Patches/misc-debugging-dumps.patch b/Spigot-Server-Patches/misc-debugging-dumps.patch deleted file mode 100644 index 1947d7ed92..0000000000 --- a/Spigot-Server-Patches/misc-debugging-dumps.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 18 Feb 2021 20:23:28 +0000 -Subject: [PATCH] misc debugging dumps - - -diff --git a/src/main/java/io/papermc/paper/util/TraceUtil.java b/src/main/java/io/papermc/paper/util/TraceUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/TraceUtil.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.util; -+ -+import org.bukkit.Bukkit; -+ -+public final class TraceUtil { -+ -+ public static void dumpTraceForThread(Thread thread, String reason) { -+ Bukkit.getLogger().warning(thread.getName() + ": " + reason); -+ StackTraceElement[] trace = thread.getStackTrace(); -+ for (StackTraceElement traceElement : trace) { -+ Bukkit.getLogger().warning("\tat " + traceElement); -+ } -+ } -+ -+ public static void dumpTraceForThread(String reason) { -+ new Throwable(reason).printStackTrace(); -+ } -+} -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import io.netty.buffer.ByteBufOutputStream; - import io.netty.buffer.Unpooled; - import io.papermc.paper.adventure.PaperAdventure; // Paper - import io.papermc.paper.event.entity.EntityMoveEvent; -+import io.papermc.paper.util.TraceUtil; - import it.unimi.dsi.fastutil.longs.LongIterator; - import java.awt.image.BufferedImage; - import java.io.BufferedWriter; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Tue, 30 Jul 2019 03:17:16 +0500 -Subject: [PATCH] offset item frame ticking - - -diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityHanging.java -@@ -0,0 +0,0 @@ public abstract class EntityHanging extends Entity { - protected static final Predicate b = (entity) -> { - return entity instanceof EntityHanging; - }; -- private int e; -+ private int e; { this.e = this.getId() % this.world.spigotConfig.hangingTickFrequency; } // Paper - public BlockPosition blockPosition; - protected EnumDirection direction; - diff --git a/Spigot-Server-Patches/provide-a-configurable-option-to-disable-creeper-lin.patch b/Spigot-Server-Patches/provide-a-configurable-option-to-disable-creeper-lin.patch deleted file mode 100644 index f62a4790e7..0000000000 --- a/Spigot-Server-Patches/provide-a-configurable-option-to-disable-creeper-lin.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Sun, 11 Jun 2017 21:01:18 +0100 -Subject: [PATCH] provide a configurable option to disable creeper lingering - effect spawns - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); - log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); - } -+ -+ public boolean disableCreeperLingeringEffect; -+ private void setDisableCreeperLingeringEffect() { -+ disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); -+ log("Creeper lingering effect: " + disableCreeperLingeringEffect); -+ } - } -diff --git a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -+++ b/src/main/java/net/minecraft/world/entity/monster/EntityCreeper.java -@@ -0,0 +0,0 @@ public class EntityCreeper extends EntityMonster { - private void createEffectCloud() { - Collection collection = this.getEffects(); - -- if (!collection.isEmpty()) { -+ if (!collection.isEmpty() && !world.paperConfig.disableCreeperLingeringEffect) { // Paper - EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.world, this.locX(), this.locY(), this.locZ()); - - entityareaeffectcloud.setSource(this); // CraftBukkit diff --git a/Spigot-Server-Patches/remove-null-possibility-for-getServer-singleton.patch b/Spigot-Server-Patches/remove-null-possibility-for-getServer-singleton.patch deleted file mode 100644 index d931dff672..0000000000 --- a/Spigot-Server-Patches/remove-null-possibility-for-getServer-singleton.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 28 Apr 2016 00:57:27 -0400 -Subject: [PATCH] remove null possibility for getServer singleton - -to stop IDE complaining about potential NPE - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import org.spigotmc.SlackActivityAccountant; // Spigot - - public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements IMojangStatistics, ICommandListener, AutoCloseable { - -+ private static MinecraftServer SERVER; // Paper - public static final Logger LOGGER = LogManager.getLogger(); - public static final File b = new File("usercache.json"); - public static final WorldSettings c = new WorldSettings("Demo World", EnumGamemode.SURVIVAL, false, EnumDifficulty.NORMAL, false, new GameRules(), DataPackConfiguration.a); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sun, 15 Oct 2017 00:29:07 +0100 -Subject: [PATCH] revert serverside behavior of keepalives - -This patch intends to bump up the time that a client has to reply to the -server back to 30 seconds as per pre 1.12.2, which allowed clients -more than enough time to reply potentially allowing them to be less -tempermental due to lag spikes on the network thread, e.g. that caused -by plugins that are interacting with netty. - -We also add a system property to allow people to tweak how long the server -will wait for a reply. There is a compromise here between lower and higher -values, lower values will mean that dead connections can be closed sooner, -whereas higher values will make this less sensitive to issues such as spikes -from networking or during connections flood of chunk packets on slower clients, - at the cost of dead connections being kept open for longer. - -diff --git a/src/main/java/net/minecraft/server/network/PlayerConnection.java b/src/main/java/net/minecraft/server/network/PlayerConnection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/network/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private final MinecraftServer minecraftServer; - public EntityPlayer player; - private int e; -- private long lastKeepAlive; private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER -+ private long lastKeepAlive = SystemUtils.getMonotonicMillis(); private void setLastPing(long lastPing) { this.lastKeepAlive = lastPing;}; private long getLastPing() { return this.lastKeepAlive;}; // Paper - OBFHELPER - private boolean awaitingKeepAlive; private void setPendingPing(boolean isPending) { this.awaitingKeepAlive = isPending;}; private boolean isPendingPing() { return this.awaitingKeepAlive;}; // Paper - OBFHELPER - private long h; private void setKeepAliveID(long keepAliveID) { this.h = keepAliveID;}; private long getKeepAliveID() {return this.h; }; // Paper - OBFHELPER - // CraftBukkit start - multithreaded fields -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - private int E; - private int receivedMovePackets; - private int processedMovePackets; -+ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - - public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { - this.minecraftServer = minecraftserver; -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { - } - - this.minecraftServer.getMethodProfiler().enter("keepAlive"); -- long i = SystemUtils.getMonotonicMillis(); -- -- if (i - this.lastKeepAlive >= 25000L) { // CraftBukkit -- if (this.awaitingKeepAlive) { -- this.disconnect(new ChatMessage("disconnect.timeout")); -- } else { -- this.awaitingKeepAlive = true; -- this.lastKeepAlive = i; -- this.h = i; -- this.sendPacket(new PacketPlayOutKeepAlive(this.h)); -+ // Paper Start - give clients a longer time to respond to pings as per pre 1.12.2 timings -+ // This should effectively place the keepalive handling back to "as it was" before 1.12.2 -+ long currentTime = SystemUtils.getMonotonicMillis(); -+ long elapsedTime = currentTime - this.getLastPing(); -+ -+ if (this.isPendingPing()) { -+ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected -+ PlayerConnection.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getName()); // more info -+ this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); -+ } -+ } else { -+ if (elapsedTime >= 15000L) { // 15 seconds -+ this.setPendingPing(true); -+ this.setLastPing(currentTime); -+ this.setKeepAliveID(currentTime); -+ this.sendPacket(new PacketPlayOutKeepAlive(this.getKeepAliveID())); - } - } -+ // Paper end - - this.minecraftServer.getMethodProfiler().exit(); - // CraftBukkit start diff --git a/Spigot-Server-Patches/stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/Spigot-Server-Patches/stop-firing-pressure-plate-EntityInteractEvent-for-i.patch deleted file mode 100644 index 3871d37ce9..0000000000 --- a/Spigot-Server-Patches/stop-firing-pressure-plate-EntityInteractEvent-for-i.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Trigary -Date: Tue, 2 Feb 2021 09:17:59 +0100 -Subject: [PATCH] stop firing pressure plate EntityInteractEvent for ignored - entities - - -diff --git a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -+++ b/src/main/java/net/minecraft/world/level/block/BlockPressurePlateBinary.java -@@ -0,0 +0,0 @@ public class BlockPressurePlateBinary extends BlockPressurePlateAbstract { - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); -+ if (entity.isIgnoreBlockTrigger()) continue; // Paper - don't call event for ignored entities - - // CraftBukkit start - Call interact event when turning on a pressure plate - if (this.getPower(world.getType(blockposition)) == 0) { diff --git a/Spigot-Server-Patches/use-CB-BlockState-implementations-for-captured-block.patch b/Spigot-Server-Patches/use-CB-BlockState-implementations-for-captured-block.patch deleted file mode 100644 index 344f9c5df0..0000000000 --- a/Spigot-Server-Patches/use-CB-BlockState-implementations-for-captured-block.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Thu, 16 Nov 2017 12:12:41 +0000 -Subject: [PATCH] use CB BlockState implementations for captured blocks - -When modifying the world, CB will store a copy of the affected -blocks in order to restore their state in the case that the event -is cancelled. This change only modifies the collection of blocks -in the world by normal means, e.g. not during tree population, -as the potentially marginal overheads would serve no advantage. - -CB was using a CraftBlockState for all blocks, which causes issues -should any block that uses information beyond a data ID would suffer -from missing information, e.g. Skulls. - -By using CBs CraftBlock#getState(), we will maintain a proper copy of -the blockstate that will be valid for restoration, as opposed to dropping -information on restoration when the event is cancelled. - -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/World.java -+++ b/src/main/java/net/minecraft/world/level/World.java -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - - public boolean captureBlockStates = false; - public boolean captureTreeGeneration = false; -- public Map capturedBlockStates = new java.util.LinkedHashMap<>(); -+ public Map capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper - public Map capturedTileEntities = new HashMap<>(); - public List captureDrops; - public long ticksPerAnimalSpawns; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) { - // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { -- CapturedBlockState blockstate = capturedBlockStates.get(blockposition); -+ CraftBlockState blockstate = capturedBlockStates.get(blockposition); - if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); - this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - // CraftBukkit start - capture blockstates - boolean captured = false; - if (this.captureBlockStates && !this.capturedBlockStates.containsKey(blockposition)) { -- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, blockposition, i); -+ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot -+ blockstate.setFlag(i); // Paper - set flag - this.capturedBlockStates.put(blockposition.immutableCopy(), blockstate); - captured = true; - } -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - public IBlockData getType(BlockPosition blockposition) { - // CraftBukkit start - tree generation - if (captureTreeGeneration) { -- CapturedBlockState previous = capturedBlockStates.get(blockposition); -+ CraftBlockState previous = capturedBlockStates.get(blockposition); // Paper - if (previous != null) { - return previous.getHandle(); - } diff --git a/Spigot-API-Patches/POM-changes.patch b/Unmapped-Spigot-API-Patches/0001-POM-changes.patch similarity index 100% rename from Spigot-API-Patches/POM-changes.patch rename to Unmapped-Spigot-API-Patches/0001-POM-changes.patch diff --git a/Spigot-API-Patches/Add-FastUtil-to-Bukkit.patch b/Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch similarity index 100% rename from Spigot-API-Patches/Add-FastUtil-to-Bukkit.patch rename to Unmapped-Spigot-API-Patches/0002-Add-FastUtil-to-Bukkit.patch diff --git a/Spigot-API-Patches/Paper-Utils.patch b/Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch similarity index 100% rename from Spigot-API-Patches/Paper-Utils.patch rename to Unmapped-Spigot-API-Patches/0003-Paper-Utils.patch diff --git a/Spigot-API-Patches/Timings-v2.patch b/Unmapped-Spigot-API-Patches/0004-Timings-v2.patch similarity index 100% rename from Spigot-API-Patches/Timings-v2.patch rename to Unmapped-Spigot-API-Patches/0004-Timings-v2.patch diff --git a/Spigot-API-Patches/Adventure.patch b/Unmapped-Spigot-API-Patches/0005-Adventure.patch similarity index 100% rename from Spigot-API-Patches/Adventure.patch rename to Unmapped-Spigot-API-Patches/0005-Adventure.patch diff --git a/Spigot-API-Patches/Player-affects-spawning-API.patch b/Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch similarity index 100% rename from Spigot-API-Patches/Player-affects-spawning-API.patch rename to Unmapped-Spigot-API-Patches/0006-Player-affects-spawning-API.patch diff --git a/Spigot-API-Patches/Add-getTPS-method.patch b/Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch similarity index 100% rename from Spigot-API-Patches/Add-getTPS-method.patch rename to Unmapped-Spigot-API-Patches/0007-Add-getTPS-method.patch diff --git a/Spigot-API-Patches/Entity-Origin-API.patch b/Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch similarity index 100% rename from Spigot-API-Patches/Entity-Origin-API.patch rename to Unmapped-Spigot-API-Patches/0008-Entity-Origin-API.patch diff --git a/Spigot-API-Patches/Version-Command-2.0.patch b/Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch similarity index 100% rename from Spigot-API-Patches/Version-Command-2.0.patch rename to Unmapped-Spigot-API-Patches/0009-Version-Command-2.0.patch diff --git a/Spigot-API-Patches/Add-PlayerLocaleChangeEvent.patch b/Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerLocaleChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0010-Add-PlayerLocaleChangeEvent.patch diff --git a/Spigot-API-Patches/Add-player-view-distance-API.patch b/Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch similarity index 100% rename from Spigot-API-Patches/Add-player-view-distance-API.patch rename to Unmapped-Spigot-API-Patches/0011-Add-player-view-distance-API.patch diff --git a/Spigot-API-Patches/Add-BeaconEffectEvent.patch b/Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BeaconEffectEvent.patch rename to Unmapped-Spigot-API-Patches/0012-Add-BeaconEffectEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerInitialSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerInitialSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0013-Add-PlayerInitialSpawnEvent.patch diff --git a/Spigot-API-Patches/Automatically-disable-plugins-that-fail-to-load.patch b/Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch similarity index 100% rename from Spigot-API-Patches/Automatically-disable-plugins-that-fail-to-load.patch rename to Unmapped-Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch diff --git a/Spigot-API-Patches/Expose-server-CommandMap.patch b/Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch similarity index 100% rename from Spigot-API-Patches/Expose-server-CommandMap.patch rename to Unmapped-Spigot-API-Patches/0015-Expose-server-CommandMap.patch diff --git a/Spigot-API-Patches/Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch similarity index 100% rename from Spigot-API-Patches/Graduate-bungeecord-chat-API-from-spigot-subclasses.patch rename to Unmapped-Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch diff --git a/Spigot-API-Patches/Player-Tab-List-and-Title-APIs.patch b/Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from Spigot-API-Patches/Player-Tab-List-and-Title-APIs.patch rename to Unmapped-Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch diff --git a/Spigot-API-Patches/Add-exception-reporting-event.patch b/Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch similarity index 100% rename from Spigot-API-Patches/Add-exception-reporting-event.patch rename to Unmapped-Spigot-API-Patches/0018-Add-exception-reporting-event.patch diff --git a/Spigot-API-Patches/Fix-ServerListPingEvent-flagging-as-Async.patch b/Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch similarity index 100% rename from Spigot-API-Patches/Fix-ServerListPingEvent-flagging-as-Async.patch rename to Unmapped-Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch diff --git a/Spigot-API-Patches/Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch similarity index 100% rename from Spigot-API-Patches/Add-BaseComponent-sendMessage-methods-to-CommandSend.patch rename to Unmapped-Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch diff --git a/Spigot-API-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from Spigot-API-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to Unmapped-Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/Spigot-API-Patches/Complete-resource-pack-API.patch b/Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch similarity index 100% rename from Spigot-API-Patches/Complete-resource-pack-API.patch rename to Unmapped-Spigot-API-Patches/0022-Complete-resource-pack-API.patch diff --git a/Spigot-API-Patches/Use-ASM-for-event-executors.patch b/Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch similarity index 100% rename from Spigot-API-Patches/Use-ASM-for-event-executors.patch rename to Unmapped-Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch diff --git a/Spigot-API-Patches/Add-a-call-helper-to-Event.patch b/Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch similarity index 100% rename from Spigot-API-Patches/Add-a-call-helper-to-Event.patch rename to Unmapped-Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch diff --git a/Spigot-API-Patches/Add-sender-name-to-commands.yml-replacement.patch b/Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch similarity index 100% rename from Spigot-API-Patches/Add-sender-name-to-commands.yml-replacement.patch rename to Unmapped-Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch diff --git a/Spigot-API-Patches/Add-command-to-reload-permissions.yml-and-require-co.patch b/Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch similarity index 100% rename from Spigot-API-Patches/Add-command-to-reload-permissions.yml-and-require-co.patch rename to Unmapped-Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch diff --git a/Spigot-API-Patches/Custom-replacement-for-eaten-items.patch b/Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch similarity index 100% rename from Spigot-API-Patches/Custom-replacement-for-eaten-items.patch rename to Unmapped-Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch diff --git a/Spigot-API-Patches/Entity-AddTo-RemoveFrom-World-Events.patch b/Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from Spigot-API-Patches/Entity-AddTo-RemoveFrom-World-Events.patch rename to Unmapped-Spigot-API-Patches/0028-Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/Spigot-API-Patches/EntityPathfindEvent.patch b/Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch similarity index 100% rename from Spigot-API-Patches/EntityPathfindEvent.patch rename to Unmapped-Spigot-API-Patches/0029-EntityPathfindEvent.patch diff --git a/Spigot-API-Patches/Reduce-thread-synchronization-in-MetadataStoreBase.patch b/Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch similarity index 100% rename from Spigot-API-Patches/Reduce-thread-synchronization-in-MetadataStoreBase.patch rename to Unmapped-Spigot-API-Patches/0030-Reduce-thread-synchronization-in-MetadataStoreBase.patch diff --git a/Spigot-API-Patches/Add-MetadataStoreBase.removeAll-Plugin.patch b/Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch similarity index 100% rename from Spigot-API-Patches/Add-MetadataStoreBase.removeAll-Plugin.patch rename to Unmapped-Spigot-API-Patches/0031-Add-MetadataStoreBase.removeAll-Plugin.patch diff --git a/Spigot-API-Patches/Add-PlayerUseUnknownEntityEvent.patch b/Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerUseUnknownEntityEvent.patch rename to Unmapped-Spigot-API-Patches/0032-Add-PlayerUseUnknownEntityEvent.patch diff --git a/Spigot-API-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 100% rename from Spigot-API-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to Unmapped-Spigot-API-Patches/0033-Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/Spigot-API-Patches/Arrow-pickup-rule-API.patch b/Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch similarity index 100% rename from Spigot-API-Patches/Arrow-pickup-rule-API.patch rename to Unmapped-Spigot-API-Patches/0034-Arrow-pickup-rule-API.patch diff --git a/Spigot-API-Patches/EntityRegainHealthEvent-isFastRegen-API.patch b/Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from Spigot-API-Patches/EntityRegainHealthEvent-isFastRegen-API.patch rename to Unmapped-Spigot-API-Patches/0035-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/Spigot-API-Patches/LootTable-API.patch b/Unmapped-Spigot-API-Patches/0036-LootTable-API.patch similarity index 100% rename from Spigot-API-Patches/LootTable-API.patch rename to Unmapped-Spigot-API-Patches/0036-LootTable-API.patch diff --git a/Spigot-API-Patches/Add-EntityZapEvent.patch b/Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityZapEvent.patch rename to Unmapped-Spigot-API-Patches/0037-Add-EntityZapEvent.patch diff --git a/Spigot-API-Patches/Misc-Utils.patch b/Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch similarity index 100% rename from Spigot-API-Patches/Misc-Utils.patch rename to Unmapped-Spigot-API-Patches/0038-Misc-Utils.patch diff --git a/Spigot-API-Patches/Allow-Reloading-of-Command-Aliases.patch b/Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch similarity index 100% rename from Spigot-API-Patches/Allow-Reloading-of-Command-Aliases.patch rename to Unmapped-Spigot-API-Patches/0039-Allow-Reloading-of-Command-Aliases.patch diff --git a/Spigot-API-Patches/Add-source-to-PlayerExpChangeEvent.patch b/Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-source-to-PlayerExpChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0040-Add-source-to-PlayerExpChangeEvent.patch diff --git a/Spigot-API-Patches/Add-ProjectileCollideEvent.patch b/Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-ProjectileCollideEvent.patch rename to Unmapped-Spigot-API-Patches/0041-Add-ProjectileCollideEvent.patch diff --git a/Spigot-API-Patches/Add-String-based-Action-Bar-API.patch b/Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch similarity index 100% rename from Spigot-API-Patches/Add-String-based-Action-Bar-API.patch rename to Unmapped-Spigot-API-Patches/0042-Add-String-based-Action-Bar-API.patch diff --git a/Spigot-API-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch b/Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch similarity index 100% rename from Spigot-API-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch rename to Unmapped-Spigot-API-Patches/0043-Add-API-methods-to-control-if-armour-stands-can-move.patch diff --git a/Spigot-API-Patches/IllegalPacketEvent.patch b/Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch similarity index 100% rename from Spigot-API-Patches/IllegalPacketEvent.patch rename to Unmapped-Spigot-API-Patches/0044-IllegalPacketEvent.patch diff --git a/Spigot-API-Patches/Fireworks-API-s.patch b/Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch similarity index 100% rename from Spigot-API-Patches/Fireworks-API-s.patch rename to Unmapped-Spigot-API-Patches/0045-Fireworks-API-s.patch diff --git a/Spigot-API-Patches/PlayerTeleportEndGatewayEvent.patch b/Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerTeleportEndGatewayEvent.patch rename to Unmapped-Spigot-API-Patches/0046-PlayerTeleportEndGatewayEvent.patch diff --git a/Spigot-API-Patches/Provide-E-TE-Chunk-count-stat-methods.patch b/Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch similarity index 100% rename from Spigot-API-Patches/Provide-E-TE-Chunk-count-stat-methods.patch rename to Unmapped-Spigot-API-Patches/0047-Provide-E-TE-Chunk-count-stat-methods.patch diff --git a/Spigot-API-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from Spigot-API-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to Unmapped-Spigot-API-Patches/0048-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/Spigot-API-Patches/Expose-WorldBorder-isInBounds-Location-check.patch b/Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch similarity index 100% rename from Spigot-API-Patches/Expose-WorldBorder-isInBounds-Location-check.patch rename to Unmapped-Spigot-API-Patches/0049-Expose-WorldBorder-isInBounds-Location-check.patch diff --git a/Spigot-API-Patches/Add-configuration-option-to-prevent-player-names-fro.patch b/Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 100% rename from Spigot-API-Patches/Add-configuration-option-to-prevent-player-names-fro.patch rename to Unmapped-Spigot-API-Patches/0050-Add-configuration-option-to-prevent-player-names-fro.patch diff --git a/Spigot-API-Patches/Fix-upstream-javadoc-warnings-and-errors.patch b/Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch similarity index 100% rename from Spigot-API-Patches/Fix-upstream-javadoc-warnings-and-errors.patch rename to Unmapped-Spigot-API-Patches/0051-Fix-upstream-javadoc-warnings-and-errors.patch diff --git a/Spigot-API-Patches/Item-canEntityPickup.patch b/Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch similarity index 100% rename from Spigot-API-Patches/Item-canEntityPickup.patch rename to Unmapped-Spigot-API-Patches/0052-Item-canEntityPickup.patch diff --git a/Spigot-API-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch b/Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 100% rename from Spigot-API-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch rename to Unmapped-Spigot-API-Patches/0053-PlayerPickupItemEvent-setFlyAtPlayer.patch diff --git a/Spigot-API-Patches/PlayerAttemptPickupItemEvent.patch b/Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerAttemptPickupItemEvent.patch rename to Unmapped-Spigot-API-Patches/0054-PlayerAttemptPickupItemEvent.patch diff --git a/Spigot-API-Patches/Add-UnknownCommandEvent.patch b/Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-UnknownCommandEvent.patch rename to Unmapped-Spigot-API-Patches/0055-Add-UnknownCommandEvent.patch diff --git a/Spigot-API-Patches/Basic-PlayerProfile-API.patch b/Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch similarity index 100% rename from Spigot-API-Patches/Basic-PlayerProfile-API.patch rename to Unmapped-Spigot-API-Patches/0056-Basic-PlayerProfile-API.patch diff --git a/Spigot-API-Patches/Shoulder-Entities-Release-API.patch b/Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch similarity index 100% rename from Spigot-API-Patches/Shoulder-Entities-Release-API.patch rename to Unmapped-Spigot-API-Patches/0057-Shoulder-Entities-Release-API.patch diff --git a/Spigot-API-Patches/Profile-Lookup-Events.patch b/Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch similarity index 100% rename from Spigot-API-Patches/Profile-Lookup-Events.patch rename to Unmapped-Spigot-API-Patches/0058-Profile-Lookup-Events.patch diff --git a/Spigot-API-Patches/Entity-fromMobSpawner.patch b/Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch similarity index 100% rename from Spigot-API-Patches/Entity-fromMobSpawner.patch rename to Unmapped-Spigot-API-Patches/0059-Entity-fromMobSpawner.patch diff --git a/Spigot-API-Patches/Improve-the-Saddle-API-for-Horses.patch b/Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch similarity index 100% rename from Spigot-API-Patches/Improve-the-Saddle-API-for-Horses.patch rename to Unmapped-Spigot-API-Patches/0060-Improve-the-Saddle-API-for-Horses.patch diff --git a/Spigot-API-Patches/ensureServerConversions-API.patch b/Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch similarity index 100% rename from Spigot-API-Patches/ensureServerConversions-API.patch rename to Unmapped-Spigot-API-Patches/0061-ensureServerConversions-API.patch diff --git a/Spigot-API-Patches/Add-getI18NDisplayName-API.patch b/Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch similarity index 100% rename from Spigot-API-Patches/Add-getI18NDisplayName-API.patch rename to Unmapped-Spigot-API-Patches/0062-Add-getI18NDisplayName-API.patch diff --git a/Spigot-API-Patches/ProfileWhitelistVerifyEvent.patch b/Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch similarity index 100% rename from Spigot-API-Patches/ProfileWhitelistVerifyEvent.patch rename to Unmapped-Spigot-API-Patches/0063-ProfileWhitelistVerifyEvent.patch diff --git a/Spigot-API-Patches/Make-plugins-list-alphabetical.patch b/Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch similarity index 100% rename from Spigot-API-Patches/Make-plugins-list-alphabetical.patch rename to Unmapped-Spigot-API-Patches/0064-Make-plugins-list-alphabetical.patch diff --git a/Spigot-API-Patches/LivingEntity-setKiller.patch b/Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch similarity index 100% rename from Spigot-API-Patches/LivingEntity-setKiller.patch rename to Unmapped-Spigot-API-Patches/0065-LivingEntity-setKiller.patch diff --git a/Spigot-API-Patches/Handle-plugin-prefixes-in-implementation-logging-con.patch b/Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch similarity index 100% rename from Spigot-API-Patches/Handle-plugin-prefixes-in-implementation-logging-con.patch rename to Unmapped-Spigot-API-Patches/0066-Handle-plugin-prefixes-in-implementation-logging-con.patch diff --git a/Spigot-API-Patches/Allow-plugins-to-use-SLF4J-for-logging.patch b/Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch similarity index 100% rename from Spigot-API-Patches/Allow-plugins-to-use-SLF4J-for-logging.patch rename to Unmapped-Spigot-API-Patches/0067-Allow-plugins-to-use-SLF4J-for-logging.patch diff --git a/Spigot-API-Patches/Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch similarity index 100% rename from Spigot-API-Patches/Add-workaround-for-plugins-modifying-the-parent-of-t.patch rename to Unmapped-Spigot-API-Patches/0068-Add-workaround-for-plugins-modifying-the-parent-of-t.patch diff --git a/Spigot-API-Patches/Add-PlayerJumpEvent.patch b/Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerJumpEvent.patch rename to Unmapped-Spigot-API-Patches/0069-Add-PlayerJumpEvent.patch diff --git a/Spigot-API-Patches/Expose-client-protocol-version-and-virtual-host.patch b/Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch similarity index 100% rename from Spigot-API-Patches/Expose-client-protocol-version-and-virtual-host.patch rename to Unmapped-Spigot-API-Patches/0070-Expose-client-protocol-version-and-virtual-host.patch diff --git a/Spigot-API-Patches/Add-PlayerArmorChangeEvent.patch b/Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerArmorChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0071-Add-PlayerArmorChangeEvent.patch diff --git a/Spigot-API-Patches/API-to-get-a-BlockState-without-a-snapshot.patch b/Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 100% rename from Spigot-API-Patches/API-to-get-a-BlockState-without-a-snapshot.patch rename to Unmapped-Spigot-API-Patches/0072-API-to-get-a-BlockState-without-a-snapshot.patch diff --git a/Spigot-API-Patches/AsyncTabCompleteEvent.patch b/Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch similarity index 100% rename from Spigot-API-Patches/AsyncTabCompleteEvent.patch rename to Unmapped-Spigot-API-Patches/0073-AsyncTabCompleteEvent.patch diff --git a/Spigot-API-Patches/Display-warning-on-deprecated-recipe-API.patch b/Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch similarity index 100% rename from Spigot-API-Patches/Display-warning-on-deprecated-recipe-API.patch rename to Unmapped-Spigot-API-Patches/0074-Display-warning-on-deprecated-recipe-API.patch diff --git a/Spigot-API-Patches/PlayerPickupExperienceEvent.patch b/Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerPickupExperienceEvent.patch rename to Unmapped-Spigot-API-Patches/0075-PlayerPickupExperienceEvent.patch diff --git a/Spigot-API-Patches/ExperienceOrbMergeEvent.patch b/Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch similarity index 100% rename from Spigot-API-Patches/ExperienceOrbMergeEvent.patch rename to Unmapped-Spigot-API-Patches/0076-ExperienceOrbMergeEvent.patch diff --git a/Spigot-API-Patches/Ability-to-apply-mending-to-XP-API.patch b/Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch similarity index 100% rename from Spigot-API-Patches/Ability-to-apply-mending-to-XP-API.patch rename to Unmapped-Spigot-API-Patches/0077-Ability-to-apply-mending-to-XP-API.patch diff --git a/Spigot-API-Patches/PreCreatureSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/PreCreatureSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0078-PreCreatureSpawnEvent.patch diff --git a/Spigot-API-Patches/PlayerNaturallySpawnCreaturesEvent.patch b/Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerNaturallySpawnCreaturesEvent.patch rename to Unmapped-Spigot-API-Patches/0079-PlayerNaturallySpawnCreaturesEvent.patch diff --git a/Spigot-API-Patches/Add-setPlayerProfile-API-for-Skulls.patch b/Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from Spigot-API-Patches/Add-setPlayerProfile-API-for-Skulls.patch rename to Unmapped-Spigot-API-Patches/0080-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/Spigot-API-Patches/Fill-Profile-Property-Events.patch b/Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch similarity index 100% rename from Spigot-API-Patches/Fill-Profile-Property-Events.patch rename to Unmapped-Spigot-API-Patches/0081-Fill-Profile-Property-Events.patch diff --git a/Spigot-API-Patches/PlayerAdvancementCriterionGrantEvent.patch b/Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerAdvancementCriterionGrantEvent.patch rename to Unmapped-Spigot-API-Patches/0082-PlayerAdvancementCriterionGrantEvent.patch diff --git a/Spigot-API-Patches/Add-ArmorStand-Item-Meta.patch b/Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from Spigot-API-Patches/Add-ArmorStand-Item-Meta.patch rename to Unmapped-Spigot-API-Patches/0083-Add-ArmorStand-Item-Meta.patch diff --git a/Spigot-API-Patches/Optimize-Hoppers.patch b/Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch similarity index 100% rename from Spigot-API-Patches/Optimize-Hoppers.patch rename to Unmapped-Spigot-API-Patches/0084-Optimize-Hoppers.patch diff --git a/Spigot-API-Patches/Tameable-getOwnerUniqueId-API.patch b/Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from Spigot-API-Patches/Tameable-getOwnerUniqueId-API.patch rename to Unmapped-Spigot-API-Patches/0085-Tameable-getOwnerUniqueId-API.patch diff --git a/Spigot-API-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from Spigot-API-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to Unmapped-Spigot-API-Patches/0086-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/Spigot-API-Patches/Add-extended-PaperServerListPingEvent.patch b/Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-extended-PaperServerListPingEvent.patch rename to Unmapped-Spigot-API-Patches/0087-Add-extended-PaperServerListPingEvent.patch diff --git a/Spigot-API-Patches/Player.setPlayerProfile-API.patch b/Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch similarity index 100% rename from Spigot-API-Patches/Player.setPlayerProfile-API.patch rename to Unmapped-Spigot-API-Patches/0088-Player.setPlayerProfile-API.patch diff --git a/Spigot-API-Patches/getPlayerUniqueId-API.patch b/Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch similarity index 100% rename from Spigot-API-Patches/getPlayerUniqueId-API.patch rename to Unmapped-Spigot-API-Patches/0089-getPlayerUniqueId-API.patch diff --git a/Spigot-API-Patches/Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-legacy-ping-support-to-PaperServerListPingEvent.patch rename to Unmapped-Spigot-API-Patches/0090-Add-legacy-ping-support-to-PaperServerListPingEvent.patch diff --git a/Spigot-API-Patches/Add-method-to-open-already-placed-sign.patch b/Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch similarity index 100% rename from Spigot-API-Patches/Add-method-to-open-already-placed-sign.patch rename to Unmapped-Spigot-API-Patches/0091-Add-method-to-open-already-placed-sign.patch diff --git a/Spigot-API-Patches/Add-Ban-Methods-to-Player-Objects.patch b/Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch similarity index 100% rename from Spigot-API-Patches/Add-Ban-Methods-to-Player-Objects.patch rename to Unmapped-Spigot-API-Patches/0092-Add-Ban-Methods-to-Player-Objects.patch diff --git a/Spigot-API-Patches/EndermanEscapeEvent.patch b/Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch similarity index 100% rename from Spigot-API-Patches/EndermanEscapeEvent.patch rename to Unmapped-Spigot-API-Patches/0093-EndermanEscapeEvent.patch diff --git a/Spigot-API-Patches/Enderman.teleportRandomly.patch b/Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch similarity index 100% rename from Spigot-API-Patches/Enderman.teleportRandomly.patch rename to Unmapped-Spigot-API-Patches/0094-Enderman.teleportRandomly.patch diff --git a/Spigot-API-Patches/Additional-world.getNearbyEntities-API-s.patch b/Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch similarity index 100% rename from Spigot-API-Patches/Additional-world.getNearbyEntities-API-s.patch rename to Unmapped-Spigot-API-Patches/0095-Additional-world.getNearbyEntities-API-s.patch diff --git a/Spigot-API-Patches/Location.isChunkLoaded-API.patch b/Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch similarity index 100% rename from Spigot-API-Patches/Location.isChunkLoaded-API.patch rename to Unmapped-Spigot-API-Patches/0096-Location.isChunkLoaded-API.patch diff --git a/Spigot-API-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch b/Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from Spigot-API-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch rename to Unmapped-Spigot-API-Patches/0097-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/Spigot-API-Patches/EndermanAttackPlayerEvent.patch b/Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch similarity index 100% rename from Spigot-API-Patches/EndermanAttackPlayerEvent.patch rename to Unmapped-Spigot-API-Patches/0098-EndermanAttackPlayerEvent.patch diff --git a/Spigot-API-Patches/Close-Plugin-Class-Loaders-on-Disable.patch b/Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch similarity index 100% rename from Spigot-API-Patches/Close-Plugin-Class-Loaders-on-Disable.patch rename to Unmapped-Spigot-API-Patches/0099-Close-Plugin-Class-Loaders-on-Disable.patch diff --git a/Spigot-API-Patches/WitchConsumePotionEvent.patch b/Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch similarity index 100% rename from Spigot-API-Patches/WitchConsumePotionEvent.patch rename to Unmapped-Spigot-API-Patches/0100-WitchConsumePotionEvent.patch diff --git a/Spigot-API-Patches/WitchThrowPotionEvent.patch b/Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch similarity index 100% rename from Spigot-API-Patches/WitchThrowPotionEvent.patch rename to Unmapped-Spigot-API-Patches/0101-WitchThrowPotionEvent.patch diff --git a/Spigot-API-Patches/Location.toBlockLocation-toCenterLocation.patch b/Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch similarity index 100% rename from Spigot-API-Patches/Location.toBlockLocation-toCenterLocation.patch rename to Unmapped-Spigot-API-Patches/0102-Location.toBlockLocation-toCenterLocation.patch diff --git a/Spigot-API-Patches/PotionEffect-clone-methods.patch b/Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch similarity index 100% rename from Spigot-API-Patches/PotionEffect-clone-methods.patch rename to Unmapped-Spigot-API-Patches/0103-PotionEffect-clone-methods.patch diff --git a/Spigot-API-Patches/WitchReadyPotionEvent.patch b/Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch similarity index 100% rename from Spigot-API-Patches/WitchReadyPotionEvent.patch rename to Unmapped-Spigot-API-Patches/0104-WitchReadyPotionEvent.patch diff --git a/Spigot-API-Patches/ItemStack-getMaxItemUseDuration.patch b/Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from Spigot-API-Patches/ItemStack-getMaxItemUseDuration.patch rename to Unmapped-Spigot-API-Patches/0105-ItemStack-getMaxItemUseDuration.patch diff --git a/Spigot-API-Patches/Add-EntityTeleportEndGatewayEvent.patch b/Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityTeleportEndGatewayEvent.patch rename to Unmapped-Spigot-API-Patches/0106-Add-EntityTeleportEndGatewayEvent.patch diff --git a/Spigot-API-Patches/Make-shield-blocking-delay-configurable.patch b/Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch similarity index 100% rename from Spigot-API-Patches/Make-shield-blocking-delay-configurable.patch rename to Unmapped-Spigot-API-Patches/0107-Make-shield-blocking-delay-configurable.patch diff --git a/Spigot-API-Patches/EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch similarity index 100% rename from Spigot-API-Patches/EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch rename to Unmapped-Spigot-API-Patches/0108-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch diff --git a/Spigot-API-Patches/Add-getNearbyXXX-methods-to-Location.patch b/Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch similarity index 100% rename from Spigot-API-Patches/Add-getNearbyXXX-methods-to-Location.patch rename to Unmapped-Spigot-API-Patches/0109-Add-getNearbyXXX-methods-to-Location.patch diff --git a/Spigot-API-Patches/PlayerReadyArrowEvent.patch b/Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerReadyArrowEvent.patch rename to Unmapped-Spigot-API-Patches/0110-PlayerReadyArrowEvent.patch diff --git a/Spigot-API-Patches/Add-EntityKnockbackByEntityEvent.patch b/Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityKnockbackByEntityEvent.patch rename to Unmapped-Spigot-API-Patches/0111-Add-EntityKnockbackByEntityEvent.patch diff --git a/Spigot-API-Patches/Expand-Explosions-API.patch b/Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch similarity index 100% rename from Spigot-API-Patches/Expand-Explosions-API.patch rename to Unmapped-Spigot-API-Patches/0112-Expand-Explosions-API.patch diff --git a/Spigot-API-Patches/ItemStack-API-additions-for-quantity-flags-lore.patch b/Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch similarity index 100% rename from Spigot-API-Patches/ItemStack-API-additions-for-quantity-flags-lore.patch rename to Unmapped-Spigot-API-Patches/0113-ItemStack-API-additions-for-quantity-flags-lore.patch diff --git a/Spigot-API-Patches/LivingEntity-Hand-Raised-Item-Use-API.patch b/Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from Spigot-API-Patches/LivingEntity-Hand-Raised-Item-Use-API.patch rename to Unmapped-Spigot-API-Patches/0114-LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/Spigot-API-Patches/RangedEntity-API.patch b/Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch similarity index 100% rename from Spigot-API-Patches/RangedEntity-API.patch rename to Unmapped-Spigot-API-Patches/0115-RangedEntity-API.patch diff --git a/Spigot-API-Patches/Add-World.getEntity-UUID-API.patch b/Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch similarity index 100% rename from Spigot-API-Patches/Add-World.getEntity-UUID-API.patch rename to Unmapped-Spigot-API-Patches/0116-Add-World.getEntity-UUID-API.patch diff --git a/Spigot-API-Patches/InventoryCloseEvent-Reason-API.patch b/Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch similarity index 100% rename from Spigot-API-Patches/InventoryCloseEvent-Reason-API.patch rename to Unmapped-Spigot-API-Patches/0117-InventoryCloseEvent-Reason-API.patch diff --git a/Spigot-API-Patches/Entity-getChunk-API.patch b/Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch similarity index 100% rename from Spigot-API-Patches/Entity-getChunk-API.patch rename to Unmapped-Spigot-API-Patches/0118-Entity-getChunk-API.patch diff --git a/Spigot-API-Patches/Add-an-asterisk-to-legacy-API-plugins.patch b/Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch similarity index 100% rename from Spigot-API-Patches/Add-an-asterisk-to-legacy-API-plugins.patch rename to Unmapped-Spigot-API-Patches/0119-Add-an-asterisk-to-legacy-API-plugins.patch diff --git a/Spigot-API-Patches/EnderDragon-Events.patch b/Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch similarity index 100% rename from Spigot-API-Patches/EnderDragon-Events.patch rename to Unmapped-Spigot-API-Patches/0120-EnderDragon-Events.patch diff --git a/Spigot-API-Patches/PlayerLaunchProjectileEvent.patch b/Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerLaunchProjectileEvent.patch rename to Unmapped-Spigot-API-Patches/0121-PlayerLaunchProjectileEvent.patch diff --git a/Spigot-API-Patches/PlayerElytraBoostEvent.patch b/Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerElytraBoostEvent.patch rename to Unmapped-Spigot-API-Patches/0122-PlayerElytraBoostEvent.patch diff --git a/Spigot-API-Patches/EntityTransformedEvent.patch b/Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch similarity index 100% rename from Spigot-API-Patches/EntityTransformedEvent.patch rename to Unmapped-Spigot-API-Patches/0123-EntityTransformedEvent.patch diff --git a/Spigot-API-Patches/Allow-disabling-armour-stand-ticking.patch b/Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch similarity index 100% rename from Spigot-API-Patches/Allow-disabling-armour-stand-ticking.patch rename to Unmapped-Spigot-API-Patches/0124-Allow-disabling-armour-stand-ticking.patch diff --git a/Spigot-API-Patches/SkeletonHorse-Additions.patch b/Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch similarity index 100% rename from Spigot-API-Patches/SkeletonHorse-Additions.patch rename to Unmapped-Spigot-API-Patches/0125-SkeletonHorse-Additions.patch diff --git a/Spigot-API-Patches/Expand-Location-Manipulation-API.patch b/Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch similarity index 100% rename from Spigot-API-Patches/Expand-Location-Manipulation-API.patch rename to Unmapped-Spigot-API-Patches/0126-Expand-Location-Manipulation-API.patch diff --git a/Spigot-API-Patches/Expand-ArmorStand-API.patch b/Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch similarity index 100% rename from Spigot-API-Patches/Expand-ArmorStand-API.patch rename to Unmapped-Spigot-API-Patches/0127-Expand-ArmorStand-API.patch diff --git a/Spigot-API-Patches/AnvilDamageEvent.patch b/Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch similarity index 100% rename from Spigot-API-Patches/AnvilDamageEvent.patch rename to Unmapped-Spigot-API-Patches/0128-AnvilDamageEvent.patch diff --git a/Spigot-API-Patches/Remove-deadlock-risk-in-firing-async-events.patch b/Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch similarity index 100% rename from Spigot-API-Patches/Remove-deadlock-risk-in-firing-async-events.patch rename to Unmapped-Spigot-API-Patches/0129-Remove-deadlock-risk-in-firing-async-events.patch diff --git a/Spigot-API-Patches/Add-hand-to-bucket-events.patch b/Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch similarity index 100% rename from Spigot-API-Patches/Add-hand-to-bucket-events.patch rename to Unmapped-Spigot-API-Patches/0130-Add-hand-to-bucket-events.patch diff --git a/Spigot-API-Patches/Add-TNTPrimeEvent.patch b/Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-TNTPrimeEvent.patch rename to Unmapped-Spigot-API-Patches/0131-Add-TNTPrimeEvent.patch diff --git a/Spigot-API-Patches/Provide-Chunk-Coordinates-as-a-Long-API.patch b/Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch similarity index 100% rename from Spigot-API-Patches/Provide-Chunk-Coordinates-as-a-Long-API.patch rename to Unmapped-Spigot-API-Patches/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch diff --git a/Spigot-API-Patches/Async-Chunks-API.patch b/Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch similarity index 100% rename from Spigot-API-Patches/Async-Chunks-API.patch rename to Unmapped-Spigot-API-Patches/0133-Async-Chunks-API.patch diff --git a/Spigot-API-Patches/Make-EnderDragon-extend-Mob.patch b/Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch similarity index 100% rename from Spigot-API-Patches/Make-EnderDragon-extend-Mob.patch rename to Unmapped-Spigot-API-Patches/0134-Make-EnderDragon-extend-Mob.patch diff --git a/Spigot-API-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from Spigot-API-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to Unmapped-Spigot-API-Patches/0135-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/Spigot-API-Patches/Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch similarity index 100% rename from Spigot-API-Patches/Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch rename to Unmapped-Spigot-API-Patches/0136-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch diff --git a/Spigot-API-Patches/Allow-Blocks-to-be-accessed-via-a-long-key.patch b/Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch similarity index 100% rename from Spigot-API-Patches/Allow-Blocks-to-be-accessed-via-a-long-key.patch rename to Unmapped-Spigot-API-Patches/0137-Allow-Blocks-to-be-accessed-via-a-long-key.patch diff --git a/Spigot-API-Patches/Slime-Pathfinder-Events.patch b/Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch similarity index 100% rename from Spigot-API-Patches/Slime-Pathfinder-Events.patch rename to Unmapped-Spigot-API-Patches/0138-Slime-Pathfinder-Events.patch diff --git a/Spigot-API-Patches/isChunkGenerated-API.patch b/Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch similarity index 100% rename from Spigot-API-Patches/isChunkGenerated-API.patch rename to Unmapped-Spigot-API-Patches/0139-isChunkGenerated-API.patch diff --git a/Spigot-API-Patches/Add-More-Creeper-API.patch b/Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch similarity index 100% rename from Spigot-API-Patches/Add-More-Creeper-API.patch rename to Unmapped-Spigot-API-Patches/0140-Add-More-Creeper-API.patch diff --git a/Spigot-API-Patches/Add-PhantomPreSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PhantomPreSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0141-Add-PhantomPreSpawnEvent.patch diff --git a/Spigot-API-Patches/Add-source-block-to-BlockPhysicsEvent.patch b/Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-source-block-to-BlockPhysicsEvent.patch rename to Unmapped-Spigot-API-Patches/0142-Add-source-block-to-BlockPhysicsEvent.patch diff --git a/Spigot-API-Patches/Inventory-removeItemAnySlot.patch b/Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch similarity index 100% rename from Spigot-API-Patches/Inventory-removeItemAnySlot.patch rename to Unmapped-Spigot-API-Patches/0143-Inventory-removeItemAnySlot.patch diff --git a/Spigot-API-Patches/Add-ray-tracing-methods-to-LivingEntity.patch b/Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 100% rename from Spigot-API-Patches/Add-ray-tracing-methods-to-LivingEntity.patch rename to Unmapped-Spigot-API-Patches/0144-Add-ray-tracing-methods-to-LivingEntity.patch diff --git a/Spigot-API-Patches/Improve-death-events.patch b/Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch similarity index 100% rename from Spigot-API-Patches/Improve-death-events.patch rename to Unmapped-Spigot-API-Patches/0145-Improve-death-events.patch diff --git a/Spigot-API-Patches/Mob-Pathfinding-API.patch b/Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch similarity index 100% rename from Spigot-API-Patches/Mob-Pathfinding-API.patch rename to Unmapped-Spigot-API-Patches/0146-Mob-Pathfinding-API.patch diff --git a/Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch b/Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch rename to Unmapped-Spigot-API-Patches/0147-Expose-attack-cooldown-methods-for-Player.patch diff --git a/Spigot-API-Patches/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch similarity index 100% rename from Spigot-API-Patches/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch rename to Unmapped-Spigot-API-Patches/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch diff --git a/Spigot-API-Patches/Performance-Concurrency-Improvements-to-Permissions.patch b/Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch similarity index 100% rename from Spigot-API-Patches/Performance-Concurrency-Improvements-to-Permissions.patch rename to Unmapped-Spigot-API-Patches/0149-Performance-Concurrency-Improvements-to-Permissions.patch diff --git a/Spigot-API-Patches/Add-ItemStackRecipeChoice-Draft-API.patch b/Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch similarity index 100% rename from Spigot-API-Patches/Add-ItemStackRecipeChoice-Draft-API.patch rename to Unmapped-Spigot-API-Patches/0150-Add-ItemStackRecipeChoice-Draft-API.patch diff --git a/Spigot-API-Patches/Implement-furnace-cook-speed-multiplier-API.patch b/Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from Spigot-API-Patches/Implement-furnace-cook-speed-multiplier-API.patch rename to Unmapped-Spigot-API-Patches/0151-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/Spigot-API-Patches/PreSpawnerSpawnEvent.patch b/Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/PreSpawnerSpawnEvent.patch rename to Unmapped-Spigot-API-Patches/0152-PreSpawnerSpawnEvent.patch diff --git a/Spigot-API-Patches/Material-API-additions.patch b/Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch similarity index 100% rename from Spigot-API-Patches/Material-API-additions.patch rename to Unmapped-Spigot-API-Patches/0153-Material-API-additions.patch diff --git a/Spigot-API-Patches/Add-Material-Tags.patch b/Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch similarity index 100% rename from Spigot-API-Patches/Add-Material-Tags.patch rename to Unmapped-Spigot-API-Patches/0154-Add-Material-Tags.patch diff --git a/Spigot-API-Patches/Allow-setting-the-vex-s-summoner.patch b/Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch similarity index 100% rename from Spigot-API-Patches/Allow-setting-the-vex-s-summoner.patch rename to Unmapped-Spigot-API-Patches/0155-Allow-setting-the-vex-s-summoner.patch diff --git a/Spigot-API-Patches/Add-LivingEntity-getTargetEntity.patch b/Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch similarity index 100% rename from Spigot-API-Patches/Add-LivingEntity-getTargetEntity.patch rename to Unmapped-Spigot-API-Patches/0156-Add-LivingEntity-getTargetEntity.patch diff --git a/Spigot-API-Patches/Add-sun-related-API.patch b/Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch similarity index 100% rename from Spigot-API-Patches/Add-sun-related-API.patch rename to Unmapped-Spigot-API-Patches/0157-Add-sun-related-API.patch diff --git a/Spigot-API-Patches/Here-s-Johnny.patch b/Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch similarity index 100% rename from Spigot-API-Patches/Here-s-Johnny.patch rename to Unmapped-Spigot-API-Patches/0158-Here-s-Johnny.patch diff --git a/Spigot-API-Patches/Turtle-API.patch b/Unmapped-Spigot-API-Patches/0159-Turtle-API.patch similarity index 100% rename from Spigot-API-Patches/Turtle-API.patch rename to Unmapped-Spigot-API-Patches/0159-Turtle-API.patch diff --git a/Spigot-API-Patches/Add-spectator-target-events.patch b/Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch similarity index 100% rename from Spigot-API-Patches/Add-spectator-target-events.patch rename to Unmapped-Spigot-API-Patches/0160-Add-spectator-target-events.patch diff --git a/Spigot-API-Patches/Add-more-Witch-API.patch b/Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-Witch-API.patch rename to Unmapped-Spigot-API-Patches/0161-Add-more-Witch-API.patch diff --git a/Spigot-API-Patches/Make-the-default-permission-message-configurable.patch b/Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch similarity index 100% rename from Spigot-API-Patches/Make-the-default-permission-message-configurable.patch rename to Unmapped-Spigot-API-Patches/0162-Make-the-default-permission-message-configurable.patch diff --git a/Spigot-API-Patches/Support-cancellation-supression-of-EntityDismount-Ve.patch b/Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch similarity index 100% rename from Spigot-API-Patches/Support-cancellation-supression-of-EntityDismount-Ve.patch rename to Unmapped-Spigot-API-Patches/0163-Support-cancellation-supression-of-EntityDismount-Ve.patch diff --git a/Spigot-API-Patches/Add-more-Zombie-API.patch b/Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-Zombie-API.patch rename to Unmapped-Spigot-API-Patches/0164-Add-more-Zombie-API.patch diff --git a/Spigot-API-Patches/Change-the-reserved-channel-check-to-be-sensible.patch b/Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch similarity index 100% rename from Spigot-API-Patches/Change-the-reserved-channel-check-to-be-sensible.patch rename to Unmapped-Spigot-API-Patches/0165-Change-the-reserved-channel-check-to-be-sensible.patch diff --git a/Spigot-API-Patches/Add-PlayerConnectionCloseEvent.patch b/Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerConnectionCloseEvent.patch rename to Unmapped-Spigot-API-Patches/0166-Add-PlayerConnectionCloseEvent.patch diff --git a/Spigot-API-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from Spigot-API-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to Unmapped-Spigot-API-Patches/0167-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/Spigot-API-Patches/BlockDestroyEvent.patch b/Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch similarity index 100% rename from Spigot-API-Patches/BlockDestroyEvent.patch rename to Unmapped-Spigot-API-Patches/0168-BlockDestroyEvent.patch diff --git a/Spigot-API-Patches/Add-ItemStack-Recipe-API-helper-methods.patch b/Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch similarity index 100% rename from Spigot-API-Patches/Add-ItemStack-Recipe-API-helper-methods.patch rename to Unmapped-Spigot-API-Patches/0169-Add-ItemStack-Recipe-API-helper-methods.patch diff --git a/Spigot-API-Patches/Add-WhitelistToggleEvent.patch b/Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-WhitelistToggleEvent.patch rename to Unmapped-Spigot-API-Patches/0170-Add-WhitelistToggleEvent.patch diff --git a/Spigot-API-Patches/Annotation-Test-changes.patch b/Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch similarity index 100% rename from Spigot-API-Patches/Annotation-Test-changes.patch rename to Unmapped-Spigot-API-Patches/0171-Annotation-Test-changes.patch diff --git a/Spigot-API-Patches/Entity-getEntitySpawnReason.patch b/Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch similarity index 100% rename from Spigot-API-Patches/Entity-getEntitySpawnReason.patch rename to Unmapped-Spigot-API-Patches/0172-Entity-getEntitySpawnReason.patch diff --git a/Spigot-API-Patches/Add-GS4-Query-event.patch b/Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch similarity index 100% rename from Spigot-API-Patches/Add-GS4-Query-event.patch rename to Unmapped-Spigot-API-Patches/0173-Add-GS4-Query-event.patch diff --git a/Spigot-API-Patches/Add-PlayerPostRespawnEvent.patch b/Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerPostRespawnEvent.patch rename to Unmapped-Spigot-API-Patches/0174-Add-PlayerPostRespawnEvent.patch diff --git a/Spigot-API-Patches/Ignore-package-private-methods-for-nullability-annot.patch b/Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch similarity index 100% rename from Spigot-API-Patches/Ignore-package-private-methods-for-nullability-annot.patch rename to Unmapped-Spigot-API-Patches/0175-Ignore-package-private-methods-for-nullability-annot.patch diff --git a/Spigot-API-Patches/Flip-some-Spigot-API-null-annotations.patch b/Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch similarity index 100% rename from Spigot-API-Patches/Flip-some-Spigot-API-null-annotations.patch rename to Unmapped-Spigot-API-Patches/0176-Flip-some-Spigot-API-null-annotations.patch diff --git a/Spigot-API-Patches/Server-Tick-Events.patch b/Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch similarity index 100% rename from Spigot-API-Patches/Server-Tick-Events.patch rename to Unmapped-Spigot-API-Patches/0177-Server-Tick-Events.patch diff --git a/Spigot-API-Patches/PlayerDeathEvent-getItemsToKeep.patch b/Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from Spigot-API-Patches/PlayerDeathEvent-getItemsToKeep.patch rename to Unmapped-Spigot-API-Patches/0178-PlayerDeathEvent-getItemsToKeep.patch diff --git a/Spigot-API-Patches/Add-Heightmap-API.patch b/Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Heightmap-API.patch rename to Unmapped-Spigot-API-Patches/0179-Add-Heightmap-API.patch diff --git a/Spigot-API-Patches/Mob-Spawner-API-Enhancements.patch b/Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from Spigot-API-Patches/Mob-Spawner-API-Enhancements.patch rename to Unmapped-Spigot-API-Patches/0180-Mob-Spawner-API-Enhancements.patch diff --git a/Spigot-API-Patches/Add-BlockSoundGroup-interface.patch b/Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch similarity index 100% rename from Spigot-API-Patches/Add-BlockSoundGroup-interface.patch rename to Unmapped-Spigot-API-Patches/0181-Add-BlockSoundGroup-interface.patch diff --git a/Spigot-API-Patches/Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch similarity index 100% rename from Spigot-API-Patches/Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch rename to Unmapped-Spigot-API-Patches/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch diff --git a/Spigot-API-Patches/Increase-custom-payload-channel-message-size.patch b/Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch similarity index 100% rename from Spigot-API-Patches/Increase-custom-payload-channel-message-size.patch rename to Unmapped-Spigot-API-Patches/0183-Increase-custom-payload-channel-message-size.patch diff --git a/Spigot-API-Patches/Expose-the-internal-current-tick.patch b/Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch similarity index 100% rename from Spigot-API-Patches/Expose-the-internal-current-tick.patch rename to Unmapped-Spigot-API-Patches/0184-Expose-the-internal-current-tick.patch diff --git a/Spigot-API-Patches/PlayerDeathEvent-shouldDropExperience.patch b/Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from Spigot-API-Patches/PlayerDeathEvent-shouldDropExperience.patch rename to Unmapped-Spigot-API-Patches/0185-PlayerDeathEvent-shouldDropExperience.patch diff --git a/Spigot-API-Patches/Add-effect-to-block-break-naturally.patch b/Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch similarity index 100% rename from Spigot-API-Patches/Add-effect-to-block-break-naturally.patch rename to Unmapped-Spigot-API-Patches/0186-Add-effect-to-block-break-naturally.patch diff --git a/Spigot-API-Patches/Add-ThrownEggHatchEvent.patch b/Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-ThrownEggHatchEvent.patch rename to Unmapped-Spigot-API-Patches/0187-Add-ThrownEggHatchEvent.patch diff --git a/Spigot-API-Patches/Entity-Jump-API.patch b/Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch similarity index 100% rename from Spigot-API-Patches/Entity-Jump-API.patch rename to Unmapped-Spigot-API-Patches/0188-Entity-Jump-API.patch diff --git a/Spigot-API-Patches/add-hand-to-BlockMultiPlaceEvent.patch b/Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from Spigot-API-Patches/add-hand-to-BlockMultiPlaceEvent.patch rename to Unmapped-Spigot-API-Patches/0189-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/Spigot-API-Patches/Add-tick-times-API.patch b/Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch similarity index 100% rename from Spigot-API-Patches/Add-tick-times-API.patch rename to Unmapped-Spigot-API-Patches/0190-Add-tick-times-API.patch diff --git a/Spigot-API-Patches/Expose-MinecraftServer-isRunning.patch b/Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from Spigot-API-Patches/Expose-MinecraftServer-isRunning.patch rename to Unmapped-Spigot-API-Patches/0191-Expose-MinecraftServer-isRunning.patch diff --git a/Spigot-API-Patches/Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch similarity index 100% rename from Spigot-API-Patches/Disable-Sync-Events-firing-Async-errors-during-shutd.patch rename to Unmapped-Spigot-API-Patches/0192-Disable-Sync-Events-firing-Async-errors-during-shutd.patch diff --git a/Spigot-API-Patches/Make-JavaPluginLoader-thread-safe.patch b/Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch similarity index 100% rename from Spigot-API-Patches/Make-JavaPluginLoader-thread-safe.patch rename to Unmapped-Spigot-API-Patches/0193-Make-JavaPluginLoader-thread-safe.patch diff --git a/Spigot-API-Patches/Add-Player-Client-Options-API.patch b/Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Player-Client-Options-API.patch rename to Unmapped-Spigot-API-Patches/0194-Add-Player-Client-Options-API.patch diff --git a/Spigot-API-Patches/Add-PlayerAttackEntityCooldownResetEvent.patch b/Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerAttackEntityCooldownResetEvent.patch rename to Unmapped-Spigot-API-Patches/0195-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/Spigot-API-Patches/Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch similarity index 100% rename from Spigot-API-Patches/Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch rename to Unmapped-Spigot-API-Patches/0196-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch diff --git a/Spigot-API-Patches/Villager-Restocks-API.patch b/Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch similarity index 100% rename from Spigot-API-Patches/Villager-Restocks-API.patch rename to Unmapped-Spigot-API-Patches/0197-Villager-Restocks-API.patch diff --git a/Spigot-API-Patches/Expose-game-version.patch b/Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch similarity index 100% rename from Spigot-API-Patches/Expose-game-version.patch rename to Unmapped-Spigot-API-Patches/0198-Expose-game-version.patch diff --git a/Spigot-API-Patches/Add-item-slot-convenience-methods.patch b/Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch similarity index 100% rename from Spigot-API-Patches/Add-item-slot-convenience-methods.patch rename to Unmapped-Spigot-API-Patches/0199-Add-item-slot-convenience-methods.patch diff --git a/Spigot-API-Patches/Add-Mob-Goal-API.patch b/Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Mob-Goal-API.patch rename to Unmapped-Spigot-API-Patches/0200-Add-Mob-Goal-API.patch diff --git a/Spigot-API-Patches/World-view-distance-api.patch b/Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch similarity index 100% rename from Spigot-API-Patches/World-view-distance-api.patch rename to Unmapped-Spigot-API-Patches/0201-World-view-distance-api.patch diff --git a/Spigot-API-Patches/Add-villager-reputation-API.patch b/Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch similarity index 100% rename from Spigot-API-Patches/Add-villager-reputation-API.patch rename to Unmapped-Spigot-API-Patches/0202-Add-villager-reputation-API.patch diff --git a/Spigot-API-Patches/Spawn-Reason-API.patch b/Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch similarity index 100% rename from Spigot-API-Patches/Spawn-Reason-API.patch rename to Unmapped-Spigot-API-Patches/0203-Spawn-Reason-API.patch diff --git a/Spigot-API-Patches/Potential-bed-API.patch b/Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch similarity index 100% rename from Spigot-API-Patches/Potential-bed-API.patch rename to Unmapped-Spigot-API-Patches/0204-Potential-bed-API.patch diff --git a/Spigot-API-Patches/Prioritise-own-classes-where-possible.patch b/Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch similarity index 100% rename from Spigot-API-Patches/Prioritise-own-classes-where-possible.patch rename to Unmapped-Spigot-API-Patches/0205-Prioritise-own-classes-where-possible.patch diff --git a/Spigot-API-Patches/Add-Raw-Byte-ItemStack-Serialization.patch b/Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from Spigot-API-Patches/Add-Raw-Byte-ItemStack-Serialization.patch rename to Unmapped-Spigot-API-Patches/0206-Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/Spigot-API-Patches/Provide-a-useful-PluginClassLoader-toString.patch b/Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch similarity index 100% rename from Spigot-API-Patches/Provide-a-useful-PluginClassLoader-toString.patch rename to Unmapped-Spigot-API-Patches/0207-Provide-a-useful-PluginClassLoader-toString.patch diff --git a/Spigot-API-Patches/Inventory-getHolder-method-without-block-snapshot.patch b/Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from Spigot-API-Patches/Inventory-getHolder-method-without-block-snapshot.patch rename to Unmapped-Spigot-API-Patches/0208-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/Spigot-API-Patches/Expose-Arrow-getItemStack.patch b/Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch similarity index 100% rename from Spigot-API-Patches/Expose-Arrow-getItemStack.patch rename to Unmapped-Spigot-API-Patches/0209-Expose-Arrow-getItemStack.patch diff --git a/Spigot-API-Patches/Add-and-implement-PlayerRecipeBookClickEvent.patch b/Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-and-implement-PlayerRecipeBookClickEvent.patch rename to Unmapped-Spigot-API-Patches/0210-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/Spigot-API-Patches/Support-components-in-ItemMeta.patch b/Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch similarity index 100% rename from Spigot-API-Patches/Support-components-in-ItemMeta.patch rename to Unmapped-Spigot-API-Patches/0211-Support-components-in-ItemMeta.patch diff --git a/Spigot-API-Patches/added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch similarity index 100% rename from Spigot-API-Patches/added-2-new-TargetReasons-for-1.16-mob-behavior.patch rename to Unmapped-Spigot-API-Patches/0212-added-2-new-TargetReasons-for-1.16-mob-behavior.patch diff --git a/Spigot-API-Patches/Add-entity-liquid-API.patch b/Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch similarity index 100% rename from Spigot-API-Patches/Add-entity-liquid-API.patch rename to Unmapped-Spigot-API-Patches/0213-Add-entity-liquid-API.patch diff --git a/Spigot-API-Patches/Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PrepareResultEvent-PrepareGrindstoneEvent.patch rename to Unmapped-Spigot-API-Patches/0214-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch diff --git a/Spigot-API-Patches/Allow-delegation-to-vanilla-chunk-gen.patch b/Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from Spigot-API-Patches/Allow-delegation-to-vanilla-chunk-gen.patch rename to Unmapped-Spigot-API-Patches/0215-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/Spigot-API-Patches/Support-hex-colors-in-getLastColors.patch b/Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch similarity index 100% rename from Spigot-API-Patches/Support-hex-colors-in-getLastColors.patch rename to Unmapped-Spigot-API-Patches/0216-Support-hex-colors-in-getLastColors.patch diff --git a/Spigot-API-Patches/Add-setMaxPlayers-API.patch b/Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch similarity index 100% rename from Spigot-API-Patches/Add-setMaxPlayers-API.patch rename to Unmapped-Spigot-API-Patches/0217-Add-setMaxPlayers-API.patch diff --git a/Spigot-API-Patches/Add-moon-phase-API.patch b/Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch similarity index 100% rename from Spigot-API-Patches/Add-moon-phase-API.patch rename to Unmapped-Spigot-API-Patches/0218-Add-moon-phase-API.patch diff --git a/Spigot-API-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch b/Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from Spigot-API-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch rename to Unmapped-Spigot-API-Patches/0219-Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/Spigot-API-Patches/Add-BellRingEvent.patch b/Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BellRingEvent.patch rename to Unmapped-Spigot-API-Patches/0220-Add-BellRingEvent.patch diff --git a/Spigot-API-Patches/0221-Brand-support.patch b/Unmapped-Spigot-API-Patches/0221-Brand-support.patch similarity index 100% rename from Spigot-API-Patches/0221-Brand-support.patch rename to Unmapped-Spigot-API-Patches/0221-Brand-support.patch diff --git a/Spigot-API-Patches/Add-more-Evoker-API.patch b/Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-Evoker-API.patch rename to Unmapped-Spigot-API-Patches/0222-Add-more-Evoker-API.patch diff --git a/Spigot-API-Patches/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch similarity index 100% rename from Spigot-API-Patches/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch rename to Unmapped-Spigot-API-Patches/0223-Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/Spigot-API-Patches/Create-HoverEvent-from-ItemStack-Entity.patch b/Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from Spigot-API-Patches/Create-HoverEvent-from-ItemStack-Entity.patch rename to Unmapped-Spigot-API-Patches/0224-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/Spigot-API-Patches/Add-additional-open-container-api-to-HumanEntity.patch b/Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from Spigot-API-Patches/Add-additional-open-container-api-to-HumanEntity.patch rename to Unmapped-Spigot-API-Patches/0225-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/Spigot-API-Patches/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 100% rename from Spigot-API-Patches/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to Unmapped-Spigot-API-Patches/0226-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/Spigot-API-Patches/Entity-isTicking.patch b/Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch similarity index 100% rename from Spigot-API-Patches/Entity-isTicking.patch rename to Unmapped-Spigot-API-Patches/0227-Entity-isTicking.patch diff --git a/Spigot-API-Patches/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch similarity index 100% rename from Spigot-API-Patches/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch rename to Unmapped-Spigot-API-Patches/0228-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch diff --git a/Spigot-API-Patches/Villager-resetOffers.patch b/Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch similarity index 100% rename from Spigot-API-Patches/Villager-resetOffers.patch rename to Unmapped-Spigot-API-Patches/0229-Villager-resetOffers.patch diff --git a/Spigot-API-Patches/Player-elytra-boost-API.patch b/Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch similarity index 100% rename from Spigot-API-Patches/Player-elytra-boost-API.patch rename to Unmapped-Spigot-API-Patches/0230-Player-elytra-boost-API.patch diff --git a/Spigot-API-Patches/Add-getOfflinePlayerIfCached-String.patch b/Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from Spigot-API-Patches/Add-getOfflinePlayerIfCached-String.patch rename to Unmapped-Spigot-API-Patches/0231-Add-getOfflinePlayerIfCached-String.patch diff --git a/Spigot-API-Patches/Add-ignore-discounts-API.patch b/Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch similarity index 100% rename from Spigot-API-Patches/Add-ignore-discounts-API.patch rename to Unmapped-Spigot-API-Patches/0232-Add-ignore-discounts-API.patch diff --git a/Spigot-API-Patches/Item-no-age-no-player-pickup.patch b/Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch similarity index 100% rename from Spigot-API-Patches/Item-no-age-no-player-pickup.patch rename to Unmapped-Spigot-API-Patches/0233-Item-no-age-no-player-pickup.patch diff --git a/Spigot-API-Patches/Beacon-API-custom-effect-ranges.patch b/Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from Spigot-API-Patches/Beacon-API-custom-effect-ranges.patch rename to Unmapped-Spigot-API-Patches/0234-Beacon-API-custom-effect-ranges.patch diff --git a/Spigot-API-Patches/Add-API-for-quit-reason.patch b/Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch similarity index 100% rename from Spigot-API-Patches/Add-API-for-quit-reason.patch rename to Unmapped-Spigot-API-Patches/0235-Add-API-for-quit-reason.patch diff --git a/Spigot-API-Patches/Add-Destroy-Speed-API.patch b/Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Destroy-Speed-API.patch rename to Unmapped-Spigot-API-Patches/0236-Add-Destroy-Speed-API.patch diff --git a/Spigot-API-Patches/Add-LivingEntity-clearActiveItem.patch b/Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from Spigot-API-Patches/Add-LivingEntity-clearActiveItem.patch rename to Unmapped-Spigot-API-Patches/0237-Add-LivingEntity-clearActiveItem.patch diff --git a/Spigot-API-Patches/Add-PlayerItemCooldownEvent.patch b/Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerItemCooldownEvent.patch rename to Unmapped-Spigot-API-Patches/0238-Add-PlayerItemCooldownEvent.patch diff --git a/Spigot-API-Patches/More-lightning-API.patch b/Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch similarity index 100% rename from Spigot-API-Patches/More-lightning-API.patch rename to Unmapped-Spigot-API-Patches/0239-More-lightning-API.patch diff --git a/Spigot-API-Patches/Add-PlayerShearBlockEvent.patch b/Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerShearBlockEvent.patch rename to Unmapped-Spigot-API-Patches/0240-Add-PlayerShearBlockEvent.patch diff --git a/Spigot-API-Patches/Enable-multi-release-plugin-jars.patch b/Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch similarity index 100% rename from Spigot-API-Patches/Enable-multi-release-plugin-jars.patch rename to Unmapped-Spigot-API-Patches/0241-Enable-multi-release-plugin-jars.patch diff --git a/Spigot-API-Patches/Player-Chunk-Load-Unload-Events.patch b/Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from Spigot-API-Patches/Player-Chunk-Load-Unload-Events.patch rename to Unmapped-Spigot-API-Patches/0242-Player-Chunk-Load-Unload-Events.patch diff --git a/Spigot-API-Patches/Expose-LivingEntity-hurt-direction.patch b/Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from Spigot-API-Patches/Expose-LivingEntity-hurt-direction.patch rename to Unmapped-Spigot-API-Patches/0243-Expose-LivingEntity-hurt-direction.patch diff --git a/Spigot-API-Patches/Added-PlayerTradeEvent.patch b/Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerTradeEvent.patch rename to Unmapped-Spigot-API-Patches/0244-Added-PlayerTradeEvent.patch diff --git a/Spigot-API-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from Spigot-API-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to Unmapped-Spigot-API-Patches/0245-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/Spigot-API-Patches/Add-TargetHitEvent-API.patch b/Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch similarity index 100% rename from Spigot-API-Patches/Add-TargetHitEvent-API.patch rename to Unmapped-Spigot-API-Patches/0246-Add-TargetHitEvent-API.patch diff --git a/Spigot-API-Patches/Additional-Block-Material-API-s.patch b/Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch similarity index 100% rename from Spigot-API-Patches/Additional-Block-Material-API-s.patch rename to Unmapped-Spigot-API-Patches/0247-Additional-Block-Material-API-s.patch diff --git a/Spigot-API-Patches/Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch similarity index 100% rename from Spigot-API-Patches/Add-API-to-get-Material-from-Boats-and-Minecarts.patch rename to Unmapped-Spigot-API-Patches/0248-Add-API-to-get-Material-from-Boats-and-Minecarts.patch diff --git a/Spigot-API-Patches/Add-PlayerFlowerPotManipulateEvent.patch b/Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerFlowerPotManipulateEvent.patch rename to Unmapped-Spigot-API-Patches/0249-Add-PlayerFlowerPotManipulateEvent.patch diff --git a/Spigot-API-Patches/Zombie-API-breaking-doors.patch b/Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch similarity index 100% rename from Spigot-API-Patches/Zombie-API-breaking-doors.patch rename to Unmapped-Spigot-API-Patches/0250-Zombie-API-breaking-doors.patch diff --git a/Spigot-API-Patches/Add-EntityLoadCrossbowEvent.patch b/Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityLoadCrossbowEvent.patch rename to Unmapped-Spigot-API-Patches/0251-Add-EntityLoadCrossbowEvent.patch diff --git a/Spigot-API-Patches/Added-WorldGameRuleChangeEvent.patch b/Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-WorldGameRuleChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0252-Added-WorldGameRuleChangeEvent.patch diff --git a/Spigot-API-Patches/Added-ServerResourcesReloadedEvent.patch b/Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-ServerResourcesReloadedEvent.patch rename to Unmapped-Spigot-API-Patches/0253-Added-ServerResourcesReloadedEvent.patch diff --git a/Spigot-API-Patches/Add-BlockFailedDispenseEvent.patch b/Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BlockFailedDispenseEvent.patch rename to Unmapped-Spigot-API-Patches/0254-Add-BlockFailedDispenseEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerLecternPageChangeEvent.patch b/Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerLecternPageChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0255-Added-PlayerLecternPageChangeEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerLoomPatternSelectEvent.patch b/Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerLoomPatternSelectEvent.patch rename to Unmapped-Spigot-API-Patches/0256-Added-PlayerLoomPatternSelectEvent.patch diff --git a/Spigot-API-Patches/Better-AnnotationTest-printout.patch b/Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch similarity index 100% rename from Spigot-API-Patches/Better-AnnotationTest-printout.patch rename to Unmapped-Spigot-API-Patches/0257-Better-AnnotationTest-printout.patch diff --git a/Spigot-API-Patches/Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch similarity index 100% rename from Spigot-API-Patches/Add-API-to-get-exact-interaction-point-in-PlayerInte.patch rename to Unmapped-Spigot-API-Patches/0258-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch diff --git a/Spigot-API-Patches/Add-sendOpLevel-API.patch b/Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch similarity index 100% rename from Spigot-API-Patches/Add-sendOpLevel-API.patch rename to Unmapped-Spigot-API-Patches/0259-Add-sendOpLevel-API.patch diff --git a/Spigot-API-Patches/Add-StructureLocateEvent.patch b/Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-StructureLocateEvent.patch rename to Unmapped-Spigot-API-Patches/0260-Add-StructureLocateEvent.patch diff --git a/Spigot-API-Patches/Return-chat-component-with-empty-text-instead-of-thr.patch b/Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from Spigot-API-Patches/Return-chat-component-with-empty-text-instead-of-thr.patch rename to Unmapped-Spigot-API-Patches/0261-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/Spigot-API-Patches/Add-BlockPreDispenseEvent.patch b/Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BlockPreDispenseEvent.patch rename to Unmapped-Spigot-API-Patches/0262-Add-BlockPreDispenseEvent.patch diff --git a/Spigot-API-Patches/Added-Vanilla-Entity-Tags.patch b/Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch similarity index 100% rename from Spigot-API-Patches/Added-Vanilla-Entity-Tags.patch rename to Unmapped-Spigot-API-Patches/0263-Added-Vanilla-Entity-Tags.patch diff --git a/Spigot-API-Patches/added-Wither-API.patch b/Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch similarity index 100% rename from Spigot-API-Patches/added-Wither-API.patch rename to Unmapped-Spigot-API-Patches/0264-added-Wither-API.patch diff --git a/Spigot-API-Patches/Added-PlayerChangeBeaconEffectEvent.patch b/Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerChangeBeaconEffectEvent.patch rename to Unmapped-Spigot-API-Patches/0265-Added-PlayerChangeBeaconEffectEvent.patch diff --git a/Spigot-API-Patches/Add-dropLeash-variable-to-EntityUnleashEvent.patch b/Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to Unmapped-Spigot-API-Patches/0266-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerStonecutterRecipeSelectEvent.patch b/Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerStonecutterRecipeSelectEvent.patch rename to Unmapped-Spigot-API-Patches/0267-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/Spigot-API-Patches/EntityMoveEvent.patch b/Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch similarity index 100% rename from Spigot-API-Patches/EntityMoveEvent.patch rename to Unmapped-Spigot-API-Patches/0268-EntityMoveEvent.patch diff --git a/Spigot-API-Patches/add-DragonEggFormEvent.patch b/Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch similarity index 100% rename from Spigot-API-Patches/add-DragonEggFormEvent.patch rename to Unmapped-Spigot-API-Patches/0269-add-DragonEggFormEvent.patch diff --git a/Spigot-API-Patches/Allow-adding-items-to-BlockDropItemEvent.patch b/Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from Spigot-API-Patches/Allow-adding-items-to-BlockDropItemEvent.patch rename to Unmapped-Spigot-API-Patches/0270-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/Spigot-API-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch b/Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from Spigot-API-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to Unmapped-Spigot-API-Patches/0271-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/Spigot-API-Patches/living-entity-allow-attribute-registration.patch b/Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch similarity index 100% rename from Spigot-API-Patches/living-entity-allow-attribute-registration.patch rename to Unmapped-Spigot-API-Patches/0272-living-entity-allow-attribute-registration.patch diff --git a/Spigot-API-Patches/Add-missing-effects.patch b/Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch similarity index 100% rename from Spigot-API-Patches/Add-missing-effects.patch rename to Unmapped-Spigot-API-Patches/0273-Add-missing-effects.patch diff --git a/Spigot-API-Patches/Expose-Tracked-Players.patch b/Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch similarity index 100% rename from Spigot-API-Patches/Expose-Tracked-Players.patch rename to Unmapped-Spigot-API-Patches/0274-Expose-Tracked-Players.patch diff --git a/Spigot-API-Patches/Cache-the-result-of-Material-isBlock.patch b/Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch similarity index 100% rename from Spigot-API-Patches/Cache-the-result-of-Material-isBlock.patch rename to Unmapped-Spigot-API-Patches/0275-Cache-the-result-of-Material-isBlock.patch diff --git a/Spigot-API-Patches/Add-worldborder-events.patch b/Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch similarity index 100% rename from Spigot-API-Patches/Add-worldborder-events.patch rename to Unmapped-Spigot-API-Patches/0276-Add-worldborder-events.patch diff --git a/Spigot-API-Patches/added-PlayerNameEntityEvent.patch b/Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/added-PlayerNameEntityEvent.patch rename to Unmapped-Spigot-API-Patches/0277-added-PlayerNameEntityEvent.patch diff --git a/Spigot-API-Patches/Add-recipe-to-cook-events.patch b/Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch similarity index 100% rename from Spigot-API-Patches/Add-recipe-to-cook-events.patch rename to Unmapped-Spigot-API-Patches/0278-Add-recipe-to-cook-events.patch diff --git a/Spigot-API-Patches/Add-Block-isValidTool.patch b/Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch similarity index 100% rename from Spigot-API-Patches/Add-Block-isValidTool.patch rename to Unmapped-Spigot-API-Patches/0279-Add-Block-isValidTool.patch diff --git a/Spigot-API-Patches/Implement-Keyed-on-World.patch b/Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch similarity index 100% rename from Spigot-API-Patches/Implement-Keyed-on-World.patch rename to Unmapped-Spigot-API-Patches/0280-Implement-Keyed-on-World.patch diff --git a/Spigot-API-Patches/fix-Inventory-getContents-null-annotations.patch b/Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch similarity index 100% rename from Spigot-API-Patches/fix-Inventory-getContents-null-annotations.patch rename to Unmapped-Spigot-API-Patches/0281-fix-Inventory-getContents-null-annotations.patch diff --git a/Spigot-API-Patches/Item-Rarity-API.patch b/Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch similarity index 100% rename from Spigot-API-Patches/Item-Rarity-API.patch rename to Unmapped-Spigot-API-Patches/0282-Item-Rarity-API.patch diff --git a/Spigot-API-Patches/Expose-protocol-version.patch b/Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch similarity index 100% rename from Spigot-API-Patches/Expose-protocol-version.patch rename to Unmapped-Spigot-API-Patches/0283-Expose-protocol-version.patch diff --git a/Spigot-API-Patches/add-isDeeplySleeping-to-HumanEntity.patch b/Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from Spigot-API-Patches/add-isDeeplySleeping-to-HumanEntity.patch rename to Unmapped-Spigot-API-Patches/0284-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/Spigot-API-Patches/add-consumeFuel-to-FurnaceBurnEvent.patch b/Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from Spigot-API-Patches/add-consumeFuel-to-FurnaceBurnEvent.patch rename to Unmapped-Spigot-API-Patches/0285-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/Spigot-API-Patches/add-get-set-drop-chance-to-EntityEquipment.patch b/Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from Spigot-API-Patches/add-get-set-drop-chance-to-EntityEquipment.patch rename to Unmapped-Spigot-API-Patches/0286-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/Spigot-API-Patches/Added-PlayerDeepSleepEvent.patch b/Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerDeepSleepEvent.patch rename to Unmapped-Spigot-API-Patches/0287-Added-PlayerDeepSleepEvent.patch diff --git a/Spigot-API-Patches/More-World-API.patch b/Unmapped-Spigot-API-Patches/0288-More-World-API.patch similarity index 100% rename from Spigot-API-Patches/More-World-API.patch rename to Unmapped-Spigot-API-Patches/0288-More-World-API.patch diff --git a/Spigot-API-Patches/Added-PlayerBedFailEnterEvent.patch b/Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerBedFailEnterEvent.patch rename to Unmapped-Spigot-API-Patches/0289-Added-PlayerBedFailEnterEvent.patch diff --git a/Spigot-API-Patches/Introduce-beacon-activation-deactivation-events.patch b/Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from Spigot-API-Patches/Introduce-beacon-activation-deactivation-events.patch rename to Unmapped-Spigot-API-Patches/0290-Introduce-beacon-activation-deactivation-events.patch diff --git a/Spigot-API-Patches/PlayerMoveEvent-Improvements.patch b/Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch similarity index 100% rename from Spigot-API-Patches/PlayerMoveEvent-Improvements.patch rename to Unmapped-Spigot-API-Patches/0291-PlayerMoveEvent-Improvements.patch diff --git a/Spigot-API-Patches/add-RespawnFlags-to-PlayerRespawnEvent.patch b/Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from Spigot-API-Patches/add-RespawnFlags-to-PlayerRespawnEvent.patch rename to Unmapped-Spigot-API-Patches/0292-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/Spigot-API-Patches/Add-more-WanderingTrader-API.patch b/Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-WanderingTrader-API.patch rename to Unmapped-Spigot-API-Patches/0293-Add-more-WanderingTrader-API.patch diff --git a/Spigot-API-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 100% rename from Spigot-API-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to Unmapped-Spigot-API-Patches/0294-Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/Spigot-API-Patches/Add-EntityBlockStorage-clearEntities.patch b/Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityBlockStorage-clearEntities.patch rename to Unmapped-Spigot-API-Patches/0295-Add-EntityBlockStorage-clearEntities.patch diff --git a/Spigot-API-Patches/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to Unmapped-Spigot-API-Patches/0296-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/Spigot-API-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to Unmapped-Spigot-API-Patches/0297-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/Spigot-API-Patches/Inventory-close.patch b/Unmapped-Spigot-API-Patches/0298-Inventory-close.patch similarity index 100% rename from Spigot-API-Patches/Inventory-close.patch rename to Unmapped-Spigot-API-Patches/0298-Inventory-close.patch diff --git a/Spigot-API-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from Spigot-API-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to Unmapped-Spigot-API-Patches/0299-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/Spigot-API-Patches/Add-basic-Datapack-API.patch b/Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch similarity index 100% rename from Spigot-API-Patches/Add-basic-Datapack-API.patch rename to Unmapped-Spigot-API-Patches/0300-Add-basic-Datapack-API.patch diff --git a/Spigot-API-Patches/additions-to-PlayerGameModeChangeEvent.patch b/Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/additions-to-PlayerGameModeChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0301-additions-to-PlayerGameModeChangeEvent.patch diff --git a/Spigot-API-Patches/ItemStack-repair-check-API.patch b/Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch similarity index 100% rename from Spigot-API-Patches/ItemStack-repair-check-API.patch rename to Unmapped-Spigot-API-Patches/0302-ItemStack-repair-check-API.patch diff --git a/Spigot-API-Patches/More-Enchantment-API.patch b/Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch similarity index 100% rename from Spigot-API-Patches/More-Enchantment-API.patch rename to Unmapped-Spigot-API-Patches/0303-More-Enchantment-API.patch diff --git a/Spigot-API-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch b/Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 100% rename from Spigot-API-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to Unmapped-Spigot-API-Patches/0304-Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/Spigot-API-Patches/List-all-missing-hard-depends-not-just-first.patch b/Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch similarity index 100% rename from Spigot-API-Patches/List-all-missing-hard-depends-not-just-first.patch rename to Unmapped-Spigot-API-Patches/0305-List-all-missing-hard-depends-not-just-first.patch diff --git a/Spigot-API-Patches/Add-Mob-lookAt-API.patch b/Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Mob-lookAt-API.patch rename to Unmapped-Spigot-API-Patches/0306-Add-Mob-lookAt-API.patch diff --git a/Spigot-API-Patches/ItemStack-editMeta.patch b/Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch similarity index 100% rename from Spigot-API-Patches/ItemStack-editMeta.patch rename to Unmapped-Spigot-API-Patches/0307-ItemStack-editMeta.patch diff --git a/Spigot-API-Patches/Add-EntityInsideBlockEvent.patch b/Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityInsideBlockEvent.patch rename to Unmapped-Spigot-API-Patches/0308-Add-EntityInsideBlockEvent.patch diff --git a/Spigot-API-Patches/Attributes-API-for-item-defaults.patch b/Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch similarity index 100% rename from Spigot-API-Patches/Attributes-API-for-item-defaults.patch rename to Unmapped-Spigot-API-Patches/0309-Attributes-API-for-item-defaults.patch diff --git a/Spigot-API-Patches/Add-cause-to-Weather-ThunderChangeEvents.patch b/Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from Spigot-API-Patches/Add-cause-to-Weather-ThunderChangeEvents.patch rename to Unmapped-Spigot-API-Patches/0310-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/Spigot-API-Patches/More-Lidded-Block-API.patch b/Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch similarity index 100% rename from Spigot-API-Patches/More-Lidded-Block-API.patch rename to Unmapped-Spigot-API-Patches/0311-More-Lidded-Block-API.patch diff --git a/Spigot-API-Patches/Add-PlayerKickEvent-causes.patch b/Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerKickEvent-causes.patch rename to Unmapped-Spigot-API-Patches/0312-Add-PlayerKickEvent-causes.patch diff --git a/Spigot-API-Patches/Add-PufferFishStateChangeEvent.patch b/Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PufferFishStateChangeEvent.patch rename to Unmapped-Spigot-API-Patches/0313-Add-PufferFishStateChangeEvent.patch diff --git a/Spigot-API-Patches/Add-BellRevealRaiderEvent.patch b/Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BellRevealRaiderEvent.patch rename to Unmapped-Spigot-API-Patches/0314-Add-BellRevealRaiderEvent.patch diff --git a/Spigot-API-Patches/Add-ElderGuardianAppearanceEvent.patch b/Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-ElderGuardianAppearanceEvent.patch rename to Unmapped-Spigot-API-Patches/0315-Add-ElderGuardianAppearanceEvent.patch diff --git a/Spigot-API-Patches/Add-more-line-of-sight-methods.patch b/Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch similarity index 100% rename from Spigot-API-Patches/Add-more-line-of-sight-methods.patch rename to Unmapped-Spigot-API-Patches/0316-Add-more-line-of-sight-methods.patch