diff --git a/.editorconfig b/.editorconfig index 210d3ca851..aa4d12f5a8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,12 @@ -[*.java] +[*] charset=utf-8 end_of_line=lf insert_final_newline=true indent_style=space indent_size=4 + +[*.tiny] +indent_style=tab + +[*.bat] +end_of_line=crlf diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..2fb638f44b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto + +*.sh text eol=lf +gradlew text eol=lf +*.bat text eol=crlf + +*.jar binary diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a94f849ec9..63f28ac60f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [16, 8] + java: [16] fail-fast: true steps: - uses: actions/checkout@v2 @@ -22,18 +22,19 @@ jobs: with: java-version: ${{ matrix.java }} distribution: 'adopt' - - name: Cache maven + - name: Cache gradle uses: actions/cache@v2 with: path: | - ~/.m2/repository/ - work/Minecraft - key: ${{ runner.os }}-paper-2-${{ hashFiles('**/pom.xml') }} + ~/.gradle/caches + ~/.gradle/jdks + ~/.gradle/native + ~/.gradle/wrapper + key: ${{ runner.os }}-paper-2-${{ hashFiles('**/*.gradle*', 'gradle/**', 'gradle.properties') }} restore-keys: ${{ runner.os }}-paper-2 - name: Patch and build run: | git config --global user.email "no-reply@github.com" git config --global user.name "Github Actions" - ./paper build - - name: Build javadocs - run: mvn -pl Paper-API,Paper-MojangAPI -am javadoc:javadoc + ./gradlew applyPatches --stacktrace + ./gradlew build --stacktrace diff --git a/.gitignore b/.gitignore index b1e563f223..5c7e1f2db7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.gradle/ +build/ + # Eclipse stuff .classpath .project @@ -63,3 +66,5 @@ Paperclip.jar paperclip.jar paperclip-*.jar paperclip.properties + +!gradle/wrapper/gradle-wrapper.jar diff --git a/.gitmodules b/.gitmodules index 758536e061..7280fb743d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,3 @@ [submodule "work/Spigot"] path = work/Spigot url = https://hub.spigotmc.org/stash/scm/spigot/spigot.git -[submodule "work/Paperclip"] - path = work/Paperclip - url = https://github.com/PaperMC/Paperclip.git diff --git a/Paper-MojangAPI/build.gradle.kts b/Paper-MojangAPI/build.gradle.kts new file mode 100644 index 0000000000..f7bf0ff771 --- /dev/null +++ b/Paper-MojangAPI/build.gradle.kts @@ -0,0 +1,35 @@ +import java.util.Locale + +plugins { + `java-library` + `maven-publish` +} + +java { + withSourcesJar() + withJavadocJar() +} + +repositories { + mavenCentral() + maven("https://libraries.minecraft.net") +} + +dependencies { + implementation(project(":Paper-API")) + api("com.mojang:brigadier:1.0.18") + + compileOnly("it.unimi.dsi:fastutil:8.2.2") + compileOnly("org.jetbrains:annotations:18.0.0") + + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") + testImplementation("org.ow2.asm:asm-tree:7.3.1") +} + +configure { + publications.create("maven") { + artifactId = project.name.toLowerCase(Locale.ENGLISH) + from(components["java"]) + } +} diff --git a/Paper-MojangAPI/pom.xml b/Paper-MojangAPI/pom.xml deleted file mode 100644 index 7712a8723c..0000000000 --- a/Paper-MojangAPI/pom.xml +++ /dev/null @@ -1,204 +0,0 @@ - - - 4.0.0 - - com.destroystokyo.paper - paper-parent - dev-SNAPSHOT - - - com.destroystokyo.paper - paper-mojangapi - 1.16.5-R0.1-SNAPSHOT - jar - - Paper-MojangAPI - https://github.com/PaperMC/Paper - API additions that utilize Mojang Specific API's - - - - 1.8 - 1.8 - UTF-8 - - - - - spigotmc-public - https://hub.spigotmc.org/nexus/content/groups/public/ - - - sonatype - https://oss.sonatype.org/content/groups/public/ - - - minecraft-libraries - Minecraft Libraries - https://libraries.minecraft.net - - - - - - spigotmc-public - https://hub.spigotmc.org/nexus/content/groups/public/ - - - - - - com.destroystokyo.paper - paper-api - ${project.version} - provided - - - - com.mojang - brigadier - 1.0.17 - compile - - - - it.unimi.dsi - fastutil - 8.2.2 - provided - - - - org.jetbrains - annotations - 18.0.0 - provided - - - - junit - junit - 4.13.1 - test - - - org.hamcrest - hamcrest-library - 1.3 - test - - - org.ow2.asm - asm-tree - 7.3.1 - test - - - - - clean install - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - - - org.codehaus.plexus - plexus-compiler-eclipse - 2.8.5-spigotmc - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - org.bukkit - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - package - - shade - - - - - ${project.build.directory}/dependency-reduced-pom.xml - - true - - - - - - - - development - - false - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.1.0 - - - process-classes - - check - - - - - checkstyle.xml - true - - - - com.puppycrawl.tools - checkstyle - 8.29 - - - - - org.codehaus.mojo - animal-sniffer-maven-plugin - 1.18 - - - process-classes - - check - - - - - - org.codehaus.mojo.signature - java18 - 1.0 - - - - - - - - diff --git a/Spigot-API-Patches/Add-FastUtil-to-Bukkit.patch b/Spigot-API-Patches/Add-FastUtil-to-Bukkit.patch deleted file mode 100644 index 4e904473c6..0000000000 --- a/Spigot-API-Patches/Add-FastUtil-to-Bukkit.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 1 Apr 2016 00:02:47 -0400 -Subject: [PATCH] Add FastUtil to Bukkit - -Doesn't expose to plugins, just allows Paper-API to use it for optimization - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - - - -+ -+ it.unimi.dsi -+ fastutil -+ 8.2.2 -+ provided -+ - - commons-lang - commons-lang diff --git a/Spigot-API-Patches/Better-AnnotationTest-printout.patch b/Spigot-API-Patches/Better-AnnotationTest-printout.patch deleted file mode 100644 index 6fecb54dfe..0000000000 --- a/Spigot-API-Patches/Better-AnnotationTest-printout.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 3 Dec 2020 14:04:57 -0800 -Subject: [PATCH] Better AnnotationTest printout - - -diff --git a/pom.xml b/pom.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - true - - -+ -+ org.apache.maven.plugins -+ maven-surefire-plugin -+ 2.22.2 -+ -+ -+ -+ listener -+ io.papermc.paper.JunitEventListener -+ -+ -+ -+ - - org.apache.maven.plugins - maven-javadoc-plugin -diff --git a/src/test/java/io/papermc/paper/JunitEventListener.java b/src/test/java/io/papermc/paper/JunitEventListener.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/test/java/io/papermc/paper/JunitEventListener.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper; -+ -+import org.junit.runner.notification.RunListener; -+ -+public class JunitEventListener extends RunListener { -+} -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -0,0 +0,0 @@ public class AnnotationTest { - - Collections.sort(errors); - -- System.out.println(errors.size() + " missing annotation(s):"); -+ StringBuilder builder = new StringBuilder() -+ .append("There ") -+ .append(errors.size() != 1 ? "are " : "is ") -+ .append(errors.size()) -+ .append(" missing annotation") -+ .append(errors.size() != 1 ? "s:\n" : ":\n"); -+ - for (String message : errors) { -- System.out.print("\t"); -- System.out.println(message); -+ builder.append("\t").append(message).append("\n"); - } - -- Assert.fail("There " + errors.size() + " are missing annotation(s)"); -+ Assert.fail(builder.toString()); - } - - private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { diff --git a/Spigot-API-Patches/POM-changes.patch b/Spigot-API-Patches/POM-changes.patch deleted file mode 100644 index 449fe6efb9..0000000000 --- a/Spigot-API-Patches/POM-changes.patch +++ /dev/null @@ -1,106 +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 00:16:08 +0100 -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 -+ -+ com.destroystokyo.paper -+ paper-parent -+ dev-SNAPSHOT -+ - -- org.spigotmc -- spigot-api -+ com.destroystokyo.paper -+ paper-api - 1.16.5-R0.1-SNAPSHOT - jar - -- Spigot-API -- https://www.spigotmc.org/ -+ Paper-API -+ https://github.com/PaperMC/Paper - An enhanced plugin API for Minecraft servers. - - -- true -+ - 1.8 - 1.8 - UTF-8 - - -- -+ - -- spigotmc-releases -- https://hub.spigotmc.org/nexus/content/repositories/releases/ -+ sonatype -+ https://oss.sonatype.org/content/groups/public/ - -- -- spigotmc-snapshots -- https://hub.spigotmc.org/nexus/content/repositories/snapshots/ -- -- -+ - - - -@@ -0,0 +0,0 @@ - 2.6 - compile - -+ -+ -+ com.google.code.findbugs -+ jsr305 -+ 1.3.9 -+ compile -+ -+ -+ -+ com.googlecode.json-simple -+ json-simple -+ 1.1.1 -+ compile -+ - - - com.google.guava -@@ -0,0 +0,0 @@ - - - -+ clean install - - - net.md-5 -@@ -0,0 +0,0 @@ - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 -- -- -- eclipse -- - - - org.codehaus.plexus -@@ -0,0 +0,0 @@ - - - -+ ${project.build.directory}/dependency-reduced-pom.xml - - true - 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/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/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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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/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-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-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-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-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/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/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/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-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/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/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/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-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-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/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/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/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/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-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-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-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-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-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/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/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-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-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/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-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-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-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-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-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-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-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-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/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/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/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-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-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-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/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-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-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/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/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-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-Concurrency-issue-in-WeightedList.patch b/Spigot-Server-Patches/Fix-Concurrency-issue-in-WeightedList.patch deleted file mode 100644 index e977fb8c15..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/world/entity/ai/behavior/WeightedList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/WeightedList.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-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-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-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: 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-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-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-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-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-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-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-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-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-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-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/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/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-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/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/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-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-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-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-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-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-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/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-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-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: 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/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/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/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/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-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/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-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-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/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-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-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/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/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: 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-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/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-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-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-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-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-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-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-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.isLoaded-BlockPosition-Z.patch b/Spigot-Server-Patches/Optimize-World.isLoaded-BlockPosition-Z.patch deleted file mode 100644 index 3f21531959..0000000000 --- a/Spigot-Server-Patches/Optimize-World.isLoaded-BlockPosition-Z.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -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-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/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-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/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/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-affects-spawning-API.patch b/Spigot-Server-Patches/Player-affects-spawning-API.patch deleted file mode 100644 index 8efae3a5da..0000000000 --- a/Spigot-Server-Patches/Player-affects-spawning-API.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jedediah Smith -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.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/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/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/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/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-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-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/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/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/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-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/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-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/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/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/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/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/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-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/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/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-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-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/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/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/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 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/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/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/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-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/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: 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/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/offset-item-frame-ticking.patch b/Spigot-Server-Patches/offset-item-frame-ticking.patch deleted file mode 100644 index 1c2f30dfd6..0000000000 --- a/Spigot-Server-Patches/offset-item-frame-ticking.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: kickash32 -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/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/UPDATE_NOTES.md b/UPDATE_NOTES.md deleted file mode 100644 index 23c915e195..0000000000 --- a/UPDATE_NOTES.md +++ /dev/null @@ -1,14 +0,0 @@ -# Shit to check - -* Mini: "Optimize World Server Map": Figure out how to fill PaperWorldMap, it needs a dim key which doesnt exist anymore? -* Mini: "MC-50319": fix if still works -* Make sure the flat bedrock setting doesn't do anything stupid -* Check DataBits foreach -* lighting is bork (load chunk, fly away, come back, everything or parts are black) -* chunk generation seems slow with a lot of it happening -* Fix IDE Debug JVM Flag for new versions of minecraft - -* Check if `PlayerEditBookEvent`: https://github.com/PaperMC/Paper/pull/1751 -The PlayerEditBookEvent is straight up not called anymore. -The method to call it must now be `PlayerConnection#a(List, int)` (CB bug). -The item is presumably edited with the new page contents before it ever reaches this method? \ No newline at end of file diff --git a/build-data/additional-spigot-member-mappings.csrg b/build-data/additional-spigot-member-mappings.csrg new file mode 100644 index 0000000000..0df7ebc7e2 --- /dev/null +++ b/build-data/additional-spigot-member-mappings.csrg @@ -0,0 +1,6 @@ +# CraftBukkit maps all of (mojmap names): +# Merchant.getLevel() +# Entity.getCommandSenderWorld() +# to getWorld(), which confuses our ability to map this method properly. This patch disambiguates it +net/minecraft/world/item/trading/IMerchant fD ()Lnet/minecraft/world/level/World; getLevel +net/minecraft/world/entity/npc/EntityVillagerAbstract fD ()Lnet/minecraft/world/level/World; getLevel diff --git a/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch b/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch new file mode 100644 index 0000000000..4a7007ceb4 --- /dev/null +++ b/build-data/craftbukkit-patch-patches/BehaviorWorkComposter.patch.patch @@ -0,0 +1,17 @@ +--- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.patch +@@ -0,0 +0,0 @@ + --- a/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java + +++ b/net/minecraft/world/entity/ai/behavior/BehaviorWorkComposter.java +-@@ -0,0 +0,0 @@ +- public BehaviorWorkComposter() {} +- +- @Override +-- protected void a(WorldServer worldserver, EntityVillager entityvillager) { +-+ protected void doWork(WorldServer worldserver, EntityVillager entityvillager) { // PAIL +- Optional optional = entityvillager.getBehaviorController().getMemory(MemoryModuleType.JOB_SITE); +- +- if (optional.isPresent()) { + @@ -0,0 +0,0 @@ + BlockPosition blockposition = globalpos.getBlockPosition(); + diff --git a/build-data/library-imports.txt b/build-data/library-imports.txt new file mode 100644 index 0000000000..e6e68fdb6f --- /dev/null +++ b/build-data/library-imports.txt @@ -0,0 +1,7 @@ +# You can use this file to import files from minecraft libraries into the project +# format: +# +# both fully qualified and a file based syntax are accepted for : +# authlib com/mojang/authlib/yggdrasil/YggdrasilGameProfileRepository.java +# datafixerupper com.mojang.datafixers.DataFixerBuilder +# datafixerupper com/mojang/datafixers/util/Either.java diff --git a/build-data/mappings-patch.tiny b/build-data/mappings-patch.tiny new file mode 100644 index 0000000000..eb16ed426e --- /dev/null +++ b/build-data/mappings-patch.tiny @@ -0,0 +1,49 @@ +tiny 2 0 spigot mojang+yarn + +# Originally DistanceManager, which also implements DistanceManager, so clashes since the implemented class +# is imported and not fully qualified. Easiest fix is to just change the name +c net/minecraft/server/level/PlayerChunkMap$a net/minecraft/server/level/ChunkMap$ChunkDistanceManager + +# CraftBukkit adds the getServer() method, clashes with a Mojang method +c net/minecraft/world/level/World net/minecraft/world/level/Level + m ()Lorg/bukkit/craftbukkit/CraftServer; getServer getCraftServer + +# CraftBukkit adds the server field, clashes with a Mojang field +c net/minecraft/server/network/PlayerConnection net/minecraft/server/network/ServerGamePacketListenerImpl + m ()Lorg/bukkit/craftbukkit/entity/CraftPlayer; getPlayer getCraftPlayer + +# CraftBukkit adds the getType() method, clashes with a Mojang method +c net/minecraft/world/entity/EntityAreaEffectCloud net/minecraft/world/entity/AreaEffectCloud + m ()Ljava/lang/String; getType getPotionType + +# CraftBukkit adds the getType() method, clashes with a Mojang method +c net/minecraft/world/entity/projectile/EntityTippedArrow net/minecraft/world/entity/projectile/Arrow + m ()Ljava/lang/String; getType getPotionType + +# CraftBukkit adds a new `a` method which allows passing the Entity parameter +# It uses `a` to match the original method (with just 1 param), so this patch makes them match +c net/minecraft/server/level/WorldServer net/minecraft/server/level/ServerLevel + m (Lnet/minecraft/server/level/WorldServer;Lnet/minecraft/world/entity/Entity;)V a makeObsidianPlatform + +# missed mapping? +c net/minecraft/world/level/block/MultifaceBlock net/minecraft/world/level/block/MultifaceBlock + m (Lnet/minecraft/world/level/block/state/IBlockData;Lnet/minecraft/world/level/IBlockAccess;Lnet/minecraft/core/BlockPosition;Lnet/minecraft/core/EnumDirection;)Lnet/minecraft/world/level/block/state/IBlockData; c getStateForPlacement + +# another missed one +c net/minecraft/server/players/UserCache net/minecraft/server/players/GameProfileCache + m (Ljava/lang/String;)Lcom/mojang/authlib/GameProfile; getProfile get + p 0 name + +# change dimension in ServerPlayer +c net/minecraft/server/level/EntityPlayer net/minecraft/server/level/ServerPlayer + m (Lnet/minecraft/server/level/WorldServer;Lorg/bukkit/event/player/PlayerTeleportEvent$TeleportCause;)Lnet/minecraft/world/entity/Entity; b changeDimension + +# We add the getLevel method back to Hopper since mojang removed it - we need the method for hooper optimization +# We add the method with this name to match the mojmap method of the same name in BlockEntity +# Since we add the method we need to add the mapping for it so reobf works as expected +c net/minecraft/world/level/block/entity/IHopper net/minecraft/world/level/block/entity/Hopper + m ()Lnet/minecraft/world/level/World; getWorld getLevel + +# Teleport method in ServerGamePacketListenerImpl +c net/minecraft/server/network/PlayerConnection net/minecraft/server/network/ServerGamePacketListenerImpl + m (DDDFFLorg/bukkit/event/player/PlayerTeleportEvent$TeleportCause;)V a teleport diff --git a/build-data/mcdev-imports.txt b/build-data/mcdev-imports.txt new file mode 100644 index 0000000000..6f0ec2fe82 --- /dev/null +++ b/build-data/mcdev-imports.txt @@ -0,0 +1,4 @@ +# You can use this file to import files from vanilla into the project +# both fully qualified and a file based syntax are accepted here: +# net.minecraft.world.level.entity.LevelEntityGetterAdapter +# net/minecraft/world/level/entity/LevelEntityGetter.java diff --git a/build-data/paper.at b/build-data/paper.at new file mode 100644 index 0000000000..16a94f7cf6 --- /dev/null +++ b/build-data/paper.at @@ -0,0 +1,217 @@ +# You can use this file to change the access modifiers on a member +# This line would make the field rollAmount public in Bee +#public net.minecraft.world.entity.animal.Bee rollAmount +# This line would make the field public and remove the final modifier +#public-f net.minecraft.network.protocol.game.ClientboundChatPacket sender +# Leave out the member and it will apply to the class itself +# More info, see here https://mcforge.readthedocs.io/en/latest/advanced/accesstransformers/#access-modifiers + +# Remap/Decompile fix (unclear why this is happening) +public net.minecraft.server.MinecraftServer doRunTask(Lnet/minecraft/server/TickTask;)V + +# Paper config files +public org.spigotmc.SpigotWorldConfig getBoolean(Ljava/lang/String;Z)Z +public org.spigotmc.SpigotWorldConfig getDouble(Ljava/lang/String;)D +public org.spigotmc.SpigotWorldConfig getDouble(Ljava/lang/String;D)D +public org.spigotmc.SpigotWorldConfig getInt(Ljava/lang/String;)I +public org.spigotmc.SpigotWorldConfig getInt(Ljava/lang/String;I)I +public org.spigotmc.SpigotWorldConfig getList(Ljava/lang/String;Ljava/lang/Object;)Ljava/util/List; +public org.spigotmc.SpigotWorldConfig getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + +# MC Utils +public net.minecraft.core.Vec3i setX(I)Lnet/minecraft/core/Vec3i; +public net.minecraft.core.Vec3i setY(I)Lnet/minecraft/core/Vec3i; +public net.minecraft.core.Vec3i setZ(I)Lnet/minecraft/core/Vec3i; +public net.minecraft.server.level.ServerChunkCache mainThread +public net.minecraft.server.level.ServerLevel chunkSource +public org.bukkit.craftbukkit.inventory.CraftItemStack handle + +# Add PlayerInitialSpawnEvent +public net.minecraft.world.entity.Entity setRot(FF)V + +# Add PlayerUseUnknownEntityEvent +public net.minecraft.network.protocol.game.ServerboundInteractPacket$ActionType + +# Configurable RCON IP address +public net.minecraft.server.dedicated.Settings getStringRaw(Ljava/lang/String;)Ljava/lang/String; + +# LootTable API +public org.bukkit.craftbukkit.block.CraftBlockEntityState getTileEntity()Lnet/minecraft/world/level/block/entity/BlockEntity; +public org.bukkit.craftbukkit.block.CraftLootable setLootTable(Lorg/bukkit/loot/LootTable;J)V +public org.bukkit.craftbukkit.entity.CraftMinecartContainer setLootTable(Lorg/bukkit/loot/LootTable;J)V + +# Firework API +public net.minecraft.world.entity.projectile.FireworkRocketEntity attachedToEntity + +# Add option to make parrots stay +public net.minecraft.world.entity.player.Player removeEntitiesOnShoulder()V + +# LivingEntity setkiller +public net.minecraft.world.entity.LivingEntity lastHurtByPlayerTime + +# SkeletonHorse Addittions +public net.minecraft.world.entity.animal.horse.SkeletonHorse trapTime + +# Fix client rendering skulls +public net.minecraft.world.item.ItemStack tag + +# Async chunk io +public net.minecraft.server.level.ChunkMap structureManager +public net.minecraft.server.level.ChunkMap overworldDataStorage +public net.minecraft.server.level.ChunkMap getUpdatingChunkIfPresent(J)Lnet/minecraft/server/level/ChunkHolder; +public net.minecraft.server.level.ChunkMap getVisibleChunkIfPresent(J)Lnet/minecraft/server/level/ChunkHolder; +public net.minecraft.server.level.ServerChunkCache mainThreadProcessor +public-f net.minecraft.world.level.chunk.storage.RegionFileStorage +public net.minecraft.world.level.chunk.storage.RegionFileStorage getFile(Lnet/minecraft/world/level/ChunkPos;Z)Lnet/minecraft/world/level/chunk/storage/RegionFile; +public net.minecraft.world.level.chunk.storage.SectionStorage dirty +public net.minecraft.util.thread.BlockableEventLoop runAllTasks()V + +# Improve death events +public net.minecraft.world.entity.LivingEntity getDeathSound()Lnet/minecraft/sounds/SoundEvent; +public net.minecraft.world.entity.LivingEntity getSoundVolume()F +public net.minecraft.world.entity.ambient.Bat getSoundVolume()F +public net.minecraft.world.entity.monster.Ghast getSoundVolume()F +public net.minecraft.world.entity.monster.Phantom getSoundVolume()F +public net.minecraft.world.entity.animal.Squid getSoundVolume()F +public net.minecraft.world.entity.animal.Wolf getSoundVolume()F + +# Add sun related api +public net.minecraft.world.entity.Mob isSunBurnTick()Z + +# Turtle API +public net.minecraft.world.entity.animal.Turtle getHomePos()Lnet/minecraft/core/BlockPos; +public net.minecraft.world.entity.animal.Turtle setHasEgg(Z)V +public net.minecraft.world.entity.animal.Turtle isGoingHome()Z +public net.minecraft.world.entity.animal.Turtle setGoingHome(Z)V +public net.minecraft.world.entity.animal.Turtle isTravelling()Z +public net.minecraft.world.entity.animal.Turtle setTravelling(Z)V + +# Call player spectator target event +public net.minecraft.server.network.ServerGamePacketListenerImpl a(Ljava/util/List;Ljava/util/function/UnaryOperator;Lnet/minecraft/world/item/ItemStack;ILnet/minecraft/world/item/ItemStack;)V # todo fix this mapping + +# Improve Server THread Pool +public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V + +# Add more zombie API +public net.minecraft.world.entity.monster.Zombie isSunSensitive()Z + +# Add PlayerConnectionCloseEvent +public net.minecraft.server.network.ServerLoginPacketListenerImpl$State +public net.minecraft.server.network.ServerLoginPacketListenerImpl state + +# Entity Activation Range 2.0 +public net.minecraft.world.entity.Entity isInsidePortal +public net.minecraft.world.entity.Mob leashHolder +public net.minecraft.world.entity.LivingEntity jumping + +# No-Tick view distance +public net.minecraft.server.level.ChunkHolder broadcast(Lnet/minecraft/network/protocol/Packet;Z)V +public net.minecraft.server.level.ChunkMap setViewDistance(I)V +public net.minecraft.server.level.ChunkMap readChunk(Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/nbt/CompoundTag; +public net.minecraft.server.level.ChunkMap playerLoadedChunk(Lnet/minecraft/server/level/ServerPlayer;[Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/world/level/chunk/LevelChunk;)V +public net.minecraft.server.level.ChunkMap mainThreadMailbox # todo one of these doesn't belong here + +# Optimise TickListServer +public net.minecraft.world.level.ServerTickList saveTickList(Ljava/util/function/Function;Ljava/lang/Iterable;J)Lnet/minecraft/nbt/ListTag; + +# Don't move existing players to world spawn +public net.minecraft.server.level.ServerPlayer fudgeSpawnLocation(Lnet/minecraft/server/level/ServerLevel;)V + +# Implement Player Client Options API +public net.minecraft.world.entity.player.Player DATA_PLAYER_MODE_CUSTOMISATION + +# Fix Longstanding Broken behavior +public net.minecraft.server.level.ChunkMap addEntity(Lnet/minecraft/world/entity/Entity;)V + +# Load Chunks for Login Async +public net.minecraft.server.level.ServerChunkCache runDistanceManagerUpdates()Z +public net.minecraft.server.level.ServerChunkCache$MainThreadExecutor # todo doesn't belong here but oh well + +# Implement MobGoalApi +public net.minecraft.world.entity.ai.goal.GoalSelector availableGoals + +# Add villager reputation API +public net.minecraft.world.entity.ai.gossip.GossipContainer$EntityGossips +public net.minecraft.world.entity.ai.gossip.GossipContainer$EntityGossips ()V + +# Add entity liquid API +public net.minecraft.world.entity.Entity isInRain()Z +public net.minecraft.world.entity.Entity isInBubbleColumn()Z + +# Allow delegation to vanilla chunk gen +public org.bukkit.craftbukkit.generator.CustomChunkGenerator delegate + +# Optimize redstone algorithm +public net.minecraft.world.level.block.RedStoneWireBlock shouldSignal + +# Add more Evoker API +public net.minecraft.world.entity.monster.Evoker setWololoTarget(Lnet/minecraft/world/entity/animal/Sheep;)V +public net.minecraft.world.entity.monster.Evoker getWololoTarget()Lnet/minecraft/world/entity/animal/Sheep; + +# More lightning API +public net.minecraft.world.entity.LightningBolt life +public net.minecraft.world.entity.LightningBolt flashes + +# Configurable door breaking difficulty +public net.minecraft.world.entity.monster.Vindicator DOOR_BREAKING_PREDICATE +public net.minecraft.world.entity.monster.Zombie DOOR_BREAKING_PREDICATE + +# Optimize sending packets to nearby locations (sounds/effects) +public net.minecraft.server.level.ServerLevel players + +# Item Rarity API +public net.minecraft.world.item.Item rarity + +# More Enchantment API +public net.minecraft.world.item.enchantment.Enchantment slots + +# Fix and optimise world force upgrading +public net.minecraft.util.worldupdate.WorldUpgrader REGEX + +# More Lidded Block API +public net.minecraft.world.level.block.entity.EnderChestBlockEntity openersCounter + +# Improve EntityShootBowEvent +public net.minecraft.world.entity.projectile.AbstractArrow getPickupItem()Lnet.minecraft.world.item.ItemStack; + +# Implement Expanded ArmorStand API +public net.minecraft.world.entity.decoration.ArmorStand isDisabled(Lnet/minecraft/world/entity/EquipmentSlot;)Z + +# Chunk debug command +public net.minecraft.server.level.ChunkMap entitiesInLevel +public net.minecraft.server.level.ServerLevel players + +# Chunk priority urgency system +public net.minecraft.server.level.ChunkMap$ChunkDistanceManager + +# Here's Johnny +public net.minecraft.world.entity.monster.Vindicator isJohnny + +# Chunk debug command +public net.minecraft.server.level.Ticket createdTick +public net.minecraft.server.level.ServerChunkCache CHUNK_STATUSES +public net.minecraft.server.level.ChunkHolder pos + +# Incremental chunk saving +public net.minecraft.world.level.entity.PersistentEntitySectionManager storeChunkSections(JLjava/util/function/Consumer;)Z + +# Mending XP API +public net.minecraft.world.entity.ExperienceOrb durabilityToXp(I)I +public net.minecraft.world.entity.ExperienceOrb xpToDurability(I)I + +# Implement an API for CanPlaceOn and CanDestroy NBT values +public net.minecraft.commands.arguments.blocks.BlockStateParser id + +# Villager Restock API +public net.minecraft.world.entity.npc.Villager numberOfRestocksToday + +# Mob Pathfinding API +public net.minecraft.world.entity.ai.navigation.PathNavigation pathFinder +public net.minecraft.world.level.pathfinder.PathFinder nodeEvaluator +public net.minecraft.world.level.pathfinder.Path nodes + +# Add more Witch API +public net.minecraft.world.entity.monster.Witch usingTime + +# PlayerDeathEvent#getItemsToKeep +public net.minecraft.world.entity.player.Inventory compartments diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000000..d86913a4aa --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,93 @@ +plugins { + java + id("com.github.johnrengelman.shadow") version "7.0.0" apply false + id("io.papermc.paperweight.core") version "1.1.2" +} + +subprojects { + apply(plugin = "java") + apply(plugin = "maven-publish") + + java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(16)) + } + } + + tasks.withType().configureEach { + options.encoding = "UTF-8" + options.release.set(16) + } + + configure { + repositories { + maven { + name = "paperSnapshots" + url = uri("https://papermc.io/repo/repository/maven-snapshots/") + credentials(PasswordCredentials::class) + } + } + } + + if (name == "Paper-MojangAPI") { + return@subprojects + } + + repositories { + mavenCentral() + maven("https://repo1.maven.org/maven2/") + maven("https://oss.sonatype.org/content/groups/public/") + maven("https://papermc.io/repo/repository/maven-public/") + maven("https://ci.emc.gs/nexus/content/groups/aikar/") + maven("https://repo.aikar.co/content/groups/aikar") + maven("https://repo.md-5.net/content/repositories/releases/") + maven("https://hub.spigotmc.org/nexus/content/groups/public/") + } +} + +repositories { + mavenCentral() + maven("https://papermc.io/repo/repository/maven-public/") { + content { + onlyForConfigurations("paperclip") + } + } + maven("https://maven.quiltmc.org/repository/release/") { + content { + onlyForConfigurations("paramMappings", "remapper") + } + } + maven("https://files.minecraftforge.net/maven/") { + content { + onlyForConfigurations("decompiler") + } + } +} + +dependencies { + paramMappings("org.quiltmc:yarn:1.17+build.2:mergedv2") + remapper("org.quiltmc:tiny-remapper:0.4.1") + decompiler("net.minecraftforge:forgeflower:1.5.498.12") + paperclip("io.papermc:paperclip:2.0.0@jar") +} + +paperweight { + minecraftVersion.set(providers.gradleProperty("mcVersion")) + serverProject.set(project(":Paper-Server")) + + paper { + spigotApiPatchDir.set(file("patches/api")) + spigotServerPatchDir.set(file("patches/server")) + + mappingsPatch.set(file("build-data/mappings-patch.tiny")) + + additionalSpigotMemberMappings.set(file("build-data/additional-spigot-member-mappings.csrg")) + craftBukkitPatchPatchesDir.set(file("build-data/craftbukkit-patch-patches")) + } +} + +tasks.register("printMinecraftVersion") { + doLast { + println(providers.gradleProperty("mcVersion").forUseAtConfigurationTime().get().trim()) + } +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000000..0fec65e48e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,7 @@ +group = io.papermc.paper +version = 1.17-R0.1-SNAPSHOT + +mcVersion = 1.17 + +org.gradle.parallel=true +org.gradle.vfs.watch=false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..e708b1c023 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..69a9715077 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000000..4f906e0c81 --- /dev/null +++ b/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000..107acd32c4 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/paper b/paper deleted file mode 100755 index a397d2786b..0000000000 --- a/paper +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env bash - -# resolve shell-specifics -case "$(echo "$SHELL" | sed -E 's|/usr(/local)?||g')" in - "/bin/zsh") - RCPATH="$HOME/.zshrc" - SOURCE="${BASH_SOURCE[0]:-${(%):-%N}}" - ;; - *) - RCPATH="$HOME/.bashrc" - if [[ -f "$HOME/.bash_aliases" ]]; then - RCPATH="$HOME/.bash_aliases" - fi - SOURCE="${BASH_SOURCE[0]}" - ;; -esac - -# get base dir regardless of execution location -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -SOURCE=$([[ "$SOURCE" = /* ]] && echo "$SOURCE" || echo "$PWD/${SOURCE#./}") -basedir=$(dirname "$SOURCE") -gitcmd="git -c commit.gpgsign=false" - -source "$basedir/scripts/functions.sh" - -"$basedir"/scripts/requireDeps.sh || exit 1 - -failed=0 -case "$1" in - "rb" | "rbp" | "rebuild") - ( - set -e - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" $2 || exit 1 - ) || failed=1 - ;; - "rbf" | "rbfull") - ( - set -e - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" "nofilter" || exit 1 - ) || failed=1 - ;; - "p" | "patch") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - ) || failed=1 - ;; - "j" | "jar") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" "--jar" || exit 1 - ) || failed=1 - ;; - "b" | "build") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - (cd Paper-API ; mvn clean install) || exit 1 - (cd Paper-MojangAPI ; mvn clean install) || exit 1 - (cd Paper-Server ; mvn clean package) || exit 1 - echo "Paper jar successfully built" - ls -la Paper-Server/target/paper*.jar - ) || failed=1 - ;; - "i" | "install") - ( - set -e - cd "$basedir" - scripts/build.sh "$basedir" || exit 1 - mvn clean install || exit 1 - echo "Paper jar successfully built and installed to local repo" - ) || failed=1 - ;; - "pc" | "paperclip") - ( - set -e - cd "$basedir" - scripts/paperclip.sh "$basedir" || exit 1 - ) || failed=1 - ;; - "make") - ( - if [[ "$2" = "bacon" ]] ; then - set -e - cd "$basedir" - scripts/build.sh "$basedir" "--jar" - fi - ) - ;; - "m" | "mcdev") - ( - set -e - cd "$basedir" - scripts/makemcdevsrc.sh "$basedir" - ) - ;; - "t" | "test" | "testserver") - ( - cd "$basedir" - shift - scripts/testServer.sh "$basedir" "$@" - ) - ;; - "td" | "testdir") - cd "${PAPER_TEST_DIR:-$basedir/work/test-server}" - ;; - "u" | "up" | "upstream") - ( - cd "$basedir" - scripts/upstreamMerge.sh "$basedir" "$2" - ) - ;; - "cu" | "commitup" | "commitupstream" | "upc" | "upcommit" | "upstreamcommit") - ( - cd "$basedir" - shift - scripts/upstreamCommit.sh "$@" - ) - ;; - "r" | "root") - cd "$basedir" - ;; - "a" | "api") - cd "$basedir/Paper-API" - ;; - "s" | "server") - cd "$basedir/Paper-Server" - ;; - "c" | "clean") - rm -rf Paper-API - rm -rf Paper-Server - rm -rf work - echo "Cleaned build files" - ;; - "con" | "continue") - if [ -d ".git/rebase-apply" ]; then - git -c commit.gpgsign=false am --continue - elif [ -d ".git/rebase-merge" ]; then - git -c commit.gpgsign=false rebase --continue - fi - ;; - "e" | "edit") - case "$2" in - "s" | "server") - mkdir -p "$basedir/work/Temp" - echo "$basedir/Paper-Server" > "$basedir/work/Temp/PAPER_LAST_EDIT" - cd "$basedir/Paper-Server" - ( - set -e - - paperstash - $gitcmd rebase -i upstream/upstream - paperunstash - ) - ;; - "a" | "api") - mkdir -p "$basedir/work/Temp" - echo "$basedir/Paper-API" > "$basedir/work/Temp/PAPER_LAST_EDIT" - cd "$basedir/Paper-API" - ( - set -e - - paperstash - $gitcmd rebase -i upstream/upstream - paperunstash - ) - ;; - "c" | "continue") - cd "$( < "$basedir/work/Temp/PAPER_LAST_EDIT")" - rm -f "$basedir/work/Temp/PAPER_LAST_EDIT" - ( - set -e - - $gitcmd add . - $gitcmd commit --amend - $gitcmd rebase --continue - - cd "$basedir" - scripts/rebuildPatches.sh "$basedir" - ) - ;; - *) - echo "You must edit either the api or server." - ;; - esac - ;; - "setup") - if [[ -f "$RCPATH" ]] ; then - NAME="paper" - if [[ ! -z "${2+x}" ]] ; then - NAME="$2" - fi - (grep "alias $NAME=" "$RCPATH" > /dev/null) && (sed -i "s|alias $NAME=.*|alias $NAME='. $SOURCE'|g" "$RCPATH") || (echo "alias $NAME='. $SOURCE'" >> "$RCPATH") - alias "$NAME=. $SOURCE" - echo "You can now just type '$NAME' at any time to access the paper tool." - else - echo "We were unable to setup the paper build tool alias: $RCPATH is missing" - fi - ;; - *) - echo "PaperMC build tool command. This provides a variety of commands to build and manage the PaperMC build" - echo "environment. For all of the functionality of this command to be available, you must first run the" - echo "'setup' command. View below for details. For essential building and patching, you do not need to do the setup." - echo "" - echo " Normal commands:" - echo " * rb, rebuild | Rebuild patches, can be called from anywhere." - echo " * p, patch | Apply all patches to the project without building it. Can be run from anywhere." - echo " * j, jar | Apply all patches and build the project, paperclip.jar will be output. Can be run from anywhere." - echo " * i, install | Build and install paper into the local repo. Can be run from anywhere." - echo " * m, mcdev | Setup decompiled sources for non-modified NMS files to be imported into an IDE. Can be run from anywhere." - echo " * u, up, upstream | Updates the submodules used by Paper to their latest upstream versions." - echo " * upc, upstreamcommit | Creates the correctly-formatted upstream commit after updating upstream." - echo " * c, clean | Removes all generated files, Paper-API, Paper-Server, and work." - echo " * t, testserver | Run the test server with the set of plugins Paper uses as a basis for server tests." - echo " * con, continue | Shortcut command for running git am --continue, or git rebase --continue." - echo "" - echo " These commands require the setup command before use:" - echo " * r, root | Change directory to the root of the project." - echo " * a. api | Move to the Paper-API directory." - echo " * s, server | Move to the Paper-Server directory." - echo " * td, testdirectory | Move to the test-server directory." - echo " * e, edit | Use to edit a specific patch, give it the argument \"server\" or \"api\"" - echo " | respectively to edit the correct project. Use the argument \"continue\" after" - echo " | the changes have been made to finish and rebuild patches. Can be called from anywhere." - echo "" - echo " * setup | Add an alias to $RCPATH to allow full functionality of this script. Run as:" - echo " | . ./paper setup" - echo " | After you run this command you'll be able to just run 'paper' from anywhere." - echo " | The default name for the resulting alias is 'paper', you can give an argument to override" - echo " | this default, such as:" - echo " | . ./paper setup example" - echo " | Which will allow you to run 'example' instead." - ;; -esac - -unset RCPATH -unset SOURCE -unset basedir -unset -f color -unset -f colorend -unset -f paperstash -unset -f paperunstash -if [[ "$failed" == "1" ]]; then - unset failed - false -else - unset failed - true -fi diff --git a/Spigot-API-Patches/API-to-get-a-BlockState-without-a-snapshot.patch b/patches/api/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 patches/api/API-to-get-a-BlockState-without-a-snapshot.patch diff --git a/Spigot-API-Patches/Ability-to-apply-mending-to-XP-API.patch b/patches/api/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 patches/api/Ability-to-apply-mending-to-XP-API.patch diff --git a/Spigot-API-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/api/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from Spigot-API-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/api/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/Spigot-API-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/api/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 patches/api/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/Spigot-API-Patches/Add-API-for-quit-reason.patch b/patches/api/Add-API-for-quit-reason.patch similarity index 100% rename from Spigot-API-Patches/Add-API-for-quit-reason.patch rename to patches/api/Add-API-for-quit-reason.patch diff --git a/Spigot-API-Patches/Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/api/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 patches/api/Add-API-methods-to-control-if-armour-stands-can-move.patch diff --git a/Spigot-API-Patches/Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/patches/api/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 patches/api/Add-API-to-get-Material-from-Boats-and-Minecarts.patch diff --git a/Spigot-API-Patches/Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/patches/api/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 patches/api/Add-API-to-get-exact-interaction-point-in-PlayerInte.patch diff --git a/Spigot-API-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/api/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 100% rename from Spigot-API-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/api/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch diff --git a/Spigot-API-Patches/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/api/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/api/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/Spigot-API-Patches/Add-ArmorStand-Item-Meta.patch b/patches/api/Add-ArmorStand-Item-Meta.patch similarity index 100% rename from Spigot-API-Patches/Add-ArmorStand-Item-Meta.patch rename to patches/api/Add-ArmorStand-Item-Meta.patch diff --git a/Spigot-API-Patches/Add-Ban-Methods-to-Player-Objects.patch b/patches/api/Add-Ban-Methods-to-Player-Objects.patch similarity index 100% rename from Spigot-API-Patches/Add-Ban-Methods-to-Player-Objects.patch rename to patches/api/Add-Ban-Methods-to-Player-Objects.patch diff --git a/Spigot-API-Patches/Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/patches/api/Add-BaseComponent-sendMessage-methods-to-CommandSend.patch similarity index 100% rename from Spigot-API-Patches/Add-BaseComponent-sendMessage-methods-to-CommandSend.patch rename to patches/api/Add-BaseComponent-sendMessage-methods-to-CommandSend.patch diff --git a/Spigot-API-Patches/Add-BeaconEffectEvent.patch b/patches/api/Add-BeaconEffectEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BeaconEffectEvent.patch rename to patches/api/Add-BeaconEffectEvent.patch diff --git a/Spigot-API-Patches/Add-BellRevealRaiderEvent.patch b/patches/api/Add-BellRevealRaiderEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BellRevealRaiderEvent.patch rename to patches/api/Add-BellRevealRaiderEvent.patch diff --git a/Spigot-API-Patches/Add-BellRingEvent.patch b/patches/api/Add-BellRingEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BellRingEvent.patch rename to patches/api/Add-BellRingEvent.patch diff --git a/Spigot-API-Patches/Add-Block-isValidTool.patch b/patches/api/Add-Block-isValidTool.patch similarity index 100% rename from Spigot-API-Patches/Add-Block-isValidTool.patch rename to patches/api/Add-Block-isValidTool.patch diff --git a/Spigot-API-Patches/Add-BlockFailedDispenseEvent.patch b/patches/api/Add-BlockFailedDispenseEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BlockFailedDispenseEvent.patch rename to patches/api/Add-BlockFailedDispenseEvent.patch diff --git a/Spigot-API-Patches/Add-BlockPreDispenseEvent.patch b/patches/api/Add-BlockPreDispenseEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-BlockPreDispenseEvent.patch rename to patches/api/Add-BlockPreDispenseEvent.patch diff --git a/Spigot-API-Patches/Add-BlockSoundGroup-interface.patch b/patches/api/Add-BlockSoundGroup-interface.patch similarity index 92% rename from Spigot-API-Patches/Add-BlockSoundGroup-interface.patch rename to patches/api/Add-BlockSoundGroup-interface.patch index faaab62a92..8387646011 100644 --- a/Spigot-API-Patches/Add-BlockSoundGroup-interface.patch +++ b/patches/api/Add-BlockSoundGroup-interface.patch @@ -67,18 +67,10 @@ diff --git a/src/main/java/org/bukkit/block/Block.java b/src/main/java/org/bukki index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/block/Block.java +++ b/src/main/java/org/bukkit/block/Block.java -@@ -0,0 +0,0 @@ - package org.bukkit.block; - - import java.util.Collection; -+ - import org.bukkit.Chunk; - import org.bukkit.FluidCollisionMode; - import org.bukkit.Location; @@ -0,0 +0,0 @@ public interface Block extends Metadatable { */ @NotNull - BoundingBox getBoundingBox(); + VoxelShape getCollisionShape(); + + // Paper start + /** diff --git a/Spigot-API-Patches/Add-Destroy-Speed-API.patch b/patches/api/Add-Destroy-Speed-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Destroy-Speed-API.patch rename to patches/api/Add-Destroy-Speed-API.patch diff --git a/Spigot-API-Patches/Add-ElderGuardianAppearanceEvent.patch b/patches/api/Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-ElderGuardianAppearanceEvent.patch rename to patches/api/Add-ElderGuardianAppearanceEvent.patch diff --git a/Spigot-API-Patches/Add-EntityBlockStorage-clearEntities.patch b/patches/api/Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityBlockStorage-clearEntities.patch rename to patches/api/Add-EntityBlockStorage-clearEntities.patch diff --git a/Spigot-API-Patches/Add-EntityInsideBlockEvent.patch b/patches/api/Add-EntityInsideBlockEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityInsideBlockEvent.patch rename to patches/api/Add-EntityInsideBlockEvent.patch diff --git a/Spigot-API-Patches/Add-EntityKnockbackByEntityEvent.patch b/patches/api/Add-EntityKnockbackByEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityKnockbackByEntityEvent.patch rename to patches/api/Add-EntityKnockbackByEntityEvent.patch diff --git a/Spigot-API-Patches/Add-EntityLoadCrossbowEvent.patch b/patches/api/Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityLoadCrossbowEvent.patch rename to patches/api/Add-EntityLoadCrossbowEvent.patch diff --git a/Spigot-API-Patches/Add-EntityTeleportEndGatewayEvent.patch b/patches/api/Add-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityTeleportEndGatewayEvent.patch rename to patches/api/Add-EntityTeleportEndGatewayEvent.patch diff --git a/Spigot-API-Patches/Add-EntityZapEvent.patch b/patches/api/Add-EntityZapEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-EntityZapEvent.patch rename to patches/api/Add-EntityZapEvent.patch diff --git a/patches/api/Add-FastUtil-to-Bukkit.patch b/patches/api/Add-FastUtil-to-Bukkit.patch new file mode 100644 index 0000000000..53950d2083 --- /dev/null +++ b/patches/api/Add-FastUtil-to-Bukkit.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 1 Apr 2016 00:02:47 -0400 +Subject: [PATCH] Add FastUtil to Bukkit + +Doesn't expose to plugins, just allows Paper-API to use it for optimization + +diff --git a/build.gradle.kts b/build.gradle.kts +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + api("net.md-5:bungeecord-chat:1.16-R0.4") + api("org.yaml:snakeyaml:1.28") + api("com.googlecode.json-simple:json-simple:1.1.1") // Paper ++ api("it.unimi.dsi:fastutil:8.2.2") + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/Spigot-API-Patches/Add-GS4-Query-event.patch b/patches/api/Add-GS4-Query-event.patch similarity index 100% rename from Spigot-API-Patches/Add-GS4-Query-event.patch rename to patches/api/Add-GS4-Query-event.patch diff --git a/Spigot-API-Patches/Add-Heightmap-API.patch b/patches/api/Add-Heightmap-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Heightmap-API.patch rename to patches/api/Add-Heightmap-API.patch diff --git a/Spigot-API-Patches/Add-ItemStack-Recipe-API-helper-methods.patch b/patches/api/Add-ItemStack-Recipe-API-helper-methods.patch similarity index 100% rename from Spigot-API-Patches/Add-ItemStack-Recipe-API-helper-methods.patch rename to patches/api/Add-ItemStack-Recipe-API-helper-methods.patch diff --git a/Spigot-API-Patches/Add-ItemStackRecipeChoice-Draft-API.patch b/patches/api/Add-ItemStackRecipeChoice-Draft-API.patch similarity index 100% rename from Spigot-API-Patches/Add-ItemStackRecipeChoice-Draft-API.patch rename to patches/api/Add-ItemStackRecipeChoice-Draft-API.patch diff --git a/Spigot-API-Patches/Add-LivingEntity-clearActiveItem.patch b/patches/api/Add-LivingEntity-clearActiveItem.patch similarity index 100% rename from Spigot-API-Patches/Add-LivingEntity-clearActiveItem.patch rename to patches/api/Add-LivingEntity-clearActiveItem.patch diff --git a/Spigot-API-Patches/Add-LivingEntity-getTargetEntity.patch b/patches/api/Add-LivingEntity-getTargetEntity.patch similarity index 100% rename from Spigot-API-Patches/Add-LivingEntity-getTargetEntity.patch rename to patches/api/Add-LivingEntity-getTargetEntity.patch diff --git a/Spigot-API-Patches/Add-Material-Tags.patch b/patches/api/Add-Material-Tags.patch similarity index 99% rename from Spigot-API-Patches/Add-Material-Tags.patch rename to patches/api/Add-Material-Tags.patch index 96c40e0aa5..1a04c5f693 100644 --- a/Spigot-API-Patches/Add-Material-Tags.patch +++ b/patches/api/Add-Material-Tags.patch @@ -173,7 +173,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ + public static final MaterialSetTag BUCKETS = new MaterialSetTag(keyFor("buckets")) + .endsWith("BUCKET") -+ .ensureSize("BUCKETS", 8); ++ .ensureSize("BUCKETS", 10); + + /** + * Covers coal and charcoal. @@ -254,7 +254,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final MaterialSetTag GLASS = new MaterialSetTag(keyFor("glass")) + .endsWith("_GLASS") + .add(Material.GLASS) -+ .ensureSize("GLASS", 17); ++ .ensureSize("GLASS", 18); + + /** + * Covers the non-colored glass panes and stained glass panes (panes only). @@ -305,7 +305,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ + public static final MaterialSetTag INFESTED_BLOCKS = new MaterialSetTag(keyFor("infested_blocks")) + .startsWith("INFESTED_") -+ .ensureSize("INFESTED_BLOCKS", 6); ++ .ensureSize("INFESTED_BLOCKS", 7); + + /** + * Covers the variants of mushroom blocks. @@ -333,7 +333,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final MaterialSetTag ORES = new MaterialSetTag(keyFor("ores")) + .add(Material.ANCIENT_DEBRIS) + .endsWith("_ORE") -+ .ensureSize("ORES", 10); ++ .ensureSize("ORES", 19); + + /** + * Covers all piston typed items and blocks including the piston head and moving piston. @@ -433,7 +433,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ + public static final MaterialSetTag SPAWN_EGGS = new MaterialSetTag(keyFor("spawn_eggs")) + .endsWith("_SPAWN_EGG") -+ .ensureSize("SPAWN_EGGS", 64); ++ .ensureSize("SPAWN_EGGS", 67); + + /** + * Covers all colors of stained glass. diff --git a/Spigot-API-Patches/Add-MetadataStoreBase.removeAll-Plugin.patch b/patches/api/Add-MetadataStoreBase.removeAll-Plugin.patch similarity index 100% rename from Spigot-API-Patches/Add-MetadataStoreBase.removeAll-Plugin.patch rename to patches/api/Add-MetadataStoreBase.removeAll-Plugin.patch diff --git a/Spigot-API-Patches/Add-Mob-Goal-API.patch b/patches/api/Add-Mob-Goal-API.patch similarity index 52% rename from Spigot-API-Patches/Add-Mob-Goal-API.patch rename to patches/api/Add-Mob-Goal-API.patch index eef545bd33..cce199fa6c 100644 --- a/Spigot-API-Patches/Add-Mob-Goal-API.patch +++ b/patches/api/Add-Mob-Goal-API.patch @@ -244,6 +244,68 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ +public interface VanillaGoal extends Goal { + ++ GoalKey AVOID_ENTITY = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_entity")); ++ GoalKey BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg")); ++ GoalKey BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door")); ++ GoalKey BREATH_AIR = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath_air")); ++ GoalKey BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed")); ++ GoalKey CAT_LIE_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_lie_on_bed")); ++ GoalKey CAT_SIT_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_block")); ++ GoalKey DOLPHIN_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_jump")); ++ GoalKey EAT_BLOCK = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_block")); ++ GoalKey FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun")); ++ GoalKey FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float")); ++ GoalKey FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat")); ++ GoalKey FOLLOW_FLOCK_LEADER = GoalKey.of(Fish.class, NamespacedKey.minecraft("follow_flock_leader")); ++ GoalKey FOLLOW_MOB = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_mob")); ++ GoalKey FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner")); ++ GoalKey FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent")); ++ GoalKey GOLEM_RANDOM_STROLL_IN_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("golem_random_stroll_in_village")); ++ GoalKey INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact")); ++ GoalKey LAND_ON_OWNERS_SHOULDER = GoalKey.of(Parrot.class, NamespacedKey.minecraft("land_on_owners_shoulder")); ++ GoalKey LEAP_AT = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at")); ++ GoalKey LLAMA_FOLLOW_CARAVAN = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow_caravan")); ++ GoalKey LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player")); ++ GoalKey LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player")); ++ GoalKey MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack")); ++ GoalKey MOVE_BACK_TO_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_back_to_village")); ++ GoalKey MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village")); ++ GoalKey MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction")); ++ GoalKey MOVE_TOWARDS = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards")); ++ GoalKey OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack")); ++ GoalKey OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower")); ++ GoalKey OPEN_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("open_door")); ++ GoalKey PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic")); ++ GoalKey PATHFIND_TO_RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("pathfind_to_raid")); ++ GoalKey RANDOM_LOOK_AROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_look_around")); ++ GoalKey RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll")); ++ GoalKey RANDOM_SWIMMING = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swimming")); ++ GoalKey RANGED_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("ranged_attack")); ++ GoalKey RANGED_BOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("ranged_bow_attack")); ++ GoalKey RANGED_CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("ranged_crossbow_attack")); ++ GoalKey REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block")); ++ GoalKey RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun")); ++ GoalKey RUN_AROUND_LIKE_CRAZY = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("run_around_like_crazy")); ++ GoalKey SIT_WHEN_ORDERED_TO = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit_when_ordered_to")); ++ GoalKey STROLL_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_through_village")); ++ GoalKey SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell")); ++ GoalKey TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt")); ++ GoalKey TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player")); ++ GoalKey TRY_FIND_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("try_find_water")); ++ GoalKey USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item")); ++ GoalKey WATER_AVOIDING_RANDOM_FLYING = GoalKey.of(Creature.class, NamespacedKey.minecraft("water_avoiding_random_flying")); ++ GoalKey WATER_AVOIDING_RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("water_avoiding_random_stroll")); ++ GoalKey ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack")); ++ GoalKey DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village")); ++ GoalKey HURT_BY = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by")); ++ GoalKey NEAREST_ATTACKABLE = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable")); ++ GoalKey NEAREST_ATTACKABLE_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_witch")); ++ GoalKey NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider")); ++ GoalKey NON_TAME_RANDOM = GoalKey.of(Tameable.class, NamespacedKey.minecraft("non_tame_random")); ++ GoalKey OWNER_HURT_BY = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by")); ++ GoalKey OWNER_HURT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt")); ++ GoalKey RESET_UNIVERSAL_ANGER = GoalKey.of(Mob.class, NamespacedKey.minecraft("reset_universal_anger")); ++ GoalKey FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim")); + GoalKey BEE_ATTACK = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_attack")); + GoalKey BEE_BECOME_ANGRY = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_become_angry")); + GoalKey BEE_ENTER_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_enter_hive")); @@ -254,29 +316,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + GoalKey BEE_LOCATE_HIVE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_locate_hive")); + GoalKey BEE_POLLINATE = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_pollinate")); + GoalKey BEE_WANDER = GoalKey.of(Bee.class, NamespacedKey.minecraft("bee_wander")); -+ GoalKey BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball")); -+ GoalKey TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance")); + GoalKey CAT_AVOID_ENTITY = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_avoid_entity")); + GoalKey CAT_RELAX_ON_OWNER = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_relax_on_owner")); ++ GoalKey CAT_TEMPT = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_tempt")); + GoalKey DOLPHIN_SWIM_TO_TREASURE = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_to_treasure")); + GoalKey DOLPHIN_SWIM_WITH_PLAYER = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_swim_with_player")); -+ GoalKey DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items")); -+ GoalKey DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack")); -+ GoalKey DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach")); -+ GoalKey DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water")); -+ GoalKey DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up")); -+ GoalKey DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack")); -+ GoalKey ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block")); -+ GoalKey ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block")); -+ GoalKey PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target")); -+ GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at")); -+ GoalKey EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell")); -+ GoalKey EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell")); -+ GoalKey EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell")); -+ GoalKey EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell")); -+ GoalKey FISH_SWIM = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_swim")); -+ GoalKey FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted")); -+ GoalKey FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant")); ++ GoalKey PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("play_with_items")); ++ GoalKey DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("defend_trusted")); ++ GoalKey FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("faceplant")); + GoalKey FOX_BREED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_breed")); + GoalKey FOX_EAT_BERRIES = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_eat_berries")); + GoalKey FOX_FLOAT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_float")); @@ -284,161 +331,193 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + GoalKey FOX_LOOK_AT_PLAYER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_look_at_player")); + GoalKey FOX_MELEE_ATTACK = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_melee_attack")); + GoalKey FOX_PANIC = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_panic")); -+ GoalKey FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search")); + GoalKey FOX_POUNCE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_pounce")); + GoalKey FOX_SEARCH_FOR_ITEMS = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_search_for_items")); -+ GoalKey FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep")); + GoalKey FOX_STROLL_THROUGH_VILLAGE = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stroll_through_village")); -+ GoalKey FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter")); -+ GoalKey FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey")); -+ GoalKey GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target")); -+ GoalKey GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move")); -+ GoalKey GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target")); -+ GoalKey GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack")); -+ GoalKey RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door")); -+ GoalKey ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell")); -+ GoalKey ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell")); -+ GoalKey SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell")); -+ GoalKey LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf")); -+ GoalKey LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by")); -+ GoalKey LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader")); -+ GoalKey LONG_DISTANCE_PATROL = GoalKey.of(Monster.class, NamespacedKey.minecraft("long_distance_patrol")); ++ GoalKey PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("perch_and_search")); ++ GoalKey SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("seek_shelter")); ++ GoalKey SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("sleep")); ++ GoalKey STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("stalk_prey")); + GoalKey OCELOT_AVOID_ENTITY = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_avoid_entity")); + GoalKey OCELOT_TEMPT = GoalKey.of(Ocelot.class, NamespacedKey.minecraft("ocelot_tempt")); + GoalKey PANDA_ATTACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_attack")); + GoalKey PANDA_AVOID = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_avoid")); + GoalKey PANDA_BREED = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_breed")); -+ GoalKey PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target")); ++ GoalKey PANDA_HURT_BY = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by")); + GoalKey PANDA_LIE_ON_BACK = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_lie_on_back")); + GoalKey PANDA_LOOK_AT_PLAYER = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_look_at_player")); + GoalKey PANDA_PANIC = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_panic")); + GoalKey PANDA_ROLL = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_roll")); + GoalKey PANDA_SIT = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sit")); + GoalKey PANDA_SNEEZE = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_sneeze")); ++ GoalKey POLAR_BEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_attack_players")); ++ GoalKey POLAR_BEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_hurt_by")); ++ GoalKey POLAR_BEAR_MELEE_ATTACK = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_melee_attack")); ++ GoalKey POLAR_BEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polar_bear_panic")); ++ GoalKey PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff")); ++ GoalKey EVIL_RABBIT_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("evil_rabbit_attack")); ++ GoalKey RABBIT_AVOID_ENTITY = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_entity")); ++ GoalKey RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic")); ++ GoalKey RAID_GARDEN = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("raid_garden")); ++ GoalKey SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee")); ++ GoalKey SQUID_RANDOM_MOVEMENT = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_random_movement")); ++ GoalKey TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed")); ++ GoalKey TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home")); ++ GoalKey TURTLE_GO_TO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_to_water")); ++ GoalKey TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg")); ++ GoalKey TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic")); ++ GoalKey TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll")); ++ GoalKey TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel")); ++ GoalKey WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity")); ++ GoalKey LLAMA_ATTACK_WOLF = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_attack_wolf")); ++ GoalKey LLAMA_HURT_BY = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_hurt_by")); ++ GoalKey SKELETON_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("skeleton_trap")); ++ GoalKey TRADER_LLAMA_DEFEND_WANDERING_TRADER = GoalKey.of(Llama.class, NamespacedKey.minecraft("trader_llama_defend_wandering_trader")); ++ GoalKey WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing")); ++ GoalKey RAIDER_OPEN_DOOR = GoalKey.of(Illager.class, NamespacedKey.minecraft("raider_open_door")); ++ GoalKey SKELETON_MELEE = GoalKey.of(Skeleton.class, NamespacedKey.minecraft("skeleton_melee")); ++ GoalKey BLAZE_ATTACK = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_attack")); ++ GoalKey DROWNED_ATTACK = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_attack")); ++ GoalKey DROWNED_GO_TO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_go_to_beach")); ++ GoalKey DROWNED_GO_TO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_go_to_water")); ++ GoalKey DROWNED_SWIM_UP = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_swim_up")); ++ GoalKey DROWNED_TRIDENT_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("drowned_trident_attack")); ++ GoalKey ENDERMAN_FREEZE_WHEN_LOOKED_AT = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_freeze_when_looked_at")); ++ GoalKey ENDERMAN_LEAVE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_leave_block")); ++ GoalKey ENDERMAN_LOOK_FOR_PLAYER = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_look_for_player")); ++ GoalKey ENDERMAN_TAKE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_take_block")); ++ GoalKey EVOKER_ATTACK_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_attack_spell")); ++ GoalKey EVOKER_CASTING_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_casting_spell")); ++ GoalKey EVOKER_SUMMON_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_summon_spell")); ++ GoalKey EVOKER_WOLOLO_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_wololo_spell")); ++ GoalKey GHAST_LOOK = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_look")); ++ GoalKey GHAST_SHOOT_FIREBALL = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_shoot_fireball")); ++ GoalKey RANDOM_FLOAT_AROUND = GoalKey.of(Ghast.class, NamespacedKey.minecraft("random_float_around")); ++ GoalKey GUARDIAN_ATTACK = GoalKey.of(Guardian.class, NamespacedKey.minecraft("guardian_attack")); ++ GoalKey ILLUSIONER_BLINDNESS_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_blindness_spell")); ++ GoalKey ILLUSIONER_MIRROR_SPELL = GoalKey.of(Illusioner.class, NamespacedKey.minecraft("illusioner_mirror_spell")); ++ GoalKey LONG_DISTANCE_PATROL = GoalKey.of(Monster.class, NamespacedKey.minecraft("long_distance_patrol")); + GoalKey PHANTOM_ATTACK_PLAYER = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_player")); + GoalKey PHANTOM_ATTACK_STRATEGY = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_attack_strategy")); + GoalKey PHANTOM_CIRCLE_AROUND_ANCHOR = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_circle_around_anchor")); + GoalKey PHANTOM_SWEEP_ATTACK = GoalKey.of(Phantom.class, NamespacedKey.minecraft("phantom_sweep_attack")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger")); -+ /** -+ * @deprecated removed in 1.16 -+ */ -+ @Deprecated -+ GoalKey ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other")); -+ GoalKey POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players")); -+ GoalKey POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by")); -+ GoalKey POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee")); -+ GoalKey POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic")); -+ GoalKey PUFFERFISH_PUFF = GoalKey.of(PufferFish.class, NamespacedKey.minecraft("pufferfish_puff")); -+ GoalKey EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots")); -+ GoalKey KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack")); -+ GoalKey RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target")); -+ GoalKey RABBIT_PANIC = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_panic")); -+ GoalKey RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground")); -+ GoalKey RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner")); -+ GoalKey RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration")); -+ GoalKey RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village")); + GoalKey RAVAGER_MELEE_ATTACK = GoalKey.of(Ravager.class, NamespacedKey.minecraft("ravager_melee_attack")); + GoalKey SHULKER_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_attack")); -+ GoalKey SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense")); -+ GoalKey SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest")); ++ GoalKey SHULKER_DEFENSE_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense_attack")); ++ GoalKey SHULKER_NEAREST_ATTACK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest_attack")); + GoalKey SHULKER_PEEK = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_peek")); -+ GoalKey SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block")); -+ GoalKey SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others")); -+ GoalKey SKELETON_MELEE = GoalKey.of(Skeleton.class, NamespacedKey.minecraft("skeleton_melee")); -+ GoalKey SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle")); -+ GoalKey SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player")); ++ GoalKey SILVERFISH_MERGE_WITH_STONE = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_merge_with_stone")); ++ GoalKey SILVERFISH_WAKE_UP_FRIENDS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_up_friends")); ++ GoalKey SLIME_ATTACK = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_attack")); ++ GoalKey SLIME_FLOAT = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_float")); ++ GoalKey SLIME_KEEP_ON_JUMPING = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_keep_on_jumping")); + GoalKey SLIME_RANDOM_DIRECTION = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_direction")); -+ GoalKey SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump")); -+ GoalKey SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack")); -+ GoalKey SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target")); ++ GoalKey SPELLCASTER_CASTING_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_casting_spell")); ++ GoalKey SPIDER_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_attack")); ++ GoalKey SPIDER = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider")); + GoalKey STRIDER_GO_TO_LAVA = GoalKey.of(Strider.class, NamespacedKey.minecraft("strider_go_to_lava")); -+ GoalKey SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid")); -+ GoalKey SQUID_FLEE = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid_flee")); -+ GoalKey TURTLE_BREED = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_breed")); -+ GoalKey TURTLE_GO_HOME = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_go_home")); -+ GoalKey TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water")); -+ GoalKey TURTLE_LAY_EGG = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_lay_egg")); -+ GoalKey TURTLE_PANIC = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_panic")); -+ GoalKey TURTLE_RANDOM_STROLL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_random_stroll")); -+ GoalKey TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt")); -+ GoalKey TURTLE_TRAVEL = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_travel")); + GoalKey VEX_CHARGE_ATTACK = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_charge_attack")); -+ GoalKey VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner")); ++ GoalKey VEX_COPY_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_owner")); + GoalKey VEX_RANDOM_MOVE = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_random_move")); -+ GoalKey VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position")); + GoalKey VINDICATOR_BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("vindicator_break_door")); + GoalKey VINDICATOR_JOHNNY_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_johnny_attack")); + GoalKey VINDICATOR_MELEE_ATTACK = GoalKey.of(Vindicator.class, NamespacedKey.minecraft("vindicator_melee_attack")); -+ GoalKey WITHER_DO_NOTHING = GoalKey.of(Wither.class, NamespacedKey.minecraft("wither_do_nothing")); -+ GoalKey WOLF_AVOID_ENTITY = GoalKey.of(Wolf.class, NamespacedKey.minecraft("wolf_avoid_entity")); + GoalKey ZOMBIE_ATTACK_TURTLE_EGG = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack_turtle_egg")); -+ GoalKey ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack")); -+ GoalKey AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target")); -+ GoalKey BEG = GoalKey.of(Wolf.class, NamespacedKey.minecraft("beg")); -+ GoalKey BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot")); -+ GoalKey BREAK_DOOR = GoalKey.of(Mob.class, NamespacedKey.minecraft("break_door")); -+ GoalKey BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath")); -+ GoalKey BREED = GoalKey.of(Animals.class, NamespacedKey.minecraft("breed")); -+ GoalKey CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed")); -+ GoalKey CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack")); -+ GoalKey DEFEND_VILLAGE = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("defend_village")); -+ GoalKey DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open")); -+ GoalKey EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile")); -+ GoalKey FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school")); -+ GoalKey FLEE_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("flee_sun")); -+ GoalKey FLOAT = GoalKey.of(Mob.class, NamespacedKey.minecraft("float")); -+ GoalKey FOLLOW_BOAT = GoalKey.of(Creature.class, NamespacedKey.minecraft("follow_boat")); -+ GoalKey FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity")); -+ GoalKey FOLLOW_OWNER = GoalKey.of(Tameable.class, NamespacedKey.minecraft("follow_owner")); -+ GoalKey FOLLOW_PARENT = GoalKey.of(Animals.class, NamespacedKey.minecraft("follow_parent")); -+ GoalKey HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap")); -+ GoalKey HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target")); -+ GoalKey INTERACT = GoalKey.of(Mob.class, NamespacedKey.minecraft("interact")); -+ GoalKey JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block")); -+ GoalKey LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target")); -+ GoalKey LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow")); -+ GoalKey LOOK_AT_PLAYER = GoalKey.of(Mob.class, NamespacedKey.minecraft("look_at_player")); -+ GoalKey LOOK_AT_TRADING_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("look_at_trading_player")); -+ GoalKey MELEE_ATTACK = GoalKey.of(Creature.class, NamespacedKey.minecraft("melee_attack")); -+ GoalKey MOVE_THROUGH_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_through_village")); -+ GoalKey MOVE_TOWARDS_RESTRICTION = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_restriction")); -+ GoalKey MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target")); -+ GoalKey NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch")); -+ GoalKey NEAREST_HEALABLE_RAIDER = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_healable_raider")); -+ GoalKey NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village")); -+ GoalKey OCELOT_ATTACK = GoalKey.of(Mob.class, NamespacedKey.minecraft("ocelot_attack")); -+ GoalKey OFFER_FLOWER = GoalKey.of(IronGolem.class, NamespacedKey.minecraft("offer_flower")); -+ GoalKey OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target")); -+ GoalKey OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target")); -+ GoalKey PANIC = GoalKey.of(Creature.class, NamespacedKey.minecraft("panic")); -+ GoalKey PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch")); -+ GoalKey RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid")); -+ GoalKey RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly")); -+ GoalKey RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround")); -+ GoalKey RANDOM_STROLL = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll")); -+ GoalKey RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land")); -+ GoalKey RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim")); -+ GoalKey RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed")); -+ GoalKey REMOVE_BLOCK = GoalKey.of(Creature.class, NamespacedKey.minecraft("remove_block")); -+ GoalKey RESTRICT_SUN = GoalKey.of(Creature.class, NamespacedKey.minecraft("restrict_sun")); -+ GoalKey SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit")); -+ GoalKey STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village")); -+ GoalKey SWELL = GoalKey.of(Creeper.class, NamespacedKey.minecraft("swell")); -+ GoalKey TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame")); -+ GoalKey TEMPT = GoalKey.of(Creature.class, NamespacedKey.minecraft("tempt")); -+ GoalKey TRADE_WITH_PLAYER = GoalKey.of(AbstractVillager.class, NamespacedKey.minecraft("trade_with_player")); -+ GoalKey USE_ITEM = GoalKey.of(Mob.class, NamespacedKey.minecraft("use_item")); -+ GoalKey WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water")); -+ GoalKey WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump")); -+ GoalKey ZOMBIE_ATTACK = GoalKey.of(Zombie.class, NamespacedKey.minecraft("zombie_attack")); -+ GoalKey STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem")); -+ GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); ++ GoalKey WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("wander_to_position")); ++ GoalKey HOLD_GROUND_ATTACK = GoalKey.of(Raider.class, NamespacedKey.minecraft("hold_ground_attack")); ++ GoalKey OBTAIN_RAID_LEADER_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("obtain_raid_leader_banner")); ++ GoalKey RAIDER_CELEBRATION = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_celebration")); ++ GoalKey RAIDER_MOVE_THROUGH_VILLAGE = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_move_through_village")); ++ ++ /** ++ * @deprecated removed in 1.16 ++ */ ++ @Deprecated GoalKey ANGER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger")); ++ /** ++ * @deprecated removed in 1.16 ++ */ ++ @Deprecated GoalKey ANGER_OTHER = GoalKey.of(PigZombie.class, NamespacedKey.minecraft("anger_other")); ++ ++ // the constants below use spigot names, they no longer work ++ @Deprecated GoalKey BLAZE_FIREBALL = GoalKey.of(Blaze.class, NamespacedKey.minecraft("blaze_fireball")); ++ @Deprecated GoalKey TEMPT_CHANCE = GoalKey.of(Cat.class, NamespacedKey.minecraft("tempt_chance")); ++ @Deprecated GoalKey DOLPHIN_PLAY_WITH_ITEMS = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("dolphin_play_with_items")); ++ @Deprecated GoalKey DROWNED_GOTO_BEACH = GoalKey.of(Drowned.class, NamespacedKey.minecraft("drowned_goto_beach")); ++ @Deprecated GoalKey DROWNED_GOTO_WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("drowned_goto_water")); ++ @Deprecated GoalKey ENDERMAN_PICKUP_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_pickup_block")); ++ @Deprecated GoalKey ENDERMAN_PLACE_BLOCK = GoalKey.of(Enderman.class, NamespacedKey.minecraft("enderman_place_block")); ++ @Deprecated GoalKey PLAYER_WHO_LOOKED_AT_TARGET = GoalKey.of(Enderman.class, NamespacedKey.minecraft("player_who_looked_at_target")); ++ @Deprecated GoalKey EVOKER_CAST_SPELL = GoalKey.of(Evoker.class, NamespacedKey.minecraft("evoker_cast_spell")); ++ @Deprecated GoalKey FOX_DEFEND_TRUSTED = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_defend_trusted")); ++ @Deprecated GoalKey FOX_FACEPLANT = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_faceplant")); ++ @Deprecated GoalKey FOX_PERCH_AND_SEARCH = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_perch_and_search")); ++ @Deprecated GoalKey FOX_SLEEP = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_sleep")); ++ @Deprecated GoalKey FOX_SEEK_SHELTER = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_seek_shelter")); ++ @Deprecated GoalKey FOX_STALK_PREY = GoalKey.of(Fox.class, NamespacedKey.minecraft("fox_stalk_prey")); ++ @Deprecated GoalKey GHAST_ATTACK_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_attack_target")); ++ @Deprecated GoalKey GHAST_IDLE_MOVE = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_idle_move")); ++ @Deprecated GoalKey GHAST_MOVE_TOWARDS_TARGET = GoalKey.of(Ghast.class, NamespacedKey.minecraft("ghast_move_towards_target")); ++ @Deprecated GoalKey SPELLCASTER_CAST_SPELL = GoalKey.of(Spellcaster.class, NamespacedKey.minecraft("spellcaster_cast_spell")); ++ @Deprecated GoalKey LLAMATRADER_DEFENDED_WANDERING_TRADER = GoalKey.of(TraderLlama.class, NamespacedKey.minecraft("llamatrader_defended_wandering_trader")); ++ @Deprecated GoalKey PANDA_HURT_BY_TARGET = GoalKey.of(Panda.class, NamespacedKey.minecraft("panda_hurt_by_target")); ++ @Deprecated GoalKey POLARBEAR_ATTACK_PLAYERS = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_attack_players")); ++ @Deprecated GoalKey POLARBEAR_HURT_BY = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_hurt_by")); ++ @Deprecated GoalKey POLARBEAR_MELEE = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_melee")); ++ @Deprecated GoalKey POLARBEAR_PANIC = GoalKey.of(PolarBear.class, NamespacedKey.minecraft("polarbear_panic")); ++ @Deprecated GoalKey EAT_CARROTS = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("eat_carrots")); ++ @Deprecated GoalKey KILLER_RABBIT_MELEE_ATTACK = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("killer_rabbit_melee_attack")); ++ @Deprecated GoalKey RABBIT_AVOID_TARGET = GoalKey.of(Rabbit.class, NamespacedKey.minecraft("rabbit_avoid_target")); ++ @Deprecated GoalKey RAIDER_HOLD_GROUND = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_hold_ground")); ++ @Deprecated GoalKey RAIDER_OBTAIN_BANNER = GoalKey.of(Raider.class, NamespacedKey.minecraft("raider_obtain_banner")); ++ @Deprecated GoalKey SHULKER_DEFENSE = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_defense")); ++ @Deprecated GoalKey SHULKER_NEAREST = GoalKey.of(Shulker.class, NamespacedKey.minecraft("shulker_nearest")); ++ @Deprecated GoalKey SILVERFISH_HIDE_IN_BLOCK = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_hide_in_block")); ++ @Deprecated GoalKey SILVERFISH_WAKE_OTHERS = GoalKey.of(Silverfish.class, NamespacedKey.minecraft("silverfish_wake_others")); ++ @Deprecated GoalKey SLIME_IDLE = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_idle")); ++ @Deprecated GoalKey SLIME_NEAREST_PLAYER = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_nearest_player")); ++ @Deprecated GoalKey SLIME_RANDOM_JUMP = GoalKey.of(Slime.class, NamespacedKey.minecraft("slime_random_jump")); ++ @Deprecated GoalKey SPIDER_MELEE_ATTACK = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_melee_attack")); ++ @Deprecated GoalKey SPIDER_NEAREST_ATTACKABLE_TARGET = GoalKey.of(Spider.class, NamespacedKey.minecraft("spider_nearest_attackable_target")); ++ @Deprecated GoalKey SQUID = GoalKey.of(Squid.class, NamespacedKey.minecraft("squid")); ++ @Deprecated GoalKey TURTLE_GOTO_WATER = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_goto_water")); ++ @Deprecated GoalKey TURTLE_TEMPT = GoalKey.of(Turtle.class, NamespacedKey.minecraft("turtle_tempt")); ++ @Deprecated GoalKey VEX_COPY_TARGET_OF_OWNER = GoalKey.of(Vex.class, NamespacedKey.minecraft("vex_copy_target_of_owner")); ++ @Deprecated GoalKey VILLAGERTRADER_WANDER_TO_POSITION = GoalKey.of(WanderingTrader.class, NamespacedKey.minecraft("villagertrader_wander_to_position")); ++ @Deprecated GoalKey ARROW_ATTACK = GoalKey.of(RangedEntity.class, NamespacedKey.minecraft("arrow_attack")); ++ @Deprecated GoalKey AVOID_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("avoid_target")); ++ @Deprecated GoalKey BOW_SHOOT = GoalKey.of(Monster.class, NamespacedKey.minecraft("bow_shoot")); ++ @Deprecated GoalKey BREATH = GoalKey.of(Creature.class, NamespacedKey.minecraft("breath")); ++ @Deprecated GoalKey CAT_SIT_ON_BED = GoalKey.of(Cat.class, NamespacedKey.minecraft("cat_sit_on_bed")); ++ @Deprecated GoalKey CROSSBOW_ATTACK = GoalKey.of(Monster.class, NamespacedKey.minecraft("crossbow_attack")); ++ @Deprecated GoalKey DOOR_OPEN = GoalKey.of(Mob.class, NamespacedKey.minecraft("door_open")); ++ @Deprecated GoalKey EAT_TILE = GoalKey.of(Mob.class, NamespacedKey.minecraft("eat_tile")); ++ @Deprecated GoalKey FISH_SCHOOL = GoalKey.of(Fish.class, NamespacedKey.minecraft("fish_school")); ++ @Deprecated GoalKey FOLLOW_ENTITY = GoalKey.of(Mob.class, NamespacedKey.minecraft("follow_entity")); ++ @Deprecated GoalKey HORSE_TRAP = GoalKey.of(SkeletonHorse.class, NamespacedKey.minecraft("horse_trap")); ++ @Deprecated GoalKey HURT_BY_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("hurt_by_target")); ++ @Deprecated GoalKey JUMP_ON_BLOCK = GoalKey.of(Cat.class, NamespacedKey.minecraft("jump_on_block")); ++ @Deprecated GoalKey LEAP_AT_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("leap_at_target")); ++ @Deprecated GoalKey LLAMA_FOLLOW = GoalKey.of(Llama.class, NamespacedKey.minecraft("llama_follow")); ++ @Deprecated GoalKey MOVE_TOWARDS_TARGET = GoalKey.of(Creature.class, NamespacedKey.minecraft("move_towards_target")); ++ @Deprecated GoalKey NEAREST_ATTACKABLE_TARGET = GoalKey.of(Mob.class, NamespacedKey.minecraft("nearest_attackable_target")); ++ @Deprecated GoalKey NEAREST_ATTACKABLE_TARGET_WITCH = GoalKey.of(Raider.class, NamespacedKey.minecraft("nearest_attackable_target_witch")); ++ @Deprecated GoalKey NEAREST_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("nearest_village")); ++ @Deprecated GoalKey OWNER_HURT_BY_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_by_target")); ++ @Deprecated GoalKey OWNER_HURT_TARGET = GoalKey.of(Tameable.class, NamespacedKey.minecraft("owner_hurt_target")); ++ @Deprecated GoalKey PERCH = GoalKey.of(Parrot.class, NamespacedKey.minecraft("perch")); ++ @Deprecated GoalKey RAID = GoalKey.of(Raider.class, NamespacedKey.minecraft("raid")); ++ @Deprecated GoalKey RANDOM_FLY = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_fly")); ++ @Deprecated GoalKey RANDOM_LOOKAROUND = GoalKey.of(Mob.class, NamespacedKey.minecraft("random_lookaround")); ++ @Deprecated GoalKey RANDOM_STROLL_LAND = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_stroll_land")); ++ @Deprecated GoalKey RANDOM_SWIM = GoalKey.of(Creature.class, NamespacedKey.minecraft("random_swim")); ++ @Deprecated GoalKey RANDOM_TARGET_NON_TAMED = GoalKey.of(Tameable.class, NamespacedKey.minecraft("random_target_non_tamed")); ++ @Deprecated GoalKey SIT = GoalKey.of(Tameable.class, NamespacedKey.minecraft("sit")); ++ @Deprecated GoalKey STROLL_VILLAGE = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village")); ++ @Deprecated GoalKey TAME = GoalKey.of(AbstractHorse.class, NamespacedKey.minecraft("tame")); ++ @Deprecated GoalKey WATER = GoalKey.of(Creature.class, NamespacedKey.minecraft("water")); ++ @Deprecated GoalKey WATER_JUMP = GoalKey.of(Dolphin.class, NamespacedKey.minecraft("water_jump")); ++ @Deprecated GoalKey STROLL_VILLAGE_GOLEM = GoalKey.of(Creature.class, NamespacedKey.minecraft("stroll_village_golem")); ++ @Deprecated GoalKey UNIVERSAL_ANGER_RESET = GoalKey.of(Mob.class, NamespacedKey.minecraft("universal_anger_reset")); +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/Spigot-API-Patches/Add-Mob-lookAt-API.patch b/patches/api/Add-Mob-lookAt-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Mob-lookAt-API.patch rename to patches/api/Add-Mob-lookAt-API.patch diff --git a/Spigot-API-Patches/Add-More-Creeper-API.patch b/patches/api/Add-More-Creeper-API.patch similarity index 100% rename from Spigot-API-Patches/Add-More-Creeper-API.patch rename to patches/api/Add-More-Creeper-API.patch diff --git a/Spigot-API-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/api/Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from Spigot-API-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/api/Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/Spigot-API-Patches/Add-PhantomPreSpawnEvent.patch b/patches/api/Add-PhantomPreSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PhantomPreSpawnEvent.patch rename to patches/api/Add-PhantomPreSpawnEvent.patch diff --git a/Spigot-API-Patches/Add-Player-Client-Options-API.patch b/patches/api/Add-Player-Client-Options-API.patch similarity index 100% rename from Spigot-API-Patches/Add-Player-Client-Options-API.patch rename to patches/api/Add-Player-Client-Options-API.patch diff --git a/Spigot-API-Patches/Add-PlayerArmorChangeEvent.patch b/patches/api/Add-PlayerArmorChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerArmorChangeEvent.patch rename to patches/api/Add-PlayerArmorChangeEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/api/Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/api/Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerConnectionCloseEvent.patch b/patches/api/Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerConnectionCloseEvent.patch rename to patches/api/Add-PlayerConnectionCloseEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerFlowerPotManipulateEvent.patch b/patches/api/Add-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerFlowerPotManipulateEvent.patch rename to patches/api/Add-PlayerFlowerPotManipulateEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerInitialSpawnEvent.patch b/patches/api/Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerInitialSpawnEvent.patch rename to patches/api/Add-PlayerInitialSpawnEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerItemCooldownEvent.patch b/patches/api/Add-PlayerItemCooldownEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerItemCooldownEvent.patch rename to patches/api/Add-PlayerItemCooldownEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerJumpEvent.patch b/patches/api/Add-PlayerJumpEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerJumpEvent.patch rename to patches/api/Add-PlayerJumpEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerKickEvent-causes.patch b/patches/api/Add-PlayerKickEvent-causes.patch similarity index 99% rename from Spigot-API-Patches/Add-PlayerKickEvent-causes.patch rename to patches/api/Add-PlayerKickEvent-causes.patch index 11a7219daf..09e9defe67 100644 --- a/Spigot-API-Patches/Add-PlayerKickEvent-causes.patch +++ b/patches/api/Add-PlayerKickEvent-causes.patch @@ -114,6 +114,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + DUPLICATE_LOGIN, + ++ RESOURCE_PACK_REJECTION, ++ + /** + * Spigot's restart command + */ diff --git a/Spigot-API-Patches/Add-PlayerLocaleChangeEvent.patch b/patches/api/Add-PlayerLocaleChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerLocaleChangeEvent.patch rename to patches/api/Add-PlayerLocaleChangeEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerPostRespawnEvent.patch b/patches/api/Add-PlayerPostRespawnEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerPostRespawnEvent.patch rename to patches/api/Add-PlayerPostRespawnEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerShearBlockEvent.patch b/patches/api/Add-PlayerShearBlockEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerShearBlockEvent.patch rename to patches/api/Add-PlayerShearBlockEvent.patch diff --git a/Spigot-API-Patches/Add-PlayerUseUnknownEntityEvent.patch b/patches/api/Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PlayerUseUnknownEntityEvent.patch rename to patches/api/Add-PlayerUseUnknownEntityEvent.patch diff --git a/Spigot-API-Patches/Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/patches/api/Add-PrepareResultEvent-PrepareGrindstoneEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PrepareResultEvent-PrepareGrindstoneEvent.patch rename to patches/api/Add-PrepareResultEvent-PrepareGrindstoneEvent.patch diff --git a/Spigot-API-Patches/Add-ProjectileCollideEvent.patch b/patches/api/Add-ProjectileCollideEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-ProjectileCollideEvent.patch rename to patches/api/Add-ProjectileCollideEvent.patch diff --git a/Spigot-API-Patches/Add-PufferFishStateChangeEvent.patch b/patches/api/Add-PufferFishStateChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-PufferFishStateChangeEvent.patch rename to patches/api/Add-PufferFishStateChangeEvent.patch diff --git a/Spigot-API-Patches/Add-Raw-Byte-ItemStack-Serialization.patch b/patches/api/Add-Raw-Byte-ItemStack-Serialization.patch similarity index 100% rename from Spigot-API-Patches/Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/api/Add-Raw-Byte-ItemStack-Serialization.patch diff --git a/Spigot-API-Patches/Add-String-based-Action-Bar-API.patch b/patches/api/Add-String-based-Action-Bar-API.patch similarity index 100% rename from Spigot-API-Patches/Add-String-based-Action-Bar-API.patch rename to patches/api/Add-String-based-Action-Bar-API.patch diff --git a/Spigot-API-Patches/Add-StructureLocateEvent.patch b/patches/api/Add-StructureLocateEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-StructureLocateEvent.patch rename to patches/api/Add-StructureLocateEvent.patch diff --git a/Spigot-API-Patches/Add-TNTPrimeEvent.patch b/patches/api/Add-TNTPrimeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-TNTPrimeEvent.patch rename to patches/api/Add-TNTPrimeEvent.patch diff --git a/Spigot-API-Patches/Add-TargetHitEvent-API.patch b/patches/api/Add-TargetHitEvent-API.patch similarity index 100% rename from Spigot-API-Patches/Add-TargetHitEvent-API.patch rename to patches/api/Add-TargetHitEvent-API.patch diff --git a/Spigot-API-Patches/Add-ThrownEggHatchEvent.patch b/patches/api/Add-ThrownEggHatchEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-ThrownEggHatchEvent.patch rename to patches/api/Add-ThrownEggHatchEvent.patch diff --git a/Spigot-API-Patches/Add-UnknownCommandEvent.patch b/patches/api/Add-UnknownCommandEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-UnknownCommandEvent.patch rename to patches/api/Add-UnknownCommandEvent.patch diff --git a/Spigot-API-Patches/Add-WhitelistToggleEvent.patch b/patches/api/Add-WhitelistToggleEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-WhitelistToggleEvent.patch rename to patches/api/Add-WhitelistToggleEvent.patch diff --git a/Spigot-API-Patches/Add-World.getEntity-UUID-API.patch b/patches/api/Add-World.getEntity-UUID-API.patch similarity index 100% rename from Spigot-API-Patches/Add-World.getEntity-UUID-API.patch rename to patches/api/Add-World.getEntity-UUID-API.patch diff --git a/Spigot-API-Patches/Add-a-call-helper-to-Event.patch b/patches/api/Add-a-call-helper-to-Event.patch similarity index 100% rename from Spigot-API-Patches/Add-a-call-helper-to-Event.patch rename to patches/api/Add-a-call-helper-to-Event.patch diff --git a/Spigot-API-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/api/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 94% rename from Spigot-API-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/api/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch index 8d495850c0..26b92f8cb4 100644 --- a/Spigot-API-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ b/patches/api/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -33,7 +33,7 @@ diff --git a/src/main/java/org/bukkit/entity/Skeleton.java b/src/main/java/org/b index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/entity/Skeleton.java +++ b/src/main/java/org/bukkit/entity/Skeleton.java -@@ -0,0 +0,0 @@ public interface Skeleton extends Monster, RangedEntity { // Paper +@@ -0,0 +0,0 @@ public interface Skeleton extends AbstractSkeleton, com.destroystokyo.paper.enti */ STRAY; } diff --git a/Spigot-API-Patches/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/api/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 patches/api/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch diff --git a/Spigot-API-Patches/Add-additional-open-container-api-to-HumanEntity.patch b/patches/api/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 patches/api/Add-additional-open-container-api-to-HumanEntity.patch diff --git a/Spigot-API-Patches/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/api/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 patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch diff --git a/Spigot-API-Patches/Add-an-asterisk-to-legacy-API-plugins.patch b/patches/api/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 patches/api/Add-an-asterisk-to-legacy-API-plugins.patch diff --git a/Spigot-API-Patches/Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/api/Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/api/Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/Spigot-API-Patches/Add-basic-Datapack-API.patch b/patches/api/Add-basic-Datapack-API.patch similarity index 100% rename from Spigot-API-Patches/Add-basic-Datapack-API.patch rename to patches/api/Add-basic-Datapack-API.patch diff --git a/Spigot-API-Patches/Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/api/Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from Spigot-API-Patches/Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/api/Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/Spigot-API-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api/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 patches/api/Add-command-line-option-to-load-extra-plugin-jars-no.patch diff --git a/Spigot-API-Patches/Add-command-to-reload-permissions.yml-and-require-co.patch b/patches/api/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 patches/api/Add-command-to-reload-permissions.yml-and-require-co.patch diff --git a/Spigot-API-Patches/Add-configuration-option-to-prevent-player-names-fro.patch b/patches/api/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 patches/api/Add-configuration-option-to-prevent-player-names-fro.patch diff --git a/Spigot-API-Patches/Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/api/Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/api/Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/Spigot-API-Patches/Add-effect-to-block-break-naturally.patch b/patches/api/Add-effect-to-block-break-naturally.patch similarity index 100% rename from Spigot-API-Patches/Add-effect-to-block-break-naturally.patch rename to patches/api/Add-effect-to-block-break-naturally.patch diff --git a/Spigot-API-Patches/Add-entity-liquid-API.patch b/patches/api/Add-entity-liquid-API.patch similarity index 100% rename from Spigot-API-Patches/Add-entity-liquid-API.patch rename to patches/api/Add-entity-liquid-API.patch diff --git a/Spigot-API-Patches/Add-exception-reporting-event.patch b/patches/api/Add-exception-reporting-event.patch similarity index 100% rename from Spigot-API-Patches/Add-exception-reporting-event.patch rename to patches/api/Add-exception-reporting-event.patch diff --git a/Spigot-API-Patches/Add-extended-PaperServerListPingEvent.patch b/patches/api/Add-extended-PaperServerListPingEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-extended-PaperServerListPingEvent.patch rename to patches/api/Add-extended-PaperServerListPingEvent.patch diff --git a/Spigot-API-Patches/Add-getI18NDisplayName-API.patch b/patches/api/Add-getI18NDisplayName-API.patch similarity index 90% rename from Spigot-API-Patches/Add-getI18NDisplayName-API.patch rename to patches/api/Add-getI18NDisplayName-API.patch index ab34aeefde..bc3a4e72e8 100644 --- a/Spigot-API-Patches/Add-getI18NDisplayName-API.patch +++ b/patches/api/Add-getI18NDisplayName-API.patch @@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public interface ItemFactory { */ @NotNull - ItemStack ensureServerConversions(@NotNull ItemStack item); + net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); + + /** + * Gets the Display name as seen in the Client. @@ -33,8 +33,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -0,0 +0,0 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public ItemStack ensureServerConversions() { - return Bukkit.getServer().getItemFactory().ensureServerConversions(this); + public @NotNull net.kyori.adventure.text.Component displayName() { + return Bukkit.getServer().getItemFactory().displayName(this); } + + /** diff --git a/Spigot-API-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/api/Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from Spigot-API-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/api/Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/Spigot-API-Patches/Add-getNearbyXXX-methods-to-Location.patch b/patches/api/Add-getNearbyXXX-methods-to-Location.patch similarity index 100% rename from Spigot-API-Patches/Add-getNearbyXXX-methods-to-Location.patch rename to patches/api/Add-getNearbyXXX-methods-to-Location.patch diff --git a/Spigot-API-Patches/Add-getOfflinePlayerIfCached-String.patch b/patches/api/Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from Spigot-API-Patches/Add-getOfflinePlayerIfCached-String.patch rename to patches/api/Add-getOfflinePlayerIfCached-String.patch diff --git a/Spigot-API-Patches/Add-getTPS-method.patch b/patches/api/Add-getTPS-method.patch similarity index 100% rename from Spigot-API-Patches/Add-getTPS-method.patch rename to patches/api/Add-getTPS-method.patch diff --git a/Spigot-API-Patches/Add-hand-to-bucket-events.patch b/patches/api/Add-hand-to-bucket-events.patch similarity index 100% rename from Spigot-API-Patches/Add-hand-to-bucket-events.patch rename to patches/api/Add-hand-to-bucket-events.patch diff --git a/Spigot-API-Patches/Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/api/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 patches/api/Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/Spigot-API-Patches/Add-ignore-discounts-API.patch b/patches/api/Add-ignore-discounts-API.patch similarity index 100% rename from Spigot-API-Patches/Add-ignore-discounts-API.patch rename to patches/api/Add-ignore-discounts-API.patch diff --git a/Spigot-API-Patches/Add-item-slot-convenience-methods.patch b/patches/api/Add-item-slot-convenience-methods.patch similarity index 100% rename from Spigot-API-Patches/Add-item-slot-convenience-methods.patch rename to patches/api/Add-item-slot-convenience-methods.patch diff --git a/Spigot-API-Patches/Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/patches/api/Add-legacy-ping-support-to-PaperServerListPingEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-legacy-ping-support-to-PaperServerListPingEvent.patch rename to patches/api/Add-legacy-ping-support-to-PaperServerListPingEvent.patch diff --git a/Spigot-API-Patches/Add-method-to-open-already-placed-sign.patch b/patches/api/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 patches/api/Add-method-to-open-already-placed-sign.patch diff --git a/Spigot-API-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/api/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 patches/api/Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/Spigot-API-Patches/Add-missing-effects.patch b/patches/api/Add-missing-effects.patch similarity index 100% rename from Spigot-API-Patches/Add-missing-effects.patch rename to patches/api/Add-missing-effects.patch diff --git a/Spigot-API-Patches/Add-moon-phase-API.patch b/patches/api/Add-moon-phase-API.patch similarity index 100% rename from Spigot-API-Patches/Add-moon-phase-API.patch rename to patches/api/Add-moon-phase-API.patch diff --git a/Spigot-API-Patches/Add-more-Evoker-API.patch b/patches/api/Add-more-Evoker-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-Evoker-API.patch rename to patches/api/Add-more-Evoker-API.patch diff --git a/Spigot-API-Patches/Add-more-WanderingTrader-API.patch b/patches/api/Add-more-WanderingTrader-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-WanderingTrader-API.patch rename to patches/api/Add-more-WanderingTrader-API.patch diff --git a/Spigot-API-Patches/Add-more-Witch-API.patch b/patches/api/Add-more-Witch-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-Witch-API.patch rename to patches/api/Add-more-Witch-API.patch diff --git a/Spigot-API-Patches/Add-more-Zombie-API.patch b/patches/api/Add-more-Zombie-API.patch similarity index 100% rename from Spigot-API-Patches/Add-more-Zombie-API.patch rename to patches/api/Add-more-Zombie-API.patch diff --git a/Spigot-API-Patches/Add-more-line-of-sight-methods.patch b/patches/api/Add-more-line-of-sight-methods.patch similarity index 100% rename from Spigot-API-Patches/Add-more-line-of-sight-methods.patch rename to patches/api/Add-more-line-of-sight-methods.patch diff --git a/Spigot-API-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/api/Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 100% rename from Spigot-API-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/api/Add-playPickupItemAnimation-to-LivingEntity.patch diff --git a/Spigot-API-Patches/Add-player-view-distance-API.patch b/patches/api/Add-player-view-distance-API.patch similarity index 100% rename from Spigot-API-Patches/Add-player-view-distance-API.patch rename to patches/api/Add-player-view-distance-API.patch diff --git a/Spigot-API-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/api/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/api/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/Spigot-API-Patches/Add-ray-tracing-methods-to-LivingEntity.patch b/patches/api/Add-ray-tracing-methods-to-LivingEntity.patch similarity index 100% rename from Spigot-API-Patches/Add-ray-tracing-methods-to-LivingEntity.patch rename to patches/api/Add-ray-tracing-methods-to-LivingEntity.patch diff --git a/Spigot-API-Patches/Add-recipe-to-cook-events.patch b/patches/api/Add-recipe-to-cook-events.patch similarity index 100% rename from Spigot-API-Patches/Add-recipe-to-cook-events.patch rename to patches/api/Add-recipe-to-cook-events.patch diff --git a/Spigot-API-Patches/Add-sendOpLevel-API.patch b/patches/api/Add-sendOpLevel-API.patch similarity index 100% rename from Spigot-API-Patches/Add-sendOpLevel-API.patch rename to patches/api/Add-sendOpLevel-API.patch diff --git a/Spigot-API-Patches/Add-sender-name-to-commands.yml-replacement.patch b/patches/api/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 patches/api/Add-sender-name-to-commands.yml-replacement.patch diff --git a/Spigot-API-Patches/Add-setMaxPlayers-API.patch b/patches/api/Add-setMaxPlayers-API.patch similarity index 100% rename from Spigot-API-Patches/Add-setMaxPlayers-API.patch rename to patches/api/Add-setMaxPlayers-API.patch diff --git a/Spigot-API-Patches/Add-setPlayerProfile-API-for-Skulls.patch b/patches/api/Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from Spigot-API-Patches/Add-setPlayerProfile-API-for-Skulls.patch rename to patches/api/Add-setPlayerProfile-API-for-Skulls.patch diff --git a/Spigot-API-Patches/Add-source-block-to-BlockPhysicsEvent.patch b/patches/api/Add-source-block-to-BlockPhysicsEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-source-block-to-BlockPhysicsEvent.patch rename to patches/api/Add-source-block-to-BlockPhysicsEvent.patch diff --git a/Spigot-API-Patches/Add-source-to-PlayerExpChangeEvent.patch b/patches/api/Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Add-source-to-PlayerExpChangeEvent.patch rename to patches/api/Add-source-to-PlayerExpChangeEvent.patch diff --git a/Spigot-API-Patches/Add-spectator-target-events.patch b/patches/api/Add-spectator-target-events.patch similarity index 100% rename from Spigot-API-Patches/Add-spectator-target-events.patch rename to patches/api/Add-spectator-target-events.patch diff --git a/Spigot-API-Patches/Add-sun-related-API.patch b/patches/api/Add-sun-related-API.patch similarity index 100% rename from Spigot-API-Patches/Add-sun-related-API.patch rename to patches/api/Add-sun-related-API.patch diff --git a/Spigot-API-Patches/Add-tick-times-API.patch b/patches/api/Add-tick-times-API.patch similarity index 100% rename from Spigot-API-Patches/Add-tick-times-API.patch rename to patches/api/Add-tick-times-API.patch diff --git a/Spigot-API-Patches/Add-villager-reputation-API.patch b/patches/api/Add-villager-reputation-API.patch similarity index 100% rename from Spigot-API-Patches/Add-villager-reputation-API.patch rename to patches/api/Add-villager-reputation-API.patch diff --git a/Spigot-API-Patches/Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api/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 patches/api/Add-workaround-for-plugins-modifying-the-parent-of-t.patch diff --git a/Spigot-API-Patches/Add-worldborder-events.patch b/patches/api/Add-worldborder-events.patch similarity index 100% rename from Spigot-API-Patches/Add-worldborder-events.patch rename to patches/api/Add-worldborder-events.patch diff --git a/Spigot-API-Patches/Added-PlayerBedFailEnterEvent.patch b/patches/api/Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerBedFailEnterEvent.patch rename to patches/api/Added-PlayerBedFailEnterEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerChangeBeaconEffectEvent.patch b/patches/api/Added-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerChangeBeaconEffectEvent.patch rename to patches/api/Added-PlayerChangeBeaconEffectEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerDeepSleepEvent.patch b/patches/api/Added-PlayerDeepSleepEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerDeepSleepEvent.patch rename to patches/api/Added-PlayerDeepSleepEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerLecternPageChangeEvent.patch b/patches/api/Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerLecternPageChangeEvent.patch rename to patches/api/Added-PlayerLecternPageChangeEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerLoomPatternSelectEvent.patch b/patches/api/Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerLoomPatternSelectEvent.patch rename to patches/api/Added-PlayerLoomPatternSelectEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/api/Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/api/Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/Spigot-API-Patches/Added-PlayerTradeEvent.patch b/patches/api/Added-PlayerTradeEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-PlayerTradeEvent.patch rename to patches/api/Added-PlayerTradeEvent.patch diff --git a/Spigot-API-Patches/Added-ServerResourcesReloadedEvent.patch b/patches/api/Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-ServerResourcesReloadedEvent.patch rename to patches/api/Added-ServerResourcesReloadedEvent.patch diff --git a/Spigot-API-Patches/Added-Vanilla-Entity-Tags.patch b/patches/api/Added-Vanilla-Entity-Tags.patch similarity index 100% rename from Spigot-API-Patches/Added-Vanilla-Entity-Tags.patch rename to patches/api/Added-Vanilla-Entity-Tags.patch diff --git a/Spigot-API-Patches/Added-WorldGameRuleChangeEvent.patch b/patches/api/Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/Added-WorldGameRuleChangeEvent.patch rename to patches/api/Added-WorldGameRuleChangeEvent.patch diff --git a/Spigot-API-Patches/Additional-Block-Material-API-s.patch b/patches/api/Additional-Block-Material-API-s.patch similarity index 100% rename from Spigot-API-Patches/Additional-Block-Material-API-s.patch rename to patches/api/Additional-Block-Material-API-s.patch diff --git a/Spigot-API-Patches/Additional-world.getNearbyEntities-API-s.patch b/patches/api/Additional-world.getNearbyEntities-API-s.patch similarity index 100% rename from Spigot-API-Patches/Additional-world.getNearbyEntities-API-s.patch rename to patches/api/Additional-world.getNearbyEntities-API-s.patch diff --git a/Spigot-API-Patches/Adventure.patch b/patches/api/Adventure.patch similarity index 89% rename from Spigot-API-Patches/Adventure.patch rename to patches/api/Adventure.patch index 0686342eed..ce7674aaa8 100644 --- a/Spigot-API-Patches/Adventure.patch +++ b/patches/api/Adventure.patch @@ -6,71 +6,22 @@ Subject: [PATCH] Adventure Co-authored-by: zml Co-authored-by: Jake Potrebic -diff --git a/pom.xml b/pom.xml +diff --git a/build.gradle.kts b/build.gradle.kts index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - 1.8 - 1.8 - UTF-8 -+ 4.7.0 - +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + api("org.yaml:snakeyaml:1.28") + api("com.googlecode.json-simple:json-simple:1.1.1") // Paper + api("it.unimi.dsi:fastutil:8.2.2") ++ api(platform("net.kyori:adventure-bom:4.8.1")) ++ api("net.kyori:adventure-api") ++ api("net.kyori:adventure-text-serializer-gson") ++ api("net.kyori:adventure-text-serializer-legacy") ++ api("net.kyori:adventure-text-serializer-plain") - -@@ -0,0 +0,0 @@ - - - -+ -+ -+ -+ -+ net.kyori -+ adventure-bom -+ ${adventure.version} -+ pom -+ import -+ -+ -+ -+ -+ - -+ -+ -+ net.kyori -+ adventure-api -+ -+ -+ net.kyori -+ adventure-text-serializer-gson -+ -+ -+ net.kyori -+ adventure-text-serializer-legacy -+ -+ -+ net.kyori -+ adventure-text-serializer-plain -+ -+ - - it.unimi.dsi - fastutil -@@ -0,0 +0,0 @@ - https://javadoc.io/doc/org.yaml/snakeyaml/1.27/ - https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/ - https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/ -+ -+ https://jd.adventure.kyori.net/api/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-gson/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-legacy/${adventure.version}/ -+ https://jd.adventure.kyori.net/text-serializer-plain/${adventure.version}/ -+ - - - + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/src/main/java/co/aikar/timings/TimingsReportListener.java b/src/main/java/co/aikar/timings/TimingsReportListener.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/co/aikar/timings/TimingsReportListener.java @@ -102,76 +53,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end } -diff --git a/src/main/java/io/papermc/paper/chat/ChatComposer.java b/src/main/java/io/papermc/paper/chat/ChatComposer.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/chat/ChatComposer.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.chat; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A chat composer is responsible for composing chat messages sent by {@link Player}s to the server. -+ * -+ * @deprecated for removal with 1.17, in favor of {@link ChatRenderer} -+ */ -+@Deprecated -+@FunctionalInterface -+public interface ChatComposer { -+ ChatComposer DEFAULT = (player, displayName, message) -> Component.translatable("chat.type.text", displayName, message); -+ -+ /** -+ * Composes a chat message. -+ * -+ * @param source the message source -+ * @param displayName the display name of the {@link Player} sending the message -+ * @param message the chat message -+ * @return a composed chat message -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ @NotNull -+ Component composeChat(final @NotNull Player source, final @NotNull Component displayName, final @NotNull Component message); -+} -diff --git a/src/main/java/io/papermc/paper/chat/ChatFormatter.java b/src/main/java/io/papermc/paper/chat/ChatFormatter.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/chat/ChatFormatter.java -@@ -0,0 +0,0 @@ -+package io.papermc.paper.chat; -+ -+import net.kyori.adventure.text.Component; -+import org.bukkit.entity.Player; -+import org.jetbrains.annotations.NotNull; -+ -+/** -+ * A chat formatter is responsible for the formatting of chat messages sent by {@link Player}s to the server. -+ * -+ * @deprecated for removal with 1.17, in favour of {@link ChatRenderer} -+ */ -+@Deprecated -+@FunctionalInterface -+public interface ChatFormatter { -+ @Deprecated -+ ChatFormatter DEFAULT = (displayName, message) -> Component.translatable("chat.type.text", displayName, message); -+ -+ /** -+ * Formats a chat message. -+ * -+ * @param displayName the display name of the {@link Player} sending the message -+ * @param message the chat message -+ * @return a formatted chat message -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ @NotNull -+ Component chat(final @NotNull Component displayName, final @NotNull Component message); -+} diff --git a/src/main/java/io/papermc/paper/chat/ChatRenderer.java b/src/main/java/io/papermc/paper/chat/ChatRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -261,20 +142,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.event.player; + -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; -+import java.util.HashSet; +import java.util.Set; +import io.papermc.paper.chat.ChatRenderer; +import net.kyori.adventure.audience.Audience; -+import net.kyori.adventure.audience.ForwardingAudience; +import net.kyori.adventure.text.Component; -+import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.player.PlayerEvent; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.NotNull; + +import static java.util.Objects.requireNonNull; @@ -284,93 +158,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ +public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable { + private final Set viewers; -+ @Deprecated private final Set recipients; -+ private boolean cancelled = false; -+ private ChatRenderer renderer; -+ @Deprecated private @Nullable ChatComposer composer; -+ @Deprecated private @Nullable ChatFormatter formatter; + private final Component originalMessage; ++ private ChatRenderer renderer; + private Component message; ++ private boolean cancelled = false; + + AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { + super(player, async); + this.viewers = viewers; -+ this.recipients = new HashSet<>(Bukkit.getOnlinePlayers()); + this.renderer = renderer; + this.message = message; + this.originalMessage = originalMessage; + } + + /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(player, async); -+ this.viewers = viewers; -+ this.recipients = new HashSet<>(Bukkit.getOnlinePlayers()); -+ this.renderer = renderer; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(player, async); -+ this.recipients = recipients; -+ this.viewers = viewers; -+ this.renderer = renderer; -+ this.message = message; -+ this.originalMessage = originalMessage; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ this.viewers = viewers; -+ this.renderer = renderer; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ final Set audiences = new HashSet<>(recipients); -+ audiences.add(Bukkit.getConsoleSender()); -+ this.viewers = audiences; -+ this.composer = composer; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** -+ * @deprecated for removal with 1.17 -+ */ -+ @Deprecated -+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(player, async); -+ this.recipients = recipients; -+ final Set audiences = new HashSet<>(recipients); -+ audiences.add(Bukkit.getConsoleSender()); -+ this.viewers = audiences; -+ this.formatter = formatter; -+ this.message = message; -+ this.originalMessage = message; -+ } -+ -+ /** + * Gets a set of {@link Audience audiences} that this chat message will be displayed to. + * + *

The set returned is not guaranteed to be mutable and may auto-populate @@ -389,26 +190,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + /** -+ * Gets a set of recipients that this chat message will be displayed to. -+ * -+ *

The set returned is not guaranteed to be mutable and may auto-populate -+ * on access. Any listener accessing the returned set should be aware that -+ * it may reduce performance for a lazy set implementation.

-+ * -+ *

Listeners should be aware that modifying the list may throw {@link -+ * UnsupportedOperationException} if the event caller provides an -+ * unmodifiable set.

-+ * -+ * @return a set of players who will receive the chat message -+ * @deprecated for removal with 1.17, in favor of {@link #viewers()} -+ */ -+ @Deprecated -+ @NotNull -+ public final Set recipients() { -+ return this.recipients; -+ } -+ -+ /** + * Sets the chat renderer. + * + * @param renderer the chat renderer @@ -416,8 +197,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ + public final void renderer(final @NotNull ChatRenderer renderer) { + this.renderer = requireNonNull(renderer, "renderer"); -+ this.formatter = null; -+ this.composer = null; + } + + /** @@ -427,86 +206,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ + @NotNull + public final ChatRenderer renderer() { -+ if(this.renderer == null) { -+ if(this.composer != null) { -+ this.renderer = ChatRenderer.viewerUnaware((source, displayName, message) -> this.composer.composeChat(source, source.displayName(), message)); -+ } else { -+ requireNonNull(this.formatter, "renderer, composer, and formatter"); -+ this.renderer = ChatRenderer.viewerUnaware((source, displayName, message) -> this.formatter.chat(source.displayName(), message)); -+ } -+ } + return this.renderer; + } + + /** -+ * Gets the chat composer. -+ * -+ * @return the chat composer -+ * @deprecated for removal with 1.17, in favour of {@link #renderer()} -+ */ -+ @Deprecated -+ @NotNull -+ public final ChatComposer composer() { -+ if(this.composer == null) { -+ if(this.renderer != null) { -+ this.composer = (source, displayName, message) -> this.renderer.render(source, displayName, message, this.legacyForwardingAudience()); -+ } else { -+ requireNonNull(this.formatter, "renderer, composer, and formatter"); -+ this.composer = (source, displayName, message) -> this.formatter.chat(displayName, message); -+ } -+ } -+ return this.composer; -+ } -+ -+ /** -+ * Sets the chat composer. -+ * -+ * @param composer the chat composer -+ * @throws NullPointerException if {@code composer} is {@code null} -+ * @deprecated for removal with 1.17, in favour of {@link #renderer(ChatRenderer)} -+ */ -+ @Deprecated -+ public final void composer(final @NotNull ChatComposer composer) { -+ this.composer = requireNonNull(composer, "composer"); -+ this.formatter = null; -+ this.renderer = null; -+ } -+ -+ /** -+ * Gets the chat formatter. -+ * -+ * @return the chat formatter -+ * @deprecated for removal with 1.17, in favour of {@link #renderer()} -+ */ -+ @Deprecated -+ @NotNull -+ public final ChatFormatter formatter() { -+ if(this.formatter == null) { -+ if(this.renderer != null) { -+ this.formatter = (displayName, message) -> this.renderer.render(this.player, displayName, message, this.legacyForwardingAudience()); -+ } else { -+ requireNonNull(this.composer, "renderer, composer, and formatter"); -+ this.formatter = (displayName, message) -> this.composer.composeChat(this.player, displayName, message); -+ } -+ } -+ return this.formatter; -+ } -+ -+ /** -+ * Sets the chat formatter. -+ * -+ * @param formatter the chat formatter -+ * @throws NullPointerException if {@code formatter} is {@code null} -+ * @deprecated for removal with 1.17, in favour of {@link #renderer(ChatRenderer)} -+ */ -+ @Deprecated -+ public final void formatter(final @NotNull ChatFormatter formatter) { -+ this.formatter = requireNonNull(formatter, "formatter"); -+ this.composer = null; -+ this.renderer = null; -+ } -+ -+ /** + * Gets the user-supplied message. + * The return value will reflect changes made using {@link #message(Component)}. + * @@ -548,15 +251,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public final void setCancelled(final boolean cancelled) { + this.cancelled = cancelled; + } -+ -+ private @NotNull Audience legacyForwardingAudience() { -+ return new ForwardingAudience() { -+ @Override -+ public @NonNull Iterable audiences() { -+ return AbstractChatEvent.this.viewers; -+ } -+ }; -+ } +} diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java new file mode 100644 @@ -566,8 +260,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.event.player; + -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; +import java.util.Set; +import io.papermc.paper.chat.ChatRenderer; +import net.kyori.adventure.audience.Audience; @@ -586,46 +278,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + super(async, player, viewers, renderer, message, originalMessage); + } + -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(async, player, viewers, renderer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(async, player, recipients, viewers, renderer, message, originalMessage); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(async, player, recipients, viewers, renderer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(async, player, recipients, composer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #AsyncChatEvent(boolean, Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(async, player, recipients, formatter, message); -+ } -+ + @NotNull + @Override + public HandlerList getHandlers() { @@ -645,8 +297,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.event.player; + -+import io.papermc.paper.chat.ChatComposer; -+import io.papermc.paper.chat.ChatFormatter; +import java.util.Set; +import io.papermc.paper.chat.ChatRenderer; +import net.kyori.adventure.audience.Audience; @@ -670,38 +320,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + super(false, player, viewers, renderer, message, originalMessage); + } + -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message) { -+ super(false, player, viewers, renderer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull Set viewers, final @NotNull ChatRenderer renderer, final @NotNull Component message, final @NotNull Component originalMessage) { -+ super(false, player, recipients, viewers, renderer, message, originalMessage); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatComposer composer, final @NotNull Component message) { -+ super(false, player, recipients, composer, message); -+ } -+ -+ /** -+ * @deprecated for removal with 1.17, use {@link #ChatEvent(Player, Set, ChatRenderer, Component, Component)} -+ */ -+ @Deprecated -+ public ChatEvent(final @NotNull Player player, final @NotNull Set recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) { -+ super(false, player, recipients, formatter, message); -+ } -+ + @NotNull + @Override + public HandlerList getHandlers() { diff --git a/Spigot-API-Patches/Allow-Blocks-to-be-accessed-via-a-long-key.patch b/patches/api/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 patches/api/Allow-Blocks-to-be-accessed-via-a-long-key.patch diff --git a/Spigot-API-Patches/Allow-Reloading-of-Command-Aliases.patch b/patches/api/Allow-Reloading-of-Command-Aliases.patch similarity index 100% rename from Spigot-API-Patches/Allow-Reloading-of-Command-Aliases.patch rename to patches/api/Allow-Reloading-of-Command-Aliases.patch diff --git a/Spigot-API-Patches/Allow-adding-items-to-BlockDropItemEvent.patch b/patches/api/Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from Spigot-API-Patches/Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/api/Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/Spigot-API-Patches/Allow-delegation-to-vanilla-chunk-gen.patch b/patches/api/Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from Spigot-API-Patches/Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/api/Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/Spigot-API-Patches/Allow-disabling-armour-stand-ticking.patch b/patches/api/Allow-disabling-armour-stand-ticking.patch similarity index 100% rename from Spigot-API-Patches/Allow-disabling-armour-stand-ticking.patch rename to patches/api/Allow-disabling-armour-stand-ticking.patch diff --git a/Spigot-API-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/api/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 patches/api/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch diff --git a/Spigot-API-Patches/Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api/Allow-plugins-to-use-SLF4J-for-logging.patch similarity index 74% rename from Spigot-API-Patches/Allow-plugins-to-use-SLF4J-for-logging.patch rename to patches/api/Allow-plugins-to-use-SLF4J-for-logging.patch index 0f734cdb0a..5c67078293 100644 --- a/Spigot-API-Patches/Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/patches/api/Allow-plugins-to-use-SLF4J-for-logging.patch @@ -13,24 +13,18 @@ Expose SLF4J as optional logging API for plugins, so they can use it without having to shade it in the plugin and going through several layers of logging abstraction. -diff --git a/pom.xml b/pom.xml +diff --git a/build.gradle.kts b/build.gradle.kts index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - 20.1.0 - provided -
-+ -+ -+ org.slf4j -+ slf4j-api -+ 1.7.25 -+ compile -+ - - - junit +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + api("net.kyori:adventure-text-serializer-plain") + api("org.ow2.asm:asm:9.0") + api("org.ow2.asm:asm-commons:9.0") ++ api("org.apache.logging.log4j:log4j-api:2.14.1") // Paper + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/plugin/Plugin.java diff --git a/Spigot-API-Patches/Allow-setting-the-vex-s-summoner.patch b/patches/api/Allow-setting-the-vex-s-summoner.patch similarity index 100% rename from Spigot-API-Patches/Allow-setting-the-vex-s-summoner.patch rename to patches/api/Allow-setting-the-vex-s-summoner.patch diff --git a/Spigot-API-Patches/Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/patches/api/Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch similarity index 100% rename from Spigot-API-Patches/Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch rename to patches/api/Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch diff --git a/Spigot-API-Patches/Annotation-Test-changes.patch b/patches/api/Annotation-Test-changes.patch similarity index 100% rename from Spigot-API-Patches/Annotation-Test-changes.patch rename to patches/api/Annotation-Test-changes.patch diff --git a/Spigot-API-Patches/AnvilDamageEvent.patch b/patches/api/AnvilDamageEvent.patch similarity index 100% rename from Spigot-API-Patches/AnvilDamageEvent.patch rename to patches/api/AnvilDamageEvent.patch diff --git a/Spigot-API-Patches/Arrow-pickup-rule-API.patch b/patches/api/Arrow-pickup-rule-API.patch similarity index 100% rename from Spigot-API-Patches/Arrow-pickup-rule-API.patch rename to patches/api/Arrow-pickup-rule-API.patch diff --git a/Spigot-API-Patches/Async-Chunks-API.patch b/patches/api/Async-Chunks-API.patch similarity index 99% rename from Spigot-API-Patches/Async-Chunks-API.patch rename to patches/api/Async-Chunks-API.patch index 5626ed6096..df58dcaaf7 100644 --- a/Spigot-API-Patches/Async-Chunks-API.patch +++ b/patches/api/Async-Chunks-API.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -0,0 +0,0 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad - public default Chunk getChunkAt(long chunkKey) { - return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); + } + return nearby; } + + /** diff --git a/Spigot-API-Patches/AsyncTabCompleteEvent.patch b/patches/api/AsyncTabCompleteEvent.patch similarity index 100% rename from Spigot-API-Patches/AsyncTabCompleteEvent.patch rename to patches/api/AsyncTabCompleteEvent.patch diff --git a/Spigot-API-Patches/Attributes-API-for-item-defaults.patch b/patches/api/Attributes-API-for-item-defaults.patch similarity index 100% rename from Spigot-API-Patches/Attributes-API-for-item-defaults.patch rename to patches/api/Attributes-API-for-item-defaults.patch diff --git a/Spigot-API-Patches/Automatically-disable-plugins-that-fail-to-load.patch b/patches/api/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 patches/api/Automatically-disable-plugins-that-fail-to-load.patch diff --git a/Spigot-API-Patches/Basic-PlayerProfile-API.patch b/patches/api/Basic-PlayerProfile-API.patch similarity index 100% rename from Spigot-API-Patches/Basic-PlayerProfile-API.patch rename to patches/api/Basic-PlayerProfile-API.patch diff --git a/Spigot-API-Patches/Beacon-API-custom-effect-ranges.patch b/patches/api/Beacon-API-custom-effect-ranges.patch similarity index 100% rename from Spigot-API-Patches/Beacon-API-custom-effect-ranges.patch rename to patches/api/Beacon-API-custom-effect-ranges.patch diff --git a/patches/api/Better-AnnotationTest-printout.patch b/patches/api/Better-AnnotationTest-printout.patch new file mode 100644 index 0000000000..de65d3c1e4 --- /dev/null +++ b/patches/api/Better-AnnotationTest-printout.patch @@ -0,0 +1,33 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 3 Dec 2020 14:04:57 -0800 +Subject: [PATCH] Better AnnotationTest printout + + +diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/AnnotationTest.java ++++ b/src/test/java/org/bukkit/AnnotationTest.java +@@ -0,0 +0,0 @@ public class AnnotationTest { + + Collections.sort(errors); + +- System.out.println(errors.size() + " missing annotation(s):"); ++ StringBuilder builder = new StringBuilder() ++ .append("There ") ++ .append(errors.size() != 1 ? "are " : "is ") ++ .append(errors.size()) ++ .append(" missing annotation") ++ .append(errors.size() != 1 ? "s:\n" : ":\n"); ++ + for (String message : errors) { +- System.out.print("\t"); +- System.out.println(message); ++ builder.append("\t").append(message).append("\n"); + } + +- Assert.fail("There " + errors.size() + " are missing annotation(s)"); ++ Assert.fail(builder.toString()); + } + + private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { diff --git a/Spigot-API-Patches/BlockDestroyEvent.patch b/patches/api/BlockDestroyEvent.patch similarity index 100% rename from Spigot-API-Patches/BlockDestroyEvent.patch rename to patches/api/BlockDestroyEvent.patch diff --git a/Spigot-API-Patches/0221-Brand-support.patch b/patches/api/Brand-support.patch similarity index 100% rename from Spigot-API-Patches/0221-Brand-support.patch rename to patches/api/Brand-support.patch diff --git a/patches/api/Build-system-changes.patch b/patches/api/Build-system-changes.patch new file mode 100644 index 0000000000..ae9db1df45 --- /dev/null +++ b/patches/api/Build-system-changes.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Zach Brown <1254957+zachbr@users.noreply.github.com> +Date: Tue, 1 Mar 2016 00:16:08 +0100 +Subject: [PATCH] Build system changes + + +diff --git a/build.gradle.kts b/build.gradle.kts +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + api("com.google.code.gson:gson:2.8.0") + api("net.md-5:bungeecord-chat:1.16-R0.4") + api("org.yaml:snakeyaml:1.28") ++ api("com.googlecode.json-simple:json-simple:1.1.1") // Paper + + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") + compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ compileOnly("com.google.code.findbugs:jsr305:1.3.9") // Paper + +- val annotations = "org.jetbrains:annotations-java5:21.0.1" ++ val annotations = "org.jetbrains:annotations:21.0.1" // Paper - we don't want Java 5 annotations... + compileOnly(annotations) + testCompileOnly(annotations) + diff --git a/Spigot-API-Patches/Cache-the-result-of-Material-isBlock.patch b/patches/api/Cache-the-result-of-Material-isBlock.patch similarity index 100% rename from Spigot-API-Patches/Cache-the-result-of-Material-isBlock.patch rename to patches/api/Cache-the-result-of-Material-isBlock.patch diff --git a/Spigot-API-Patches/Change-the-reserved-channel-check-to-be-sensible.patch b/patches/api/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 patches/api/Change-the-reserved-channel-check-to-be-sensible.patch diff --git a/Spigot-API-Patches/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/patches/api/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch similarity index 97% rename from Spigot-API-Patches/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch rename to patches/api/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch index efec11d28d..1a8bebb465 100644 --- a/Spigot-API-Patches/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch +++ b/patches/api/Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch @@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -0,0 +0,0 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - Chunk getChunk(); + } /** - * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. diff --git a/Spigot-API-Patches/Close-Plugin-Class-Loaders-on-Disable.patch b/patches/api/Close-Plugin-Class-Loaders-on-Disable.patch similarity index 100% rename from Spigot-API-Patches/Close-Plugin-Class-Loaders-on-Disable.patch rename to patches/api/Close-Plugin-Class-Loaders-on-Disable.patch diff --git a/Spigot-API-Patches/Complete-resource-pack-API.patch b/patches/api/Complete-resource-pack-API.patch similarity index 100% rename from Spigot-API-Patches/Complete-resource-pack-API.patch rename to patches/api/Complete-resource-pack-API.patch diff --git a/patches/api/Convert-project-to-Gradle.patch b/patches/api/Convert-project-to-Gradle.patch new file mode 100644 index 0000000000..03d10d2ea0 --- /dev/null +++ b/patches/api/Convert-project-to-Gradle.patch @@ -0,0 +1,360 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 10 Dec 2020 20:50:33 -0800 +Subject: [PATCH] Convert project to Gradle + +The pom.xml file is deleted in this patch so the patch will fail to +apply if there are changes made to it from upstream - thus notifying us +that changes were made. + +diff --git a/.gitignore b/.gitignore +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -0,0 +0,0 @@ ++.gradle/ ++ + # Eclipse stuff + /.classpath + /.project +diff --git a/build.gradle.kts b/build.gradle.kts +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ ++import java.util.Locale ++ ++plugins { ++ `java-library` ++ `maven-publish` ++} ++ ++java { ++ withSourcesJar() ++ withJavadocJar() ++} ++ ++dependencies { ++ // api dependencies are listed transitively to API consumers ++ api("commons-lang:commons-lang:2.6") ++ api("com.google.guava:guava:21.0") ++ api("com.google.code.gson:gson:2.8.0") ++ api("net.md-5:bungeecord-chat:1.16-R0.4") ++ api("org.yaml:snakeyaml:1.28") ++ ++ compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") ++ compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") ++ compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ ++ val annotations = "org.jetbrains:annotations-java5:21.0.1" ++ compileOnly(annotations) ++ testCompileOnly(annotations) ++ ++ testImplementation("junit:junit:4.13.1") ++ testImplementation("org.hamcrest:hamcrest-library:1.3") ++ testImplementation("org.ow2.asm:asm-tree:9.1") ++} ++ ++configure { ++ publications.create("maven") { ++ artifactId = project.name.toLowerCase(Locale.ENGLISH) ++ from(components["java"]) ++ } ++} ++ ++val generateApiVersioningFile by tasks.registering { ++ val pomProps = layout.buildDirectory.file("pom.properties") ++ outputs.file(pomProps) ++ doLast { ++ pomProps.get().asFile.writeText("version=${project.version}") ++ } ++} ++ ++tasks.jar { ++ from(generateApiVersioningFile.map { it.outputs.files.singleFile }) { ++ into("META-INF/maven/${project.group}/${project.name.toLowerCase(Locale.ENGLISH)}") ++ } ++ manifest { ++ attributes += mapOf( ++ "Automatic-Module-Name" to "org.bukkit" ++ ) ++ } ++} ++ ++tasks.withType().configureEach { ++ (options as StandardJavadocDocletOptions).links( ++ "https://guava.dev/releases/21.0/api/docs/", ++ "https://javadoc.io/doc/org.yaml/snakeyaml/1.27/", ++ "https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/", ++ "https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/" ++ ) ++} +diff --git a/pom.xml b/pom.xml +deleted file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- a/pom.xml ++++ /dev/null +@@ -0,0 +0,0 @@ +- +- +- 4.0.0 +- +- org.spigotmc +- spigot-api +- 1.17-R0.1-SNAPSHOT +- jar +- +- Spigot-API +- https://www.spigotmc.org/ +- An enhanced plugin API for Minecraft servers. +- +- +- true +- 1.8 +- 1.8 +- UTF-8 +- +- +- +- +- spigotmc-releases +- https://hub.spigotmc.org/nexus/content/repositories/releases/ +- +- +- spigotmc-snapshots +- https://hub.spigotmc.org/nexus/content/repositories/snapshots/ +- +- +- +- +- +- commons-lang +- commons-lang +- 2.6 +- compile +- +- +- +- com.google.guava +- guava +- 21.0 +- compile +- +- +- +- com.google.code.gson +- gson +- 2.8.0 +- compile +- +- +- net.md-5 +- bungeecord-chat +- 1.16-R0.4 +- jar +- compile +- +- +- org.yaml +- snakeyaml +- 1.28 +- compile +- +- +- +- org.apache.maven +- maven-resolver-provider +- 3.8.1 +- provided +- +- +- org.apache.maven.resolver +- maven-resolver-connector-basic +- 1.7.0 +- provided +- +- +- org.apache.maven.resolver +- maven-resolver-transport-http +- 1.7.0 +- provided +- +- +- +- org.jetbrains +- annotations-java5 +- 21.0.1 +- provided +- +- +- +- junit +- junit +- 4.13.1 +- test +- +- +- org.hamcrest +- hamcrest-library +- 1.3 +- test +- +- +- org.ow2.asm +- asm-tree +- 9.1 +- test +- +- +- +- +- +- +- net.md-5 +- scriptus +- 0.4.1 +- +- +- initialize +- +- describe +- +- +- +- +- +- org.apache.maven.plugins +- maven-compiler-plugin +- 3.8.1 +- +- +- eclipse +- +- +- +- org.codehaus.plexus +- plexus-compiler-eclipse +- 2.8.8 +- +- +- org.eclipse.jdt +- ecj +- 3.24.0 +- +- +- +- +- org.apache.maven.plugins +- maven-jar-plugin +- 3.2.0 +- +- +- +- false +- +- +- org.bukkit +- +- +- +- +- +- org.apache.maven.plugins +- maven-shade-plugin +- 3.2.3 +- +- +- package +- +- shade +- +- +- +- +- +- +- *:* +- +- META-INF/MANIFEST.MF +- +- +- +- +- true +- +- +- +- org.apache.maven.plugins +- maven-javadoc-plugin +- 3.2.0 +- +- +- https://guava.dev/releases/21.0/api/docs/ +- https://javadoc.io/doc/org.yaml/snakeyaml/1.27/ +- https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/ +- https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/ +- +- +- +- +- +- +- +- +- development +- +- false +- +- +- +- +- org.apache.maven.plugins +- maven-checkstyle-plugin +- 3.1.1 +- +- +- process-classes +- +- check +- +- +- +- +- checkstyle.xml +- true +- +- +- +- com.puppycrawl.tools +- checkstyle +- 8.39 +- +- +- +- +- org.codehaus.mojo +- animal-sniffer-maven-plugin +- 1.19 +- +- +- process-classes +- +- check +- +- +- +- +- +- org.codehaus.mojo.signature +- java18 +- 1.0 +- +- +- +- +- +- +- +- diff --git a/Spigot-API-Patches/Create-HoverEvent-from-ItemStack-Entity.patch b/patches/api/Create-HoverEvent-from-ItemStack-Entity.patch similarity index 97% rename from Spigot-API-Patches/Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/api/Create-HoverEvent-from-ItemStack-Entity.patch index 14f854c189..52beec5c41 100644 --- a/Spigot-API-Patches/Create-HoverEvent-from-ItemStack-Entity.patch +++ b/patches/api/Create-HoverEvent-from-ItemStack-Entity.patch @@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java @@ -0,0 +0,0 @@ public interface ItemFactory { */ - @Nullable - String getI18NDisplayName(@Nullable ItemStack item); + @NotNull + ItemStack ensureServerConversions(@NotNull ItemStack item); + + /** + * Creates a {@link net.md_5.bungee.api.chat.hover.content.Content} of that ItemStack for displaying. diff --git a/Spigot-API-Patches/Custom-replacement-for-eaten-items.patch b/patches/api/Custom-replacement-for-eaten-items.patch similarity index 100% rename from Spigot-API-Patches/Custom-replacement-for-eaten-items.patch rename to patches/api/Custom-replacement-for-eaten-items.patch diff --git a/Spigot-API-Patches/Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/patches/api/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 patches/api/Disable-Sync-Events-firing-Async-errors-during-shutd.patch diff --git a/Spigot-API-Patches/Display-warning-on-deprecated-recipe-API.patch b/patches/api/Display-warning-on-deprecated-recipe-API.patch similarity index 100% rename from Spigot-API-Patches/Display-warning-on-deprecated-recipe-API.patch rename to patches/api/Display-warning-on-deprecated-recipe-API.patch diff --git a/Spigot-API-Patches/Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/patches/api/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 patches/api/Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch diff --git a/Spigot-API-Patches/Enable-multi-release-plugin-jars.patch b/patches/api/Enable-multi-release-plugin-jars.patch similarity index 55% rename from Spigot-API-Patches/Enable-multi-release-plugin-jars.patch rename to patches/api/Enable-multi-release-plugin-jars.patch index 97b4c61f4f..a9230e6211 100644 --- a/Spigot-API-Patches/Enable-multi-release-plugin-jars.patch +++ b/patches/api/Enable-multi-release-plugin-jars.patch @@ -13,18 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.dataFolder = dataFolder; this.file = file; - this.jar = new JarFile(file); -+ // Paper - enable multi-release jars for Java 9+ -+ JarFile jarFile; -+ try { -+ final java.lang.reflect.Method runtimeVersionMethod = JarFile.class.getMethod("runtimeVersion"); -+ final Object runtimeVersion = runtimeVersionMethod.invoke(null); -+ @SuppressWarnings("JavaReflectionMemberAccess") final java.lang.reflect.Constructor constructor = JarFile.class.getConstructor(File.class, boolean.class, int.class, runtimeVersion.getClass()); -+ jarFile = constructor.newInstance(file, true, java.util.zip.ZipFile.OPEN_READ, runtimeVersion); -+ } catch (Exception ignored) { -+ jarFile = new JarFile(file); -+ } -+ this.jar = jarFile; -+ // Paper end ++ this.jar = new JarFile(file, true, java.util.zip.ZipFile.OPEN_READ, JarFile.runtimeVersion()); // Paper - enable multi-release jars for Java 9+ this.manifest = jar.getManifest(); this.url = file.toURI().toURL(); this.libraryLoader = libraryLoader; diff --git a/Spigot-API-Patches/EnderDragon-Events.patch b/patches/api/EnderDragon-Events.patch similarity index 100% rename from Spigot-API-Patches/EnderDragon-Events.patch rename to patches/api/EnderDragon-Events.patch diff --git a/Spigot-API-Patches/Enderman.teleportRandomly.patch b/patches/api/Enderman.teleportRandomly.patch similarity index 100% rename from Spigot-API-Patches/Enderman.teleportRandomly.patch rename to patches/api/Enderman.teleportRandomly.patch diff --git a/Spigot-API-Patches/EndermanAttackPlayerEvent.patch b/patches/api/EndermanAttackPlayerEvent.patch similarity index 100% rename from Spigot-API-Patches/EndermanAttackPlayerEvent.patch rename to patches/api/EndermanAttackPlayerEvent.patch diff --git a/Spigot-API-Patches/EndermanEscapeEvent.patch b/patches/api/EndermanEscapeEvent.patch similarity index 100% rename from Spigot-API-Patches/EndermanEscapeEvent.patch rename to patches/api/EndermanEscapeEvent.patch diff --git a/Spigot-API-Patches/Entity-AddTo-RemoveFrom-World-Events.patch b/patches/api/Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from Spigot-API-Patches/Entity-AddTo-RemoveFrom-World-Events.patch rename to patches/api/Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/Spigot-API-Patches/Entity-Jump-API.patch b/patches/api/Entity-Jump-API.patch similarity index 100% rename from Spigot-API-Patches/Entity-Jump-API.patch rename to patches/api/Entity-Jump-API.patch diff --git a/Spigot-API-Patches/Entity-Origin-API.patch b/patches/api/Entity-Origin-API.patch similarity index 100% rename from Spigot-API-Patches/Entity-Origin-API.patch rename to patches/api/Entity-Origin-API.patch diff --git a/Spigot-API-Patches/Entity-fromMobSpawner.patch b/patches/api/Entity-fromMobSpawner.patch similarity index 100% rename from Spigot-API-Patches/Entity-fromMobSpawner.patch rename to patches/api/Entity-fromMobSpawner.patch diff --git a/Spigot-API-Patches/Entity-getChunk-API.patch b/patches/api/Entity-getChunk-API.patch similarity index 91% rename from Spigot-API-Patches/Entity-getChunk-API.patch rename to patches/api/Entity-getChunk-API.patch index c222dca653..83994ab122 100644 --- a/Spigot-API-Patches/Entity-getChunk-API.patch +++ b/patches/api/Entity-getChunk-API.patch @@ -28,6 +28,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @return The current, or most recent chunk if the entity is invalid (which may load the chunk) + */ + @NotNull -+ Chunk getChunk(); ++ default Chunk getChunk() { ++ // TODO remove impl here ++ return getLocation().getChunk(); ++ } // Paper end } diff --git a/Spigot-API-Patches/Entity-getEntitySpawnReason.patch b/patches/api/Entity-getEntitySpawnReason.patch similarity index 92% rename from Spigot-API-Patches/Entity-getEntitySpawnReason.patch rename to patches/api/Entity-getEntitySpawnReason.patch index 0008e705be..01af933d1f 100644 --- a/Spigot-API-Patches/Entity-getEntitySpawnReason.patch +++ b/patches/api/Entity-getEntitySpawnReason.patch @@ -14,9 +14,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -0,0 +0,0 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent - */ - @NotNull - Chunk getChunk(); + // TODO remove impl here + return getLocation().getChunk(); + } + + /** + * @return The {@link org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason} that spawned this entity. diff --git a/Spigot-API-Patches/Entity-isTicking.patch b/patches/api/Entity-isTicking.patch similarity index 100% rename from Spigot-API-Patches/Entity-isTicking.patch rename to patches/api/Entity-isTicking.patch diff --git a/Spigot-API-Patches/EntityMoveEvent.patch b/patches/api/EntityMoveEvent.patch similarity index 100% rename from Spigot-API-Patches/EntityMoveEvent.patch rename to patches/api/EntityMoveEvent.patch diff --git a/Spigot-API-Patches/EntityPathfindEvent.patch b/patches/api/EntityPathfindEvent.patch similarity index 100% rename from Spigot-API-Patches/EntityPathfindEvent.patch rename to patches/api/EntityPathfindEvent.patch diff --git a/Spigot-API-Patches/EntityRegainHealthEvent-isFastRegen-API.patch b/patches/api/EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from Spigot-API-Patches/EntityRegainHealthEvent-isFastRegen-API.patch rename to patches/api/EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/Spigot-API-Patches/EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/patches/api/EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch similarity index 100% rename from Spigot-API-Patches/EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch rename to patches/api/EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch diff --git a/Spigot-API-Patches/EntityTransformedEvent.patch b/patches/api/EntityTransformedEvent.patch similarity index 100% rename from Spigot-API-Patches/EntityTransformedEvent.patch rename to patches/api/EntityTransformedEvent.patch diff --git a/Spigot-API-Patches/Expand-ArmorStand-API.patch b/patches/api/Expand-ArmorStand-API.patch similarity index 100% rename from Spigot-API-Patches/Expand-ArmorStand-API.patch rename to patches/api/Expand-ArmorStand-API.patch diff --git a/Spigot-API-Patches/Expand-Explosions-API.patch b/patches/api/Expand-Explosions-API.patch similarity index 100% rename from Spigot-API-Patches/Expand-Explosions-API.patch rename to patches/api/Expand-Explosions-API.patch diff --git a/Spigot-API-Patches/Expand-Location-Manipulation-API.patch b/patches/api/Expand-Location-Manipulation-API.patch similarity index 100% rename from Spigot-API-Patches/Expand-Location-Manipulation-API.patch rename to patches/api/Expand-Location-Manipulation-API.patch diff --git a/Spigot-API-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/api/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 patches/api/Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/Spigot-API-Patches/ExperienceOrbMergeEvent.patch b/patches/api/ExperienceOrbMergeEvent.patch similarity index 100% rename from Spigot-API-Patches/ExperienceOrbMergeEvent.patch rename to patches/api/ExperienceOrbMergeEvent.patch diff --git a/Spigot-API-Patches/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/api/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 patches/api/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/Spigot-API-Patches/Expose-Arrow-getItemStack.patch b/patches/api/Expose-Arrow-getItemStack.patch similarity index 100% rename from Spigot-API-Patches/Expose-Arrow-getItemStack.patch rename to patches/api/Expose-Arrow-getItemStack.patch diff --git a/Spigot-API-Patches/Expose-LivingEntity-hurt-direction.patch b/patches/api/Expose-LivingEntity-hurt-direction.patch similarity index 100% rename from Spigot-API-Patches/Expose-LivingEntity-hurt-direction.patch rename to patches/api/Expose-LivingEntity-hurt-direction.patch diff --git a/Spigot-API-Patches/Expose-MinecraftServer-isRunning.patch b/patches/api/Expose-MinecraftServer-isRunning.patch similarity index 100% rename from Spigot-API-Patches/Expose-MinecraftServer-isRunning.patch rename to patches/api/Expose-MinecraftServer-isRunning.patch diff --git a/Spigot-API-Patches/Expose-Tracked-Players.patch b/patches/api/Expose-Tracked-Players.patch similarity index 100% rename from Spigot-API-Patches/Expose-Tracked-Players.patch rename to patches/api/Expose-Tracked-Players.patch diff --git a/Spigot-API-Patches/Expose-WorldBorder-isInBounds-Location-check.patch b/patches/api/Expose-WorldBorder-isInBounds-Location-check.patch similarity index 100% rename from Spigot-API-Patches/Expose-WorldBorder-isInBounds-Location-check.patch rename to patches/api/Expose-WorldBorder-isInBounds-Location-check.patch diff --git a/Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch b/patches/api/Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch rename to patches/api/Expose-attack-cooldown-methods-for-Player.patch diff --git a/Spigot-API-Patches/Expose-client-protocol-version-and-virtual-host.patch b/patches/api/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 patches/api/Expose-client-protocol-version-and-virtual-host.patch diff --git a/Spigot-API-Patches/Expose-game-version.patch b/patches/api/Expose-game-version.patch similarity index 100% rename from Spigot-API-Patches/Expose-game-version.patch rename to patches/api/Expose-game-version.patch diff --git a/Spigot-API-Patches/Expose-protocol-version.patch b/patches/api/Expose-protocol-version.patch similarity index 100% rename from Spigot-API-Patches/Expose-protocol-version.patch rename to patches/api/Expose-protocol-version.patch diff --git a/Spigot-API-Patches/Expose-server-CommandMap.patch b/patches/api/Expose-server-CommandMap.patch similarity index 100% rename from Spigot-API-Patches/Expose-server-CommandMap.patch rename to patches/api/Expose-server-CommandMap.patch diff --git a/Spigot-API-Patches/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/api/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 patches/api/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch diff --git a/Spigot-API-Patches/Expose-the-internal-current-tick.patch b/patches/api/Expose-the-internal-current-tick.patch similarity index 100% rename from Spigot-API-Patches/Expose-the-internal-current-tick.patch rename to patches/api/Expose-the-internal-current-tick.patch diff --git a/Spigot-API-Patches/Fill-Profile-Property-Events.patch b/patches/api/Fill-Profile-Property-Events.patch similarity index 100% rename from Spigot-API-Patches/Fill-Profile-Property-Events.patch rename to patches/api/Fill-Profile-Property-Events.patch diff --git a/Spigot-API-Patches/Fireworks-API-s.patch b/patches/api/Fireworks-API-s.patch similarity index 100% rename from Spigot-API-Patches/Fireworks-API-s.patch rename to patches/api/Fireworks-API-s.patch diff --git a/Spigot-API-Patches/Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/patches/api/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 patches/api/Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch diff --git a/Spigot-API-Patches/Fix-ServerListPingEvent-flagging-as-Async.patch b/patches/api/Fix-ServerListPingEvent-flagging-as-Async.patch similarity index 100% rename from Spigot-API-Patches/Fix-ServerListPingEvent-flagging-as-Async.patch rename to patches/api/Fix-ServerListPingEvent-flagging-as-Async.patch diff --git a/Spigot-API-Patches/Fix-upstream-javadoc-warnings-and-errors.patch b/patches/api/Fix-upstream-javadoc-warnings-and-errors.patch similarity index 100% rename from Spigot-API-Patches/Fix-upstream-javadoc-warnings-and-errors.patch rename to patches/api/Fix-upstream-javadoc-warnings-and-errors.patch diff --git a/Spigot-API-Patches/Flip-some-Spigot-API-null-annotations.patch b/patches/api/Flip-some-Spigot-API-null-annotations.patch similarity index 100% rename from Spigot-API-Patches/Flip-some-Spigot-API-null-annotations.patch rename to patches/api/Flip-some-Spigot-API-null-annotations.patch diff --git a/Spigot-API-Patches/Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/patches/api/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 patches/api/Graduate-bungeecord-chat-API-from-spigot-subclasses.patch diff --git a/Spigot-API-Patches/Handle-plugin-prefixes-in-implementation-logging-con.patch b/patches/api/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 patches/api/Handle-plugin-prefixes-in-implementation-logging-con.patch diff --git a/Spigot-API-Patches/Here-s-Johnny.patch b/patches/api/Here-s-Johnny.patch similarity index 100% rename from Spigot-API-Patches/Here-s-Johnny.patch rename to patches/api/Here-s-Johnny.patch diff --git a/Spigot-API-Patches/Ignore-package-private-methods-for-nullability-annot.patch b/patches/api/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 patches/api/Ignore-package-private-methods-for-nullability-annot.patch diff --git a/Spigot-API-Patches/IllegalPacketEvent.patch b/patches/api/IllegalPacketEvent.patch similarity index 100% rename from Spigot-API-Patches/IllegalPacketEvent.patch rename to patches/api/IllegalPacketEvent.patch diff --git a/Spigot-API-Patches/Implement-Keyed-on-World.patch b/patches/api/Implement-Keyed-on-World.patch similarity index 100% rename from Spigot-API-Patches/Implement-Keyed-on-World.patch rename to patches/api/Implement-Keyed-on-World.patch diff --git a/Spigot-API-Patches/Implement-furnace-cook-speed-multiplier-API.patch b/patches/api/Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from Spigot-API-Patches/Implement-furnace-cook-speed-multiplier-API.patch rename to patches/api/Implement-furnace-cook-speed-multiplier-API.patch diff --git a/Spigot-API-Patches/Improve-death-events.patch b/patches/api/Improve-death-events.patch similarity index 100% rename from Spigot-API-Patches/Improve-death-events.patch rename to patches/api/Improve-death-events.patch diff --git a/Spigot-API-Patches/Improve-the-Saddle-API-for-Horses.patch b/patches/api/Improve-the-Saddle-API-for-Horses.patch similarity index 100% rename from Spigot-API-Patches/Improve-the-Saddle-API-for-Horses.patch rename to patches/api/Improve-the-Saddle-API-for-Horses.patch diff --git a/Spigot-API-Patches/Increase-custom-payload-channel-message-size.patch b/patches/api/Increase-custom-payload-channel-message-size.patch similarity index 100% rename from Spigot-API-Patches/Increase-custom-payload-channel-message-size.patch rename to patches/api/Increase-custom-payload-channel-message-size.patch diff --git a/Spigot-API-Patches/Introduce-beacon-activation-deactivation-events.patch b/patches/api/Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from Spigot-API-Patches/Introduce-beacon-activation-deactivation-events.patch rename to patches/api/Introduce-beacon-activation-deactivation-events.patch diff --git a/Spigot-API-Patches/Inventory-close.patch b/patches/api/Inventory-close.patch similarity index 100% rename from Spigot-API-Patches/Inventory-close.patch rename to patches/api/Inventory-close.patch diff --git a/Spigot-API-Patches/Inventory-getHolder-method-without-block-snapshot.patch b/patches/api/Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from Spigot-API-Patches/Inventory-getHolder-method-without-block-snapshot.patch rename to patches/api/Inventory-getHolder-method-without-block-snapshot.patch diff --git a/Spigot-API-Patches/Inventory-removeItemAnySlot.patch b/patches/api/Inventory-removeItemAnySlot.patch similarity index 100% rename from Spigot-API-Patches/Inventory-removeItemAnySlot.patch rename to patches/api/Inventory-removeItemAnySlot.patch diff --git a/Spigot-API-Patches/InventoryCloseEvent-Reason-API.patch b/patches/api/InventoryCloseEvent-Reason-API.patch similarity index 100% rename from Spigot-API-Patches/InventoryCloseEvent-Reason-API.patch rename to patches/api/InventoryCloseEvent-Reason-API.patch diff --git a/Spigot-API-Patches/Item-Rarity-API.patch b/patches/api/Item-Rarity-API.patch similarity index 100% rename from Spigot-API-Patches/Item-Rarity-API.patch rename to patches/api/Item-Rarity-API.patch diff --git a/Spigot-API-Patches/Item-canEntityPickup.patch b/patches/api/Item-canEntityPickup.patch similarity index 100% rename from Spigot-API-Patches/Item-canEntityPickup.patch rename to patches/api/Item-canEntityPickup.patch diff --git a/Spigot-API-Patches/Item-no-age-no-player-pickup.patch b/patches/api/Item-no-age-no-player-pickup.patch similarity index 100% rename from Spigot-API-Patches/Item-no-age-no-player-pickup.patch rename to patches/api/Item-no-age-no-player-pickup.patch diff --git a/Spigot-API-Patches/ItemStack-API-additions-for-quantity-flags-lore.patch b/patches/api/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 patches/api/ItemStack-API-additions-for-quantity-flags-lore.patch diff --git a/Spigot-API-Patches/ItemStack-editMeta.patch b/patches/api/ItemStack-editMeta.patch similarity index 100% rename from Spigot-API-Patches/ItemStack-editMeta.patch rename to patches/api/ItemStack-editMeta.patch diff --git a/Spigot-API-Patches/ItemStack-getMaxItemUseDuration.patch b/patches/api/ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from Spigot-API-Patches/ItemStack-getMaxItemUseDuration.patch rename to patches/api/ItemStack-getMaxItemUseDuration.patch diff --git a/Spigot-API-Patches/ItemStack-repair-check-API.patch b/patches/api/ItemStack-repair-check-API.patch similarity index 100% rename from Spigot-API-Patches/ItemStack-repair-check-API.patch rename to patches/api/ItemStack-repair-check-API.patch diff --git a/Spigot-API-Patches/List-all-missing-hard-depends-not-just-first.patch b/patches/api/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 patches/api/List-all-missing-hard-depends-not-just-first.patch diff --git a/Spigot-API-Patches/LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/api/LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from Spigot-API-Patches/LivingEntity-Hand-Raised-Item-Use-API.patch rename to patches/api/LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/Spigot-API-Patches/LivingEntity-setKiller.patch b/patches/api/LivingEntity-setKiller.patch similarity index 100% rename from Spigot-API-Patches/LivingEntity-setKiller.patch rename to patches/api/LivingEntity-setKiller.patch diff --git a/Spigot-API-Patches/Location.isChunkLoaded-API.patch b/patches/api/Location.isChunkLoaded-API.patch similarity index 100% rename from Spigot-API-Patches/Location.isChunkLoaded-API.patch rename to patches/api/Location.isChunkLoaded-API.patch diff --git a/Spigot-API-Patches/Location.toBlockLocation-toCenterLocation.patch b/patches/api/Location.toBlockLocation-toCenterLocation.patch similarity index 100% rename from Spigot-API-Patches/Location.toBlockLocation-toCenterLocation.patch rename to patches/api/Location.toBlockLocation-toCenterLocation.patch diff --git a/Spigot-API-Patches/LootTable-API.patch b/patches/api/LootTable-API.patch similarity index 100% rename from Spigot-API-Patches/LootTable-API.patch rename to patches/api/LootTable-API.patch diff --git a/Spigot-API-Patches/Make-EnderDragon-extend-Mob.patch b/patches/api/Make-EnderDragon-extend-Mob.patch similarity index 100% rename from Spigot-API-Patches/Make-EnderDragon-extend-Mob.patch rename to patches/api/Make-EnderDragon-extend-Mob.patch diff --git a/Spigot-API-Patches/Make-JavaPluginLoader-thread-safe.patch b/patches/api/Make-JavaPluginLoader-thread-safe.patch similarity index 100% rename from Spigot-API-Patches/Make-JavaPluginLoader-thread-safe.patch rename to patches/api/Make-JavaPluginLoader-thread-safe.patch diff --git a/Spigot-API-Patches/Make-plugins-list-alphabetical.patch b/patches/api/Make-plugins-list-alphabetical.patch similarity index 100% rename from Spigot-API-Patches/Make-plugins-list-alphabetical.patch rename to patches/api/Make-plugins-list-alphabetical.patch diff --git a/Spigot-API-Patches/Make-shield-blocking-delay-configurable.patch b/patches/api/Make-shield-blocking-delay-configurable.patch similarity index 100% rename from Spigot-API-Patches/Make-shield-blocking-delay-configurable.patch rename to patches/api/Make-shield-blocking-delay-configurable.patch diff --git a/Spigot-API-Patches/Make-the-default-permission-message-configurable.patch b/patches/api/Make-the-default-permission-message-configurable.patch similarity index 100% rename from Spigot-API-Patches/Make-the-default-permission-message-configurable.patch rename to patches/api/Make-the-default-permission-message-configurable.patch diff --git a/Spigot-API-Patches/Material-API-additions.patch b/patches/api/Material-API-additions.patch similarity index 100% rename from Spigot-API-Patches/Material-API-additions.patch rename to patches/api/Material-API-additions.patch diff --git a/Spigot-API-Patches/Misc-Utils.patch b/patches/api/Misc-Utils.patch similarity index 100% rename from Spigot-API-Patches/Misc-Utils.patch rename to patches/api/Misc-Utils.patch diff --git a/Spigot-API-Patches/Mob-Pathfinding-API.patch b/patches/api/Mob-Pathfinding-API.patch similarity index 100% rename from Spigot-API-Patches/Mob-Pathfinding-API.patch rename to patches/api/Mob-Pathfinding-API.patch diff --git a/Spigot-API-Patches/Mob-Spawner-API-Enhancements.patch b/patches/api/Mob-Spawner-API-Enhancements.patch similarity index 100% rename from Spigot-API-Patches/Mob-Spawner-API-Enhancements.patch rename to patches/api/Mob-Spawner-API-Enhancements.patch diff --git a/Spigot-API-Patches/More-Enchantment-API.patch b/patches/api/More-Enchantment-API.patch similarity index 100% rename from Spigot-API-Patches/More-Enchantment-API.patch rename to patches/api/More-Enchantment-API.patch diff --git a/Spigot-API-Patches/More-Lidded-Block-API.patch b/patches/api/More-Lidded-Block-API.patch similarity index 100% rename from Spigot-API-Patches/More-Lidded-Block-API.patch rename to patches/api/More-Lidded-Block-API.patch diff --git a/Spigot-API-Patches/More-World-API.patch b/patches/api/More-World-API.patch similarity index 100% rename from Spigot-API-Patches/More-World-API.patch rename to patches/api/More-World-API.patch diff --git a/Spigot-API-Patches/More-lightning-API.patch b/patches/api/More-lightning-API.patch similarity index 100% rename from Spigot-API-Patches/More-lightning-API.patch rename to patches/api/More-lightning-API.patch diff --git a/Spigot-API-Patches/Optimize-Hoppers.patch b/patches/api/Optimize-Hoppers.patch similarity index 100% rename from Spigot-API-Patches/Optimize-Hoppers.patch rename to patches/api/Optimize-Hoppers.patch diff --git a/Spigot-API-Patches/Paper-Utils.patch b/patches/api/Paper-Utils.patch similarity index 100% rename from Spigot-API-Patches/Paper-Utils.patch rename to patches/api/Paper-Utils.patch diff --git a/Spigot-API-Patches/Performance-Concurrency-Improvements-to-Permissions.patch b/patches/api/Performance-Concurrency-Improvements-to-Permissions.patch similarity index 100% rename from Spigot-API-Patches/Performance-Concurrency-Improvements-to-Permissions.patch rename to patches/api/Performance-Concurrency-Improvements-to-Permissions.patch diff --git a/Spigot-API-Patches/Player-Chunk-Load-Unload-Events.patch b/patches/api/Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from Spigot-API-Patches/Player-Chunk-Load-Unload-Events.patch rename to patches/api/Player-Chunk-Load-Unload-Events.patch diff --git a/Spigot-API-Patches/Player-Tab-List-and-Title-APIs.patch b/patches/api/Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from Spigot-API-Patches/Player-Tab-List-and-Title-APIs.patch rename to patches/api/Player-Tab-List-and-Title-APIs.patch diff --git a/Spigot-API-Patches/Player-affects-spawning-API.patch b/patches/api/Player-affects-spawning-API.patch similarity index 100% rename from Spigot-API-Patches/Player-affects-spawning-API.patch rename to patches/api/Player-affects-spawning-API.patch diff --git a/Spigot-API-Patches/Player-elytra-boost-API.patch b/patches/api/Player-elytra-boost-API.patch similarity index 100% rename from Spigot-API-Patches/Player-elytra-boost-API.patch rename to patches/api/Player-elytra-boost-API.patch diff --git a/Spigot-API-Patches/Player.setPlayerProfile-API.patch b/patches/api/Player.setPlayerProfile-API.patch similarity index 100% rename from Spigot-API-Patches/Player.setPlayerProfile-API.patch rename to patches/api/Player.setPlayerProfile-API.patch diff --git a/Spigot-API-Patches/PlayerAdvancementCriterionGrantEvent.patch b/patches/api/PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerAdvancementCriterionGrantEvent.patch rename to patches/api/PlayerAdvancementCriterionGrantEvent.patch diff --git a/Spigot-API-Patches/PlayerAttemptPickupItemEvent.patch b/patches/api/PlayerAttemptPickupItemEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerAttemptPickupItemEvent.patch rename to patches/api/PlayerAttemptPickupItemEvent.patch diff --git a/Spigot-API-Patches/PlayerDeathEvent-getItemsToKeep.patch b/patches/api/PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from Spigot-API-Patches/PlayerDeathEvent-getItemsToKeep.patch rename to patches/api/PlayerDeathEvent-getItemsToKeep.patch diff --git a/Spigot-API-Patches/PlayerDeathEvent-shouldDropExperience.patch b/patches/api/PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from Spigot-API-Patches/PlayerDeathEvent-shouldDropExperience.patch rename to patches/api/PlayerDeathEvent-shouldDropExperience.patch diff --git a/Spigot-API-Patches/PlayerElytraBoostEvent.patch b/patches/api/PlayerElytraBoostEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerElytraBoostEvent.patch rename to patches/api/PlayerElytraBoostEvent.patch diff --git a/Spigot-API-Patches/PlayerLaunchProjectileEvent.patch b/patches/api/PlayerLaunchProjectileEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerLaunchProjectileEvent.patch rename to patches/api/PlayerLaunchProjectileEvent.patch diff --git a/Spigot-API-Patches/PlayerMoveEvent-Improvements.patch b/patches/api/PlayerMoveEvent-Improvements.patch similarity index 100% rename from Spigot-API-Patches/PlayerMoveEvent-Improvements.patch rename to patches/api/PlayerMoveEvent-Improvements.patch diff --git a/Spigot-API-Patches/PlayerNaturallySpawnCreaturesEvent.patch b/patches/api/PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerNaturallySpawnCreaturesEvent.patch rename to patches/api/PlayerNaturallySpawnCreaturesEvent.patch diff --git a/Spigot-API-Patches/PlayerPickupExperienceEvent.patch b/patches/api/PlayerPickupExperienceEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerPickupExperienceEvent.patch rename to patches/api/PlayerPickupExperienceEvent.patch diff --git a/Spigot-API-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/api/PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 100% rename from Spigot-API-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch rename to patches/api/PlayerPickupItemEvent-setFlyAtPlayer.patch diff --git a/Spigot-API-Patches/PlayerReadyArrowEvent.patch b/patches/api/PlayerReadyArrowEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerReadyArrowEvent.patch rename to patches/api/PlayerReadyArrowEvent.patch diff --git a/Spigot-API-Patches/PlayerTeleportEndGatewayEvent.patch b/patches/api/PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from Spigot-API-Patches/PlayerTeleportEndGatewayEvent.patch rename to patches/api/PlayerTeleportEndGatewayEvent.patch diff --git a/Spigot-API-Patches/Potential-bed-API.patch b/patches/api/Potential-bed-API.patch similarity index 100% rename from Spigot-API-Patches/Potential-bed-API.patch rename to patches/api/Potential-bed-API.patch diff --git a/Spigot-API-Patches/PotionEffect-clone-methods.patch b/patches/api/PotionEffect-clone-methods.patch similarity index 100% rename from Spigot-API-Patches/PotionEffect-clone-methods.patch rename to patches/api/PotionEffect-clone-methods.patch diff --git a/Spigot-API-Patches/PreCreatureSpawnEvent.patch b/patches/api/PreCreatureSpawnEvent.patch similarity index 100% rename from Spigot-API-Patches/PreCreatureSpawnEvent.patch rename to patches/api/PreCreatureSpawnEvent.patch diff --git a/Spigot-API-Patches/PreSpawnerSpawnEvent.patch b/patches/api/PreSpawnerSpawnEvent.patch similarity index 95% rename from Spigot-API-Patches/PreSpawnerSpawnEvent.patch rename to patches/api/PreSpawnerSpawnEvent.patch index ff92e4142c..391d4675fa 100644 --- a/Spigot-API-Patches/PreSpawnerSpawnEvent.patch +++ b/patches/api/PreSpawnerSpawnEvent.patch @@ -8,6 +8,8 @@ which contains the location of the spawner too similarly to how the SpawnerSpawnEvent gets called instead of the CreatureSpawnEvent for spawners. +Dropped as it does not apply due to the earlier PreCreatureSpawnEvent patch not being applied + diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreSpawnerSpawnEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/Spigot-API-Patches/Prioritise-own-classes-where-possible.patch b/patches/api/Prioritise-own-classes-where-possible.patch similarity index 94% rename from Spigot-API-Patches/Prioritise-own-classes-where-possible.patch rename to patches/api/Prioritise-own-classes-where-possible.patch index 3826df3296..9f75bf62cc 100644 --- a/Spigot-API-Patches/Prioritise-own-classes-where-possible.patch +++ b/patches/api/Prioritise-own-classes-where-possible.patch @@ -82,5 +82,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - Class result = loader.getClassByName(name, resolve, description); + Class result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self - // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. - if (result != null && result.getClassLoader() instanceof PluginClassLoader) { + if (result != null) { + // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. diff --git a/Spigot-API-Patches/Profile-Lookup-Events.patch b/patches/api/Profile-Lookup-Events.patch similarity index 100% rename from Spigot-API-Patches/Profile-Lookup-Events.patch rename to patches/api/Profile-Lookup-Events.patch diff --git a/Spigot-API-Patches/ProfileWhitelistVerifyEvent.patch b/patches/api/ProfileWhitelistVerifyEvent.patch similarity index 100% rename from Spigot-API-Patches/ProfileWhitelistVerifyEvent.patch rename to patches/api/ProfileWhitelistVerifyEvent.patch diff --git a/Spigot-API-Patches/Provide-Chunk-Coordinates-as-a-Long-API.patch b/patches/api/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 patches/api/Provide-Chunk-Coordinates-as-a-Long-API.patch diff --git a/Spigot-API-Patches/Provide-E-TE-Chunk-count-stat-methods.patch b/patches/api/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 patches/api/Provide-E-TE-Chunk-count-stat-methods.patch diff --git a/Spigot-API-Patches/Provide-a-useful-PluginClassLoader-toString.patch b/patches/api/Provide-a-useful-PluginClassLoader-toString.patch similarity index 100% rename from Spigot-API-Patches/Provide-a-useful-PluginClassLoader-toString.patch rename to patches/api/Provide-a-useful-PluginClassLoader-toString.patch diff --git a/Spigot-API-Patches/RangedEntity-API.patch b/patches/api/RangedEntity-API.patch similarity index 95% rename from Spigot-API-Patches/RangedEntity-API.patch rename to patches/api/RangedEntity-API.patch index 333c8810a5..1f1222a73f 100644 --- a/Spigot-API-Patches/RangedEntity-API.patch +++ b/patches/api/RangedEntity-API.patch @@ -126,19 +126,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/entity/Skeleton.java +++ b/src/main/java/org/bukkit/entity/Skeleton.java @@ -0,0 +0,0 @@ package org.bukkit.entity; - - import org.jetbrains.annotations.Contract; - import org.jetbrains.annotations.NotNull; -+import com.destroystokyo.paper.entity.RangedEntity; - - /** - * Represents a Skeleton. + * Other skeleton-like entities, such as the {@link WitherSkeleton} or the + * {@link Stray} are not related to this type. */ --public interface Skeleton extends Monster { -+public interface Skeleton extends Monster, RangedEntity { // Paper +-public interface Skeleton extends AbstractSkeleton { ++public interface Skeleton extends AbstractSkeleton, com.destroystokyo.paper.entity.RangedEntity { // Paper /** - * Gets the current type of this skeleton. + * Computes whether or not this skeleton is currently in the process of diff --git a/src/main/java/org/bukkit/entity/Snowman.java b/src/main/java/org/bukkit/entity/Snowman.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/entity/Snowman.java diff --git a/Spigot-API-Patches/Reduce-thread-synchronization-in-MetadataStoreBase.patch b/patches/api/Reduce-thread-synchronization-in-MetadataStoreBase.patch similarity index 100% rename from Spigot-API-Patches/Reduce-thread-synchronization-in-MetadataStoreBase.patch rename to patches/api/Reduce-thread-synchronization-in-MetadataStoreBase.patch diff --git a/Spigot-API-Patches/Remove-deadlock-risk-in-firing-async-events.patch b/patches/api/Remove-deadlock-risk-in-firing-async-events.patch similarity index 88% rename from Spigot-API-Patches/Remove-deadlock-risk-in-firing-async-events.patch rename to patches/api/Remove-deadlock-risk-in-firing-async-events.patch index fdbc0b68ad..2728bd55ce 100644 --- a/Spigot-API-Patches/Remove-deadlock-risk-in-firing-async-events.patch +++ b/patches/api/Remove-deadlock-risk-in-firing-async-events.patch @@ -15,19 +15,6 @@ which results in a hard crash. This change removes the synchronize and adds some protection around enable/disable -diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/entity/Entity.java -+++ b/src/main/java/org/bukkit/entity/Entity.java -@@ -0,0 +0,0 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource { // Paper - -- /** -+ /* - * Gets the entity's current position - * - * @return a new copy of Location containing the position of this entity diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java diff --git a/Spigot-API-Patches/Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/api/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 patches/api/Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/Spigot-API-Patches/Server-Tick-Events.patch b/patches/api/Server-Tick-Events.patch similarity index 100% rename from Spigot-API-Patches/Server-Tick-Events.patch rename to patches/api/Server-Tick-Events.patch diff --git a/Spigot-API-Patches/Shoulder-Entities-Release-API.patch b/patches/api/Shoulder-Entities-Release-API.patch similarity index 100% rename from Spigot-API-Patches/Shoulder-Entities-Release-API.patch rename to patches/api/Shoulder-Entities-Release-API.patch diff --git a/Spigot-API-Patches/SkeletonHorse-Additions.patch b/patches/api/SkeletonHorse-Additions.patch similarity index 100% rename from Spigot-API-Patches/SkeletonHorse-Additions.patch rename to patches/api/SkeletonHorse-Additions.patch diff --git a/Spigot-API-Patches/Slime-Pathfinder-Events.patch b/patches/api/Slime-Pathfinder-Events.patch similarity index 100% rename from Spigot-API-Patches/Slime-Pathfinder-Events.patch rename to patches/api/Slime-Pathfinder-Events.patch diff --git a/Spigot-API-Patches/Spawn-Reason-API.patch b/patches/api/Spawn-Reason-API.patch similarity index 100% rename from Spigot-API-Patches/Spawn-Reason-API.patch rename to patches/api/Spawn-Reason-API.patch diff --git a/Spigot-API-Patches/Support-cancellation-supression-of-EntityDismount-Ve.patch b/patches/api/Support-cancellation-supression-of-EntityDismount-Ve.patch similarity index 100% rename from Spigot-API-Patches/Support-cancellation-supression-of-EntityDismount-Ve.patch rename to patches/api/Support-cancellation-supression-of-EntityDismount-Ve.patch diff --git a/Spigot-API-Patches/Support-components-in-ItemMeta.patch b/patches/api/Support-components-in-ItemMeta.patch similarity index 100% rename from Spigot-API-Patches/Support-components-in-ItemMeta.patch rename to patches/api/Support-components-in-ItemMeta.patch diff --git a/Spigot-API-Patches/Support-hex-colors-in-getLastColors.patch b/patches/api/Support-hex-colors-in-getLastColors.patch similarity index 100% rename from Spigot-API-Patches/Support-hex-colors-in-getLastColors.patch rename to patches/api/Support-hex-colors-in-getLastColors.patch diff --git a/Spigot-API-Patches/Tameable-getOwnerUniqueId-API.patch b/patches/api/Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from Spigot-API-Patches/Tameable-getOwnerUniqueId-API.patch rename to patches/api/Tameable-getOwnerUniqueId-API.patch diff --git a/Spigot-API-Patches/Timings-v2.patch b/patches/api/Timings-v2.patch similarity index 99% rename from Spigot-API-Patches/Timings-v2.patch rename to patches/api/Timings-v2.patch index 44ef3919e6..d95fdf4170 100644 --- a/Spigot-API-Patches/Timings-v2.patch +++ b/patches/api/Timings-v2.patch @@ -3,6 +3,8 @@ From: Aikar Date: Mon, 29 Feb 2016 18:48:17 -0600 Subject: [PATCH] Timings v2 +TODO: Add #isStopping to FullServerTickHandler#stopTiming in patch 191 +expose isRunning diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java new file mode 100644 @@ -43,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public void stopTiming() { + super.stopTiming(); -+ if (!isEnabled() || Bukkit.isStopping()) { ++ if (!isEnabled()) { + return; + } + if (TimingHistory.timedTicks % 20 == 0) { diff --git a/Spigot-API-Patches/Turtle-API.patch b/patches/api/Turtle-API.patch similarity index 100% rename from Spigot-API-Patches/Turtle-API.patch rename to patches/api/Turtle-API.patch diff --git a/Spigot-API-Patches/Use-ASM-for-event-executors.patch b/patches/api/Use-ASM-for-event-executors.patch similarity index 96% rename from Spigot-API-Patches/Use-ASM-for-event-executors.patch rename to patches/api/Use-ASM-for-event-executors.patch index 57cdbcfe52..e5e3fdfac4 100644 --- a/Spigot-API-Patches/Use-ASM-for-event-executors.patch +++ b/patches/api/Use-ASM-for-event-executors.patch @@ -5,28 +5,19 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. -diff --git a/pom.xml b/pom.xml +diff --git a/build.gradle.kts b/build.gradle.kts index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -0,0 +0,0 @@ - 9.1 - test - -+ -+ -+ org.ow2.asm -+ asm -+ 9.0 -+ -+ -+ org.ow2.asm -+ asm-commons -+ 9.0 -+ -
+--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + api("net.kyori:adventure-text-serializer-gson") + api("net.kyori:adventure-text-serializer-legacy") + api("net.kyori:adventure-text-serializer-plain") ++ api("org.ow2.asm:asm:9.0") ++ api("org.ow2.asm:asm-commons:9.0") - + compileOnly("org.apache.maven:maven-resolver-provider:3.8.1") + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") diff --git a/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java b/src/main/java/com/destroystokyo/paper/event/executor/MethodHandleEventExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/Spigot-API-Patches/Version-Command-2.0.patch b/patches/api/Version-Command-2.0.patch similarity index 100% rename from Spigot-API-Patches/Version-Command-2.0.patch rename to patches/api/Version-Command-2.0.patch diff --git a/Spigot-API-Patches/Villager-Restocks-API.patch b/patches/api/Villager-Restocks-API.patch similarity index 100% rename from Spigot-API-Patches/Villager-Restocks-API.patch rename to patches/api/Villager-Restocks-API.patch diff --git a/Spigot-API-Patches/Villager-resetOffers.patch b/patches/api/Villager-resetOffers.patch similarity index 100% rename from Spigot-API-Patches/Villager-resetOffers.patch rename to patches/api/Villager-resetOffers.patch diff --git a/Spigot-API-Patches/WitchConsumePotionEvent.patch b/patches/api/WitchConsumePotionEvent.patch similarity index 100% rename from Spigot-API-Patches/WitchConsumePotionEvent.patch rename to patches/api/WitchConsumePotionEvent.patch diff --git a/Spigot-API-Patches/WitchReadyPotionEvent.patch b/patches/api/WitchReadyPotionEvent.patch similarity index 100% rename from Spigot-API-Patches/WitchReadyPotionEvent.patch rename to patches/api/WitchReadyPotionEvent.patch diff --git a/Spigot-API-Patches/WitchThrowPotionEvent.patch b/patches/api/WitchThrowPotionEvent.patch similarity index 100% rename from Spigot-API-Patches/WitchThrowPotionEvent.patch rename to patches/api/WitchThrowPotionEvent.patch diff --git a/Spigot-API-Patches/World-view-distance-api.patch b/patches/api/World-view-distance-api.patch similarity index 100% rename from Spigot-API-Patches/World-view-distance-api.patch rename to patches/api/World-view-distance-api.patch diff --git a/Spigot-API-Patches/Zombie-API-breaking-doors.patch b/patches/api/Zombie-API-breaking-doors.patch similarity index 100% rename from Spigot-API-Patches/Zombie-API-breaking-doors.patch rename to patches/api/Zombie-API-breaking-doors.patch diff --git a/Spigot-API-Patches/add-DragonEggFormEvent.patch b/patches/api/add-DragonEggFormEvent.patch similarity index 100% rename from Spigot-API-Patches/add-DragonEggFormEvent.patch rename to patches/api/add-DragonEggFormEvent.patch diff --git a/Spigot-API-Patches/add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/api/add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from Spigot-API-Patches/add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/api/add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/Spigot-API-Patches/add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/api/add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from Spigot-API-Patches/add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/api/add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/Spigot-API-Patches/add-get-set-drop-chance-to-EntityEquipment.patch b/patches/api/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 patches/api/add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/Spigot-API-Patches/add-hand-to-BlockMultiPlaceEvent.patch b/patches/api/add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from Spigot-API-Patches/add-hand-to-BlockMultiPlaceEvent.patch rename to patches/api/add-hand-to-BlockMultiPlaceEvent.patch diff --git a/Spigot-API-Patches/add-isDeeplySleeping-to-HumanEntity.patch b/patches/api/add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from Spigot-API-Patches/add-isDeeplySleeping-to-HumanEntity.patch rename to patches/api/add-isDeeplySleeping-to-HumanEntity.patch diff --git a/Spigot-API-Patches/added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/patches/api/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 patches/api/added-2-new-TargetReasons-for-1.16-mob-behavior.patch diff --git a/Spigot-API-Patches/added-PlayerNameEntityEvent.patch b/patches/api/added-PlayerNameEntityEvent.patch similarity index 100% rename from Spigot-API-Patches/added-PlayerNameEntityEvent.patch rename to patches/api/added-PlayerNameEntityEvent.patch diff --git a/Spigot-API-Patches/added-Wither-API.patch b/patches/api/added-Wither-API.patch similarity index 100% rename from Spigot-API-Patches/added-Wither-API.patch rename to patches/api/added-Wither-API.patch diff --git a/Spigot-API-Patches/additions-to-PlayerGameModeChangeEvent.patch b/patches/api/additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from Spigot-API-Patches/additions-to-PlayerGameModeChangeEvent.patch rename to patches/api/additions-to-PlayerGameModeChangeEvent.patch diff --git a/Spigot-API-Patches/ensureServerConversions-API.patch b/patches/api/ensureServerConversions-API.patch similarity index 91% rename from Spigot-API-Patches/ensureServerConversions-API.patch rename to patches/api/ensureServerConversions-API.patch index 55f425d4d7..374584c2b8 100644 --- a/Spigot-API-Patches/ensureServerConversions-API.patch +++ b/patches/api/ensureServerConversions-API.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/inventory/ItemFactory.java @@ -0,0 +0,0 @@ public interface ItemFactory { */ - @NotNull - net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); + @Nullable + String getI18NDisplayName(@Nullable ItemStack item); + + /** + * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. @@ -42,10 +42,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 /** @@ -0,0 +0,0 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, net.kyor - public @NotNull net.kyori.adventure.text.Component displayName() { return Bukkit.getServer().getItemFactory().displayName(this); } -+ + + /** + * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. + * @@ -58,5 +57,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public ItemStack ensureServerConversions() { + return Bukkit.getServer().getItemFactory().ensureServerConversions(this); + } - // Paper end - } ++ + /** + * Gets the Display name as seen in the Client. + * Currently the server only supports the English language. To override this, diff --git a/Spigot-API-Patches/fix-Inventory-getContents-null-annotations.patch b/patches/api/fix-Inventory-getContents-null-annotations.patch similarity index 100% rename from Spigot-API-Patches/fix-Inventory-getContents-null-annotations.patch rename to patches/api/fix-Inventory-getContents-null-annotations.patch diff --git a/Spigot-API-Patches/getPlayerUniqueId-API.patch b/patches/api/getPlayerUniqueId-API.patch similarity index 100% rename from Spigot-API-Patches/getPlayerUniqueId-API.patch rename to patches/api/getPlayerUniqueId-API.patch diff --git a/Spigot-API-Patches/isChunkGenerated-API.patch b/patches/api/isChunkGenerated-API.patch similarity index 95% rename from Spigot-API-Patches/isChunkGenerated-API.patch rename to patches/api/isChunkGenerated-API.patch index fcf1dded40..c2284fe9ca 100644 --- a/Spigot-API-Patches/isChunkGenerated-API.patch +++ b/patches/api/isChunkGenerated-API.patch @@ -38,9 +38,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -0,0 +0,0 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + public default Chunk getChunkAt(long chunkKey) { return getChunkAt((int) chunkKey, (int) (chunkKey >> 32)); } - ++ + /** + * Checks if a {@link Chunk} has been generated at the specified chunk key, + * which is the X and Z packed into a long. @@ -51,7 +52,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public default boolean isChunkGenerated(long chunkKey) { + return isChunkGenerated((int) chunkKey, (int) (chunkKey >> 32)); + } -+ + // Paper end + /** - * This is the Legacy API before Java 8 was supported. Java 8 Consumer is provided, - * as well as future support diff --git a/Spigot-API-Patches/living-entity-allow-attribute-registration.patch b/patches/api/living-entity-allow-attribute-registration.patch similarity index 100% rename from Spigot-API-Patches/living-entity-allow-attribute-registration.patch rename to patches/api/living-entity-allow-attribute-registration.patch diff --git a/Spigot-Server-Patches/API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server/API-to-get-a-BlockState-without-a-snapshot.patch similarity index 75% rename from Spigot-Server-Patches/API-to-get-a-BlockState-without-a-snapshot.patch rename to patches/server/API-to-get-a-BlockState-without-a-snapshot.patch index 3037240c80..52a62cf0cc 100644 --- a/Spigot-Server-Patches/API-to-get-a-BlockState-without-a-snapshot.patch +++ b/patches/server/API-to-get-a-BlockState-without-a-snapshot.patch @@ -12,41 +12,43 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.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; +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + this.type = type; + this.worldPosition = pos.immutable(); + this.blockState = state; + 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 +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - 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 - read container + public void load(CompoundTag nbt) { +- this.persistentDataContainer = new CraftPersistentDataContainer(BlockEntity.DATA_TYPE_REGISTRY); ++ this.persistentDataContainer.clear(); + + net.minecraft.nbt.Tag persistentDataTag = nbt.get("PublicBukkitValues"); + if (persistentDataTag instanceof CompoundTag) { +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { } // CraftBukkit start - add method + // Paper start public InventoryHolder getOwner() { +- if (this.level == null) return null; + return getOwner(true); + } + public InventoryHolder getOwner(boolean useSnapshot) { + // Paper end - if (world == null) return null; ++ if (level == 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 { / + org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ()); + if (block == null) { +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { return null; } // Spigot end @@ -63,6 +65,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public BlockState getState() { +- Material material = this.getType(); + // Paper start - allow disabling the use of snapshots + return getState(true); + } @@ -77,15 +80,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + public BlockState getState0() { + // Paper end - Material material = getType(); ++ Material material = getType(); switch (material) { + case ACACIA_SIGN: 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())); +@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockStat + this.tileEntity = tileEntityClass.cast(world.getHandle().getBlockEntity(this.getPosition())); Preconditions.checkState(this.tileEntity != null, "Tile is null, asynchronous access? %s", block); + // Paper start @@ -136,7 +140,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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()); + return (Map) CraftNBTTagConfigSerializer.serialize(this.toTagCompound()); } + + // Paper start diff --git a/patches/server/Ability-to-apply-mending-to-XP-API.patch b/patches/server/Ability-to-apply-mending-to-XP-API.patch new file mode 100644 index 0000000000..d4132ad311 --- /dev/null +++ b/patches/server/Ability-to-apply-mending-to-XP-API.patch @@ -0,0 +1,87 @@ +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/item/enchantment/EnchantmentHelper.java b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/EnchantmentHelper.java +@@ -0,0 +0,0 @@ public class EnchantmentHelper { + return getItemEnchantmentLevel(Enchantments.CHANNELING, stack) > 0; + } + +- @Nullable +- public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { ++ @Deprecated public static @javax.annotation.Nonnull ItemStack getRandomEquippedItemWithEnchant(Enchantment enchantment, LivingEntity entityliving) { ++ Entry entry = getRandomItemWith(enchantment, entityliving); ++ return entry != null ? entry.getValue() : ItemStack.EMPTY; ++ } // Paper - OBFHELPER ++ @Nullable public static Entry getRandomItemWith(Enchantment enchantment, LivingEntity entity) { + return getRandomItemWith(enchantment, entity, (stack) -> { + 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.ServerPlayer; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.players.UserWhiteListEntry; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeMap; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.inventory.AbstractContainerMenu; ++import net.minecraft.world.item.enchantment.EnchantmentHelper; ++import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.SignBlockEntity; +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + return GameMode.getByValue(this.getHandle().gameMode.getGameModeForPlayer().getId()); + } + ++ // Paper start ++ @Override ++ public int applyMending(int amount) { ++ ServerPlayer handle = getHandle(); ++ // Logic copied from EntityExperienceOrb and remapped to unobfuscated methods/properties ++ net.minecraft.world.item.ItemStack itemstack = EnchantmentHelper.getRandomEquippedItemWithEnchant(Enchantments.MENDING, handle); ++ if (!itemstack.isEmpty() && itemstack.getItem().canBeDepleted()) { ++ ++ ExperienceOrb orb = net.minecraft.world.entity.EntityType.EXPERIENCE_ORB.create(handle.level); ++ orb.value = amount; ++ orb.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM; ++ orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ()); ++ ++ int i = Math.min(orb.xpToDurability(amount), itemstack.getDamageValue()); ++ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, i); ++ i = event.getRepairAmount(); ++ orb.discard(); ++ if (!event.isCancelled()) { ++ amount -= orb.durabilityToXp(i); ++ itemstack.setDamageValue(itemstack.getDamageValue() - i); ++ } ++ } ++ return amount; ++ } ++ + @Override +- public void giveExp(int exp) { ++ public void giveExp(int exp, boolean applyMending) { ++ if (applyMending) { ++ exp = this.applyMending(exp); ++ } ++ // Paper end + this.getHandle().giveExperiencePoints(exp); + } + diff --git a/Spigot-Server-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 66% rename from Spigot-Server-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/server/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch index 960d694ea2..ec80f5732d 100644 --- a/Spigot-Server-Patches/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch +++ b/patches/server/Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch @@ -5,10 +5,10 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.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 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -0,0 +0,0 @@ package net.minecraft.server.network; @@ -17,17 +17,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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; +@@ -0,0 +0,0 @@ import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; 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; +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId(); + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId); + // Paper start @@ -36,9 +36,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); + profile.complete(); -+ i = CraftPlayerProfile.asAuthlibCopy(profile); -+ playerName = i.getName(); -+ uniqueId = i.getId(); ++ gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); ++ playerName = gameProfile.getName(); ++ uniqueId = gameProfile.getId(); + // Paper end if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) { diff --git a/Spigot-Server-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/server/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 69% rename from Spigot-Server-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/server/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch index ffff74d637..722548d1fb 100644 --- a/Spigot-Server-Patches/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch +++ b/patches/server/Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch @@ -17,8 +17,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import java.util.Collection; +import java.util.List; import java.util.function.Predicate; - import net.minecraft.core.BlockPosition; - import net.minecraft.core.IRegistry; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Registry; @@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { @Override @@ -29,45 +29,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @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(); - + if (!this.isLoaded()) { + this.getWorld().getChunkAt(x, z); // Transient load for this tick + } @@ -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 + BlockPos position = (BlockPos) obj; +- entities[index++] = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(); ++ // Paper start ++ entities[index++] = this.worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()).getState(useSnapshot); + } + + 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(); ++ net.minecraft.world.level.chunk.LevelChunk chunk = getHandle(); + + List entities = new ArrayList<>(); + -+ for (BlockPosition position : chunk.tileEntities.keySet()) { ++ for (BlockPos position : chunk.blockEntities.keySet()) { + Block block = worldServer.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()); + if (blockPredicate.test(block)) { + entities.add(block.getState(useSnapshot)); + } ++ // Paper end } return entities; - } -+ // Paper end - - @Override - public boolean isLoaded() { diff --git a/patches/server/Add-API-for-quit-reason.patch b/patches/server/Add-API-for-quit-reason.patch new file mode 100644 index 0000000000..ac7f491acb --- /dev/null +++ b/patches/server/Add-API-for-quit-reason.patch @@ -0,0 +1,63 @@ +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/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + + this.handlingFault = true; + if (this.channel.isOpen()) { ++ net.minecraft.server.level.ServerPlayer player = this.getPlayer(); // Paper + if (throwable instanceof TimeoutException) { + Connection.LOGGER.debug("Timeout", throwable); ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.TIMED_OUT; // Paper + this.disconnect(new TranslatableComponent("disconnect.timeout")); + } else { + TranslatableComponent chatmessage = new TranslatableComponent("disconnect.genericReason", new Object[]{"Internal Exception: " + throwable}); + ++ if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper + if (flag) { + Connection.LOGGER.debug("Failed to sent packet", throwable); + ConnectionProtocol enumprotocol = this.getCurrentProtocol(); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + 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 ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure + // CraftBukkit end + ++ this.player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.KICKED; // Paper + this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { + this.connection.disconnect(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.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.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.getScoreboardName()))); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.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.getScoreboardName())), entityplayer.quitReason); // Paper - quit reason + if (entityplayer.didPlayerJoinEvent) this.cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + diff --git a/patches/server/Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/server/Add-API-methods-to-control-if-armour-stands-can-move.patch new file mode 100644 index 0000000000..9ac3870b3f --- /dev/null +++ b/patches/server/Add-API-methods-to-control-if-armour-stands-can-move.patch @@ -0,0 +1,52 @@ +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/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + public Rotations rightArmPose; + public Rotations leftLegPose; + public Rotations rightLegPose; ++ public boolean canMove = true; // Paper + + public ArmorStand(EntityType type, Level world) { + super(type, world); +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + public boolean canBeSeenByAnyone() { + return !this.isInvisible() && !this.isMarker(); + } ++ ++ // Paper start ++ @Override ++ public void move(net.minecraft.world.entity.MoverType type, Vec3 movement) { ++ if (this.canMove) { ++ super.move(type, movement); ++ } ++ } ++ // 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 (this.getHandle().disabledSlots & (1 << CraftEquipmentSlot.getNMS(equipmentSlot).getFilterFlag() + 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/patches/server/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 69% rename from Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/server/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch index 2d75b4559a..39463b1b23 100644 --- a/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ b/patches/server/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -15,18 +15,18 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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; +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public int latency; + public boolean wonGame; 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; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket 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 @@ -34,17 +34,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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()); + public void placeNewPlayer(Connection connection, ServerPlayer player) { ++ player.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = player.getGameProfile(); + GameProfileCache usercache = this.server.getProfileCache(); + GameProfile gameprofile1 = usercache.get(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; + return this.getData() != null; } + // Paper start @@ -53,10 +53,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + Player player = getPlayer(); + if (player != null) return player.getLastLogin(); + -+ NBTTagCompound data = getPaperData(); ++ CompoundTag data = getPaperData(); + + if (data != null) { -+ if (data.hasKey("LastLogin")) { ++ if (data.contains("LastLogin")) { + return data.getLong("LastLogin"); + } else { + // if the player file cannot provide accurate data, this is probably the closest we can approximate @@ -73,10 +73,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + Player player = getPlayer(); + if (player != null) return player.getLastSeen(); + -+ NBTTagCompound data = getPaperData(); ++ CompoundTag data = getPaperData(); + + if (data != null) { -+ if (data.hasKey("LastSeen")) { ++ if (data.contains("LastSeen")) { + return data.getLong("LastSeen"); + } else { + // if the player file cannot provide accurate data, this is probably the closest we can approximate @@ -88,12 +88,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private NBTTagCompound getPaperData() { -+ NBTTagCompound result = getData(); ++ private CompoundTag getPaperData() { ++ CompoundTag result = getData(); + + if (result != null) { -+ if (!result.hasKey("Paper")) { -+ result.set("Paper", new NBTTagCompound()); ++ if (!result.contains("Paper")) { ++ result.put("Paper", new CompoundTag()); + } + result = result.getCompound("Paper"); + } @@ -104,7 +104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public Location getBedSpawnLocation() { - NBTTagCompound data = getData(); + CompoundTag data = this.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 @@ -116,7 +116,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private long lastSaveTime; // Paper end - public CraftPlayer(CraftServer server, EntityPlayer entity) { + public CraftPlayer(CraftServer server, ServerPlayer entity) { @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.firstPlayed = firstPlayed; } @@ -133,31 +133,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + - public void readExtraData(NBTTagCompound nbttagcompound) { - hasPlayedBefore = true; - if (nbttagcompound.hasKey("bukkit")) { + public void readExtraData(CompoundTag nbttagcompound) { + this.hasPlayedBefore = true; + if (nbttagcompound.contains("bukkit")) { @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } - public void setExtraData(NBTTagCompound nbttagcompound) { + public void setExtraData(CompoundTag nbttagcompound) { + this.lastSaveTime = System.currentTimeMillis(); // Paper + - if (!nbttagcompound.hasKey("bukkit")) { - nbttagcompound.set("bukkit", new NBTTagCompound()); + if (!nbttagcompound.contains("bukkit")) { + nbttagcompound.put("bukkit", new CompoundTag()); } @@ -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()); + data.putLong("firstPlayed", this.getFirstPlayed()); + data.putLong("lastPlayed", System.currentTimeMillis()); + data.putString("lastKnownName", handle.getScoreboardName()); + + // Paper start - persist for use in offline save data -+ if (!nbttagcompound.hasKey("Paper")) { -+ nbttagcompound.set("Paper", new NBTTagCompound()); ++ if (!nbttagcompound.contains("Paper")) { ++ nbttagcompound.put("Paper", new CompoundTag()); + } + -+ NBTTagCompound paper = nbttagcompound.getCompound("Paper"); -+ paper.setLong("LastLogin", handle.loginTime); -+ paper.setLong("LastSeen", System.currentTimeMillis()); ++ CompoundTag paper = nbttagcompound.getCompound("Paper"); ++ paper.putLong("LastLogin", handle.loginTime); ++ paper.putLong("LastSeen", System.currentTimeMillis()); + // Paper end } diff --git a/patches/server/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/server/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch new file mode 100644 index 0000000000..69390f83ec --- /dev/null +++ b/patches/server/Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch @@ -0,0 +1,32 @@ +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/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -0,0 +0,0 @@ public class PlayerAdvancements { + this.progressChanged.add(advancement); + flag = true; + if (!flag1 && advancementprogress.isDone()) { +- this.player.level.getCraftServer().getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit)); // CraftBukkit ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ boolean announceToChat = advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat(); ++ net.kyori.adventure.text.Component message = announceToChat ? io.papermc.paper.adventure.PaperAdventure.asAdventure(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), this.player.getDisplayName(), advancement.getChatComponent())) : null; ++ org.bukkit.event.player.PlayerAdvancementDoneEvent event = new org.bukkit.event.player.PlayerAdvancementDoneEvent(this.player.getBukkitEntity(), advancement.bukkit, message); ++ this.player.level.getCraftServer().getPluginManager().callEvent(event); ++ message = event.message(); ++ // Paper end + advancement.getRewards().grant(this.player); +- if (advancement.getDisplay() != null && advancement.getDisplay().shouldAnnounceChat() && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { +- this.playerList.broadcastMessage(new TranslatableComponent("chat.type.advancement." + advancement.getDisplay().getFrame().getName(), new Object[]{this.player.getDisplayName(), advancement.getChatComponent()}), ChatType.SYSTEM, Util.NIL_UUID); ++ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent ++ if (message != null && this.player.level.getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) { ++ this.playerList.broadcastMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), ChatType.SYSTEM, Util.NIL_UUID); ++ // Paper end + } + } + } diff --git a/Spigot-Server-Patches/Add-ArmorStand-Item-Meta.patch b/patches/server/Add-ArmorStand-Item-Meta.patch similarity index 74% rename from Spigot-Server-Patches/Add-ArmorStand-Item-Meta.patch rename to patches/server/Add-ArmorStand-Item-Meta.patch index 1e178065fb..5c99375f83 100644 --- a/Spigot-Server-Patches/Add-ArmorStand-Item-Meta.patch +++ b/patches/server/Add-ArmorStand-Item-Meta.patch @@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private boolean small; + private boolean marker; + // Paper end - NBTTagCompound entityTag; + CompoundTag entityTag; CraftMetaArmorStand(CraftMetaItem meta) { @@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { @@ -56,27 +56,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - if (tag.hasKey(ENTITY_TAG.NBT)) { - entityTag = tag.getCompound(ENTITY_TAG.NBT); + if (tag.contains(ENTITY_TAG.NBT)) { + this.entityTag = tag.getCompound(ENTITY_TAG.NBT); + + // Paper start -+ if (entityTag.hasKey(INVISIBLE.NBT)) { ++ if (entityTag.contains(INVISIBLE.NBT)) { + invisible = entityTag.getBoolean(INVISIBLE.NBT); + } + -+ if (entityTag.hasKey(NO_BASE_PLATE.NBT)) { ++ if (entityTag.contains(NO_BASE_PLATE.NBT)) { + noBasePlate = entityTag.getBoolean(NO_BASE_PLATE.NBT); + } + -+ if (entityTag.hasKey(SHOW_ARMS.NBT)) { ++ if (entityTag.contains(SHOW_ARMS.NBT)) { + showArms = entityTag.getBoolean(SHOW_ARMS.NBT); + } + -+ if (entityTag.hasKey(SMALL.NBT)) { ++ if (entityTag.contains(SMALL.NBT)) { + small = entityTag.getBoolean(SMALL.NBT); + } + -+ if (entityTag.hasKey(MARKER.NBT)) { ++ if (entityTag.contains(MARKER.NBT)) { + marker = entityTag.getBoolean(MARKER.NBT); + } + // Paper end @@ -85,62 +85,54 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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; ++ this.invisible = SerializableMeta.getBoolean(map, INVISIBLE.BUKKIT); ++ this.noBasePlate = SerializableMeta.getBoolean(map, NO_BASE_PLATE.BUKKIT); ++ this.showArms = SerializableMeta.getBoolean(map, SHOW_ARMS.BUKKIT); ++ this.small = SerializableMeta.getBoolean(map, SMALL.BUKKIT); ++ this.marker = SerializableMeta.getBoolean(map, MARKER.BUKKIT); + // Paper end } @Override @@ -0,0 +0,0 @@ public class CraftMetaArmorStand extends CraftMetaItem { - void applyToItem(NBTTagCompound tag) { + void applyToItem(CompoundTag tag) { super.applyToItem(tag); + // Paper start -+ if (!isArmorStandEmpty() && entityTag == null) { -+ entityTag = new NBTTagCompound(); ++ if (!isArmorStandEmpty() && this.entityTag == null) { ++ this.entityTag = new CompoundTag(); + } + + if (isInvisible()) { -+ entityTag.setBoolean(INVISIBLE.NBT, invisible); ++ this.entityTag.putBoolean(INVISIBLE.NBT, this.invisible); + } + + if (hasNoBasePlate()) { -+ entityTag.setBoolean(NO_BASE_PLATE.NBT, noBasePlate); ++ this.entityTag.putBoolean(NO_BASE_PLATE.NBT, this.noBasePlate); + } + + if (shouldShowArms()) { -+ entityTag.setBoolean(SHOW_ARMS.NBT, showArms); ++ this.entityTag.putBoolean(SHOW_ARMS.NBT, this.showArms); + } + + if (isSmall()) { -+ entityTag.setBoolean(SMALL.NBT, small); ++ this.entityTag.putBoolean(SMALL.NBT, this.small); + } + + if (isMarker()) { -+ entityTag.setBoolean(MARKER.NBT, marker); ++ this.entityTag.putBoolean(MARKER.NBT, this.marker); + } + // Paper end -+ - if (entityTag != null) { - tag.set(ENTITY_TAG.NBT, entityTag); + if (this.entityTag != null) { + tag.put(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); +- return !(this.entityTag != null); ++ return !(this.isInvisible() || this.hasNoBasePlate() || this.shouldShowArms() || this.isSmall() || this.isMarker() || this.entityTag != null); } @Override @@ -148,13 +140,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (meta instanceof CraftMetaArmorStand) { CraftMetaArmorStand that = (CraftMetaArmorStand) meta; -- return entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : entityTag == null; +- return this.entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : this.entityTag == null; + // Paper start -+ return invisible == that.invisible && -+ noBasePlate == that.noBasePlate && -+ showArms == that.showArms && -+ small == that.small && -+ marker == that.marker; ++ return this.invisible == that.invisible && ++ this.noBasePlate == that.noBasePlate && ++ this.showArms == that.showArms && ++ this.small == that.small && ++ this.marker == that.marker; + // Paper end } return true; @@ -163,16 +155,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 final int original; int hash = original = super.applyHash(); -- if (entityTag != null) { -- hash = 73 * hash + entityTag.hashCode(); +- if (this.entityTag != null) { +- hash = 73 * hash + this.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; ++ hash += this.entityTag != null ? 73 * hash + this.entityTag.hashCode() : 0; ++ hash += this.isInvisible() ? 61 * hash + 1231 : 0; ++ hash += this.hasNoBasePlate() ? 61 * hash + 1231 : 0; ++ hash += this.shouldShowArms() ? 61 * hash + 1231 : 0; ++ hash += this.isSmall() ? 61 * hash + 1231 : 0; ++ hash += this.isMarker() ? 61 * hash + 1231 : 0; + // Paper end return original != hash ? CraftMetaArmorStand.class.hashCode() ^ hash : hash; @@ -182,23 +174,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 super.serialize(builder); + // Paper start -+ if (isInvisible()) { ++ if (this.isInvisible()) { + builder.put(INVISIBLE.BUKKIT, invisible); + } + -+ if (hasNoBasePlate()) { ++ if (this.hasNoBasePlate()) { + builder.put(NO_BASE_PLATE.BUKKIT, noBasePlate); + } + -+ if (shouldShowArms()) { ++ if (this.shouldShowArms()) { + builder.put(SHOW_ARMS.BUKKIT, showArms); + } + -+ if (isSmall()) { ++ if (this.isSmall()) { + builder.put(SMALL.BUKKIT, small); + } + -+ if (isMarker()) { ++ if (this.isMarker()) { + builder.put(MARKER.BUKKIT, marker); + } + // Paper end @@ -281,15 +273,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end CraftMetaCompass.LODESTONE_DIMENSION.NBT, CraftMetaCompass.LODESTONE_POS.NBT, - CraftMetaCompass.LODESTONE_TRACKED.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.entityTag = new CompoundTag(); + meta.entityTag.putBoolean("Small", true); + meta.setInvisible(true); // Paper cleanStack.setItemMeta(meta); return cleanStack; diff --git a/patches/server/Add-BeaconEffectEvent.patch b/patches/server/Add-BeaconEffectEvent.patch new file mode 100644 index 0000000000..411c23067c --- /dev/null +++ b/patches/server/Add-BeaconEffectEvent.patch @@ -0,0 +1,62 @@ +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/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -0,0 +0,0 @@ import net.minecraft.world.phys.AABB; + import org.bukkit.craftbukkit.potion.CraftPotionUtil; + import org.bukkit.potion.PotionEffect; + // CraftBukkit end ++// Paper start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import com.destroystokyo.paper.event.block.BeaconEffectEvent; ++// Paper end + + public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + } + +- private static void applyEffect(List list, MobEffect mobeffectlist, int j, int b0) { +- { ++ private static void applyEffect(List list, MobEffect effects, int i, int b0, boolean isPrimary, BlockPos worldPosition) { // Paper - BeaconEffectEvent ++ if (!list.isEmpty()) { // Paper - BeaconEffectEvent + Iterator iterator = list.iterator(); + + Player entityhuman; ++ // Paper start - BeaconEffectEvent ++ org.bukkit.block.Block block = ((Player) list.get(0)).level.getWorld().getBlockAt(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); ++ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(effects, i, b0, true, true)); ++ // Paper end + + while (iterator.hasNext()) { +- entityhuman = (Player) iterator.next(); +- entityhuman.addEffect(new MobEffectInstance(mobeffectlist, j, b0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ // Paper start - BeaconEffectEvent ++ entityhuman = (ServerPlayer) iterator.next(); ++ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (org.bukkit.entity.Player) entityhuman.getBukkitEntity(), isPrimary); ++ if (CraftEventFactory.callEvent(event).isCancelled()) continue; ++ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON); ++ // Paper end + } + } + } +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + int j = BeaconBlockEntity.getLevel(beaconLevel); + List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel); + +- BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0); ++ BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent + + if (BeaconBlockEntity.hasSecondaryEffect(beaconLevel, primaryEffect, secondaryEffect)) { +- BeaconBlockEntity.applyEffect(list, secondaryEffect, j, 0); ++ BeaconBlockEntity.applyEffect(list, secondaryEffect, j, 0, false, pos); // Paper - BeaconEffectEvent + } + } + diff --git a/patches/server/Add-BellRevealRaiderEvent.patch b/patches/server/Add-BellRevealRaiderEvent.patch new file mode 100644 index 0000000000..d811b71a8e --- /dev/null +++ b/patches/server/Add-BellRevealRaiderEvent.patch @@ -0,0 +1,32 @@ +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/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -0,0 +0,0 @@ public class BellBlockEntity extends BlockEntity { + private static void makeRaidersGlow(Level world, BlockPos pos, List hearingEntities) { + hearingEntities.stream().filter((livingEntity) -> { + return isRaiderWithinRange(pos, livingEntity); +- }).forEach(BellBlockEntity::glow); ++ }).forEach(entity -> glow(entity, pos)); // Paper - pass BlockPos + } + + private static void showBellParticles(Level world, BlockPos pos, List hearingEntities) { +@@ -0,0 +0,0 @@ public class BellBlockEntity extends BlockEntity { + return entity.isAlive() && !entity.isRemoved() && pos.closerThan(entity.position(), 48.0D) && entity.getType().is(EntityTypeTags.RAIDERS); + } + +- private static void glow(LivingEntity entity) { ++ // Paper start ++ private static void glow(LivingEntity entity) { glow(entity, null); } ++ private static void glow(LivingEntity entity, BlockPos pos) { ++ if (pos != null && !new io.papermc.paper.event.block.BellRevealRaiderEvent(entity.level.getWorld().getBlockAt(net.minecraft.server.MCUtil.toLocation(entity.level, pos)), entity.getBukkitEntity()).callEvent()) return; ++ // Paper end + entity.addEffect(new MobEffectInstance(MobEffects.GLOWING, 60)); + } + diff --git a/patches/server/Add-BellRingEvent.patch b/patches/server/Add-BellRingEvent.patch new file mode 100644 index 0000000000..9ad0b5d8c5 --- /dev/null +++ b/patches/server/Add-BellRingEvent.patch @@ -0,0 +1,28 @@ +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/BellBlock.java b/src/main/java/net/minecraft/world/level/block/BellBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BellBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BellBlock.java +@@ -0,0 +0,0 @@ package net.minecraft.world.level.block; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.stats.Stats; +@@ -0,0 +0,0 @@ public class BellBlock extends BaseEntityBlock { + direction = world.getBlockState(pos).getValue(FACING); + } + ++ if (!new io.papermc.paper.event.block.BellRingEvent(world.getWorld().getBlockAt(MCUtil.toLocation(world, pos)), entity == null ? null : entity.getBukkitEntity()).callEvent()) return false; // Paper - BellRingEvent + ((BellBlockEntity)blockEntity).onHit(direction); + world.playSound((Player)null, pos, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0F, 1.0F); + world.gameEvent(entity, GameEvent.RING_BELL, pos); diff --git a/Spigot-Server-Patches/Add-Block-isValidTool.patch b/patches/server/Add-Block-isValidTool.patch similarity index 100% rename from Spigot-Server-Patches/Add-Block-isValidTool.patch rename to patches/server/Add-Block-isValidTool.patch diff --git a/Spigot-Server-Patches/Add-Channel-initialization-listeners.patch b/patches/server/Add-Channel-initialization-listeners.patch similarity index 88% rename from Spigot-Server-Patches/Add-Channel-initialization-listeners.patch rename to patches/server/Add-Channel-initialization-listeners.patch index a549544f8f..8da1b9d013 100644 --- a/Spigot-Server-Patches/Add-Channel-initialization-listeners.patch +++ b/patches/server/Add-Channel-initialization-listeners.patch @@ -105,15 +105,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } +} -diff --git a/src/main/java/net/minecraft/server/network/ServerConnection.java b/src/main/java/net/minecraft/server/network/ServerConnection.java +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.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 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + pending.add((Connection) object); // Paper channel.pipeline().addLast("packet_handler", (ChannelHandler) object); - ((NetworkManager) object).setPacketListener(new HandshakeListener(ServerConnection.this.e, (NetworkManager) object)); + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) 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.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit } diff --git a/Spigot-Server-Patches/Add-CraftMagicNumbers.isSupportedApiVersion.patch b/patches/server/Add-CraftMagicNumbers.isSupportedApiVersion.patch similarity index 100% rename from Spigot-Server-Patches/Add-CraftMagicNumbers.isSupportedApiVersion.patch rename to patches/server/Add-CraftMagicNumbers.isSupportedApiVersion.patch diff --git a/patches/server/Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch b/patches/server/Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch new file mode 100644 index 0000000000..154a7611b5 --- /dev/null +++ b/patches/server/Add-Debug-Entities-option-to-debug-dupe-uuid-issues.patch @@ -0,0 +1,139 @@ +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 + +1.17: Needs to be reworked for new entity storage system + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); + ++ entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); + playerchunkmap_entitytracker.updatePlayers(this.level.players()); + if (entity instanceof ServerPlayer) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (playerchunkmap_entitytracker1 != null) { + playerchunkmap_entitytracker1.broadcastRemoved(); + } +- ++ entity.tracker = null; // Paper - We're no longer tracked + } + + protected void tick() { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ public static Throwable getAddToWorldStackTrace(Entity entity) { ++ return new Throwable(entity + " Added to world at " + new java.util.Date()); ++ } + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot ++ // 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.isRemoved()) { ++ // 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 { +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 Nameable, EntityAccess, CommandSource, n + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper + private CraftEntity bukkitEntity; + ++ public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper ++ public Throwable addedToWorldStack; // Paper - entity debug + public CraftEntity getBukkitEntity() { + if (this.bukkitEntity == null) { + this.bukkitEntity = CraftEntity.getEntity(this.level.getCraftServer(), this); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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/src/main/java/net/minecraft/world/level/entity/EntityLookup.java b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/entity/EntityLookup.java ++++ b/src/main/java/net/minecraft/world/level/entity/EntityLookup.java +@@ -0,0 +0,0 @@ public class EntityLookup { + for(T entityAccess : this.byId.values()) { + U entityAccess2 = (U)((EntityAccess)filter.tryCast(entityAccess)); + if (entityAccess2 != null) { +- action.accept((T)entityAccess2); ++ action.accept(entityAccess2); // Paper - decompile fix + } + } + +@@ -0,0 +0,0 @@ public class EntityLookup { + UUID uUID = entity.getUUID(); + if (this.byUuid.containsKey(uUID)) { + LOGGER.warn("Duplicate entity UUID {}: {}", uUID, entity); ++ // Paper start - extra debug info ++ if (entity instanceof net.minecraft.world.entity.Entity) { ++ if (net.minecraft.server.level.ServerLevel.DEBUG_ENTITIES) { ++ ((net.minecraft.world.entity.Entity) entity).addedToWorldStack = net.minecraft.server.level.ServerLevel.getAddToWorldStackTrace((net.minecraft.world.entity.Entity) entity); ++ } ++ ++ T old = this.byUuid.get(entity.getUUID()); ++ if (old instanceof net.minecraft.world.entity.Entity && old != null && old.getId() != entity.getId() && ((net.minecraft.world.entity.Entity) old).valid) { ++ Logger logger = LogManager.getLogger(); ++ logger.error("Overwrote an existing entity " + old + " with " + entity); ++ if (net.minecraft.server.level.ServerLevel.DEBUG_ENTITIES) { ++ if (((net.minecraft.world.entity.Entity) old).addedToWorldStack != null) { ++ ((net.minecraft.world.entity.Entity) old).addedToWorldStack.printStackTrace(); ++ } else { ++ logger.error("Oddly, the old entity was not added to the world in the normal way. Plugins?"); ++ } ++ ((net.minecraft.world.entity.Entity) entity).addedToWorldStack.printStackTrace(); ++ } ++ } ++ } ++ // Paper end + } else { + this.byUuid.put(uUID, entity); + this.byId.put(entity.getId(), entity); diff --git a/Spigot-Server-Patches/Add-Destroy-Speed-API.patch b/patches/server/Add-Destroy-Speed-API.patch similarity index 85% rename from Spigot-Server-Patches/Add-Destroy-Speed-API.patch rename to patches/server/Add-Destroy-Speed-API.patch index cbe2771a5c..85196c63a1 100644 --- a/Spigot-Server-Patches/Add-Destroy-Speed-API.patch +++ b/patches/server/Add-Destroy-Speed-API.patch @@ -18,13 +18,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public float getDestroySpeed(ItemStack itemStack, boolean considerEnchants) { + net.minecraft.world.item.ItemStack nmsItemStack; + if (itemStack instanceof CraftItemStack) { -+ nmsItemStack = ((CraftItemStack) itemStack).getHandle(); ++ nmsItemStack = ((CraftItemStack) itemStack).handle; + } else { + nmsItemStack = CraftItemStack.asNMSCopy(itemStack); + } -+ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().getBlockData()); ++ float speed = nmsItemStack.getItem().getDestroySpeed(nmsItemStack, this.getNMSBlock().defaultBlockState()); + if (speed > 1.0F && considerEnchants) { -+ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentManager.getEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.DIG_SPEED, nmsItemStack); ++ int enchantLevel = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.BLOCK_EFFICIENCY, nmsItemStack); + if (enchantLevel > 0) { + speed += enchantLevel * enchantLevel + 1; + } diff --git a/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/Add-Early-Warning-Feature-to-WatchDog.patch similarity index 82% rename from Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch rename to patches/server/Add-Early-Warning-Feature-to-WatchDog.patch index 205a6d63ae..384813dfb5 100644 --- a/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch +++ b/patches/server/Add-Early-Warning-Feature-to-WatchDog.patch @@ -39,8 +39,8 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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 + // +- if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.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") ) ++ long currentTime = WatchdogThread.monotonicMillis(); ++ if ( this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable { - Logger log = Bukkit.getServer().getLogger(); + boolean isLongTimeout = currentTime > lastTick + timeoutTime; @@ -146,7 +145,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 ); + WatchdogThread.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 @@ -156,18 +155,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); for ( ThreadInfo thread : threads ) { - dumpThread( thread, log ); + WatchdogThread.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() ) + if ( this.restart && !MinecraftServer.getServer().hasStopped() ) { RestartCommand.restart(); } diff --git a/patches/server/Add-ElderGuardianAppearanceEvent.patch b/patches/server/Add-ElderGuardianAppearanceEvent.patch new file mode 100644 index 0000000000..7490bd0b04 --- /dev/null +++ b/patches/server/Add-ElderGuardianAppearanceEvent.patch @@ -0,0 +1,23 @@ +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/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -0,0 +0,0 @@ public class ElderGuardian extends Guardian { + while (iterator.hasNext()) { + ServerPlayer entityplayer = (ServerPlayer) 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.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); + entityplayer.addEffect(new MobEffectInstance(mobeffectlist, 6000, 2), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } ++ } // Paper - Add Guardian Appearance Event + } + } + diff --git a/Spigot-Server-Patches/Add-EntityBlockStorage-clearEntities.patch b/patches/server/Add-EntityBlockStorage-clearEntities.patch similarity index 63% rename from Spigot-Server-Patches/Add-EntityBlockStorage-clearEntities.patch rename to patches/server/Add-EntityBlockStorage-clearEntities.patch index eba70612e7..04569f62f8 100644 --- a/Spigot-Server-Patches/Add-EntityBlockStorage-clearEntities.patch +++ b/patches/server/Add-EntityBlockStorage-clearEntities.patch @@ -4,29 +4,29 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.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(); +--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -0,0 +0,0 @@ public class BeehiveBlockEntity extends BlockEntity { + return this.stored.size(); } + // Paper start - Add EntityBlockStorage clearEntities + public void clearBees() { -+ this.bees.clear(); ++ this.stored.clear(); + } + // Paper end - public static int a(IBlockData iblockdata) { - return (Integer) iblockdata.get(BlockBeehive.b); + public static int getHoneyLevel(BlockState state) { + return (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL); } 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 +@@ -0,0 +0,0 @@ public class CraftBeehive extends CraftBlockEntityState impl - getSnapshot().addBee(((CraftBee) entity).getHandle(), false); + getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false); } + // Paper start - Add EntityBlockStorage clearEntities + @Override diff --git a/patches/server/Add-EntityInsideBlockEvent.patch b/patches/server/Add-EntityInsideBlockEvent.patch new file mode 100644 index 0000000000..0a4c58a87b --- /dev/null +++ b/patches/server/Add-EntityInsideBlockEvent.patch @@ -0,0 +1,246 @@ +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/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +@@ -0,0 +0,0 @@ public abstract class BaseFireBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.fireImmune()) { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() + 1); + if (entity.getRemainingFireTicks() == 0) { +diff --git a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -0,0 +0,0 @@ public abstract class BasePressurePlateBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + int i = this.getSignalForState(state); + +diff --git a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BubbleColumnBlock.java +@@ -0,0 +0,0 @@ public class BubbleColumnBlock extends Block implements BucketPickup { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + BlockState blockState = world.getBlockState(pos.above()); + if (blockState.isAir()) { + entity.onAboveBubbleCol(state.getValue(DRAG_DOWN)); +diff --git a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +@@ -0,0 +0,0 @@ public abstract class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && this.sensitive && !(Boolean) state.getValue(ButtonBlock.POWERED)) { + this.checkPressed(state, world, pos); + } +diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +@@ -0,0 +0,0 @@ public class CactusBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit + entity.hurt(DamageSource.CACTUS, 1.0F); + CraftEventFactory.blockDamage = null; // CraftBukkit +diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java +@@ -0,0 +0,0 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.fireImmune() && (Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { + entity.hurt(DamageSource.IN_FIRE, (float) this.fireDamage); + } +diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/CropBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java +@@ -0,0 +0,0 @@ public class CropBlock extends BushBlock implements BonemealableBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (entity instanceof Ravager && !CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState(), !world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)).isCancelled()) { // CraftBukkit + world.destroyBlock(pos, true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -0,0 +0,0 @@ public class DetectorRailBlock extends BaseRailBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) state.getValue(DetectorRailBlock.POWERED)) { + this.checkPressed(world, pos, state); +diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +@@ -0,0 +0,0 @@ public class EndPortalBlock extends BaseEntityBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (world instanceof ServerLevel && !entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(world, pos), BooleanOp.AND)) { + ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends + ServerLevel worldserver = ((ServerLevel) world).getServer().getLevel(resourcekey); +diff --git a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +@@ -0,0 +0,0 @@ public class HoneyBlock extends HalfTransparentBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (this.isSlidingDown(pos, entity)) { + this.maybeDoSlideAchievement(entity, pos); + this.doSlideMovement(entity); +diff --git a/src/main/java/net/minecraft/world/level/block/HopperBlock.java b/src/main/java/net/minecraft/world/level/block/HopperBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/HopperBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/HopperBlock.java +@@ -0,0 +0,0 @@ public class HopperBlock extends BaseEntityBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof HopperBlockEntity) { + HopperBlockEntity.entityInside(world, pos, state, entity, (HopperBlockEntity)blockEntity); +diff --git a/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LavaCauldronBlock.java +@@ -0,0 +0,0 @@ public class LavaCauldronBlock extends AbstractCauldronBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (this.isEntityInsideContent(state, pos, entity)) { + entity.lavaHurt(); + } +diff --git a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java +@@ -0,0 +0,0 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) { + // CraftBukkit start + if (entity.mayInteract(world, pos)) { +diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -0,0 +0,0 @@ public class NetherPortalBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!entity.isPassenger() && !entity.isVehicle() && entity.canChangeDimensions()) { + // CraftBukkit start - Entity in portal + EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); +diff --git a/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java b/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PowderSnowBlock.java +@@ -0,0 +0,0 @@ public class PowderSnowBlock extends Block implements BucketPickup { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!(entity instanceof LivingEntity) || entity.getFeetBlockState().is((Block) this)) { + entity.makeStuckInBlock(state, new Vec3(0.8999999761581421D, 1.5D, 0.8999999761581421D)); + if (world.isClientSide) { +diff --git a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java +@@ -0,0 +0,0 @@ public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (entity instanceof LivingEntity && entity.getType() != EntityType.FOX && entity.getType() != EntityType.BEE) { + entity.makeStuckInBlock(state, new Vec3(0.800000011920929D, 0.75D, 0.800000011920929D)); + if (!world.isClientSide && (Integer) state.getValue(SweetBerryBushBlock.AGE) > 0 && (entity.xOld != entity.getX() || entity.zOld != entity.getZ())) { +diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java +@@ -0,0 +0,0 @@ public class TripWireBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide) { + if (!(Boolean) state.getValue(TripWireBlock.POWERED)) { + this.checkPressed(world, pos); +diff --git a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WaterlilyBlock.java +@@ -0,0 +0,0 @@ public class WaterlilyBlock extends BushBlock { + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { + super.entityInside(state, world, pos, entity); ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (world instanceof ServerLevel && entity instanceof Boat && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, Blocks.AIR.defaultBlockState()).isCancelled()) { // CraftBukkit + world.destroyBlock(new BlockPos(pos), true, entity); + } +diff --git a/src/main/java/net/minecraft/world/level/block/WebBlock.java b/src/main/java/net/minecraft/world/level/block/WebBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/WebBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WebBlock.java +@@ -0,0 +0,0 @@ public class WebBlock extends Block { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + entity.makeStuckInBlock(state, new Vec3(0.25D, (double)0.05F, 0.25D)); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/WitherRoseBlock.java +@@ -0,0 +0,0 @@ public class WitherRoseBlock extends FlowerBlock { + + @Override + public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { ++ if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper + if (!world.isClientSide && world.getDifficulty() != Difficulty.PEACEFUL) { + if (entity instanceof LivingEntity) { + LivingEntity entityliving = (LivingEntity) entity; diff --git a/patches/server/Add-EntityLoadCrossbowEvent.patch b/patches/server/Add-EntityLoadCrossbowEvent.patch new file mode 100644 index 0000000000..aee527efe0 --- /dev/null +++ b/patches/server/Add-EntityLoadCrossbowEvent.patch @@ -0,0 +1,39 @@ +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/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -0,0 +0,0 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + int j = this.getUseDuration(stack) - remainingUseTicks; + float f = CrossbowItem.getPowerForTime(j, stack); + +- if (f >= 1.0F && !CrossbowItem.isCharged(stack) && CrossbowItem.tryLoadProjectiles(user, stack)) { ++ // Paper start - EntityLoadCrossbowEvent ++ if (f >= 1.0F && !CrossbowItem.isCharged(stack) /*&& CrossbowItem.tryLoadProjectiles(entityliving, itemstack)*/) { ++ final io.papermc.paper.event.entity.EntityLoadCrossbowEvent event = new io.papermc.paper.event.entity.EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), user.getUsedItemHand() == InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND); ++ if (!event.callEvent() || !tryLoadProjectiles(user, stack, event.shouldConsumeItem())) return; ++ // Paper end + CrossbowItem.setCharged(stack, true); + SoundSource soundcategory = user instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE; + +@@ -0,0 +0,0 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + } + + private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile) { ++ // Paper start ++ return CrossbowItem.tryLoadProjectiles(shooter, projectile, true); ++ } ++ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack projectile, boolean consume) { ++ // Paper end + int i = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, projectile); + int j = i == 0 ? 1 : 3; +- boolean flag = shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; ++ boolean flag = !consume || shooter instanceof Player && ((Player) shooter).getAbilities().instabuild; // Paper - add consme + ItemStack itemstack1 = shooter.getProjectile(projectile); + ItemStack itemstack2 = itemstack1.copy(); + diff --git a/Spigot-Server-Patches/Add-EntityZapEvent.patch b/patches/server/Add-EntityZapEvent.patch similarity index 51% rename from Spigot-Server-Patches/Add-EntityZapEvent.patch rename to patches/server/Add-EntityZapEvent.patch index d1f62144c0..4c2f2c9b33 100644 --- a/Spigot-Server-Patches/Add-EntityZapEvent.patch +++ b/patches/server/Add-EntityZapEvent.patch @@ -4,39 +4,45 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pig.java b/src/main/java/net/minecraft/world/entity/animal/Pig.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 { +--- a/src/main/java/net/minecraft/world/entity/animal/Pig.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pig.java +@@ -0,0 +0,0 @@ public class Pig extends Animal implements ItemSteerable, Saddleable { } - entitypigzombie.setPersistent(); + entitypigzombie.setPersistenceRequired(); + // Paper start -+ if (CraftEventFactory.callEntityZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { ++ if (CraftEventFactory.callEntityZapEvent(this, lightning, entitypigzombie).isCancelled()) { + return; + } + // Paper end // CraftBukkit start - if (CraftEventFactory.callPigZapEvent(this, entitylightning, entitypigzombie).isCancelled()) { + if (CraftEventFactory.callPigZapEvent(this, lightning, 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 +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.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); +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void thunderHit(ServerLevel world, LightningBolt lightning) { + if (world.getDifficulty() != Difficulty.PEACEFUL) { +- Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); ++ // Paper - move log down, event can cancel + Witch entitywitch = (Witch) EntityType.WITCH.create((Level) world); + // Paper start -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, lightning, 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()); ++ Villager.LOGGER.info("Villager {} was struck by lightning {}.", this, lightning); // Paper - move log down, event can cancel ++ + entitywitch.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + entitywitch.finalizeSpawn(world, world.getCurrentDifficultyAt(entitywitch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) 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 diff --git a/patches/server/Add-Heightmap-API.patch b/patches/server/Add-Heightmap-API.patch new file mode 100644 index 0000000000..c2d839221c --- /dev/null +++ b/patches/server/Add-Heightmap-API.patch @@ -0,0 +1,40 @@ +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/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 this.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.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.WORLD_SURFACE, x, z); ++ case SOLID: ++ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.OCEAN_FLOOR, x, z); ++ case SOLID_OR_LIQUID: ++ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING, x, z); ++ case SOLID_OR_LIQUID_NO_LEAVES: ++ return this.world.getHeight(net.minecraft.world.level.levelgen.Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, x, z); ++ default: ++ throw new UnsupportedOperationException(); ++ } ++ } ++ // Paper end ++ + @Override + public Location getSpawnLocation() { + BlockPos spawn = this.world.getSharedSpawnPos(); diff --git a/Spigot-Server-Patches/Add-LivingEntity-clearActiveItem.patch b/patches/server/Add-LivingEntity-clearActiveItem.patch similarity index 84% rename from Spigot-Server-Patches/Add-LivingEntity-clearActiveItem.patch rename to patches/server/Add-LivingEntity-clearActiveItem.patch index 8d7c280205..2a0bd1b478 100644 --- a/Spigot-Server-Patches/Add-LivingEntity-clearActiveItem.patch +++ b/patches/server/Add-LivingEntity-clearActiveItem.patch @@ -9,16 +9,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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(); + return getHandle().getUseItem().asBukkitMirror(); } + // Paper start + @Override + public void clearActiveItem() { -+ getHandle().clearActiveItem(); ++ getHandle().stopUsingItem(); + } + // Paper end + @Override public int getItemUseRemainingTime() { - return getHandle().getItemUseRemainingTime(); + return getHandle().getUseItemRemainingTicks(); diff --git a/patches/server/Add-LivingEntity-getTargetEntity.patch b/patches/server/Add-LivingEntity-getTargetEntity.patch new file mode 100644 index 0000000000..9566205fa0 --- /dev/null +++ b/patches/server/Add-LivingEntity-getTargetEntity.patch @@ -0,0 +1,102 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.loot.LootTable; + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + return level.clip(raytrace); + } + ++ public EntityHitResult getTargetEntity(int maxDistance) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = this.getEyePosition(1.0F); ++ Vec3 direction = this.getLookAngle(); ++ Vec3 end = start.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance); ++ ++ List entityList = level.getEntities(this, getBoundingBox().expandTowards(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance).inflate(1.0D, 1.0D, 1.0D), EntitySelector.NO_CREATIVE_OR_SPECTATOR.and(Entity::isPickable)); ++ ++ double distance = 0.0D; ++ EntityHitResult result = null; ++ ++ for (Entity entity : entityList) { ++ final double inflationAmount = (double) entity.getPickRadius(); ++ AABB aabb = entity.getBoundingBox().inflate(inflationAmount, inflationAmount, inflationAmount); ++ Optional rayTraceResult = aabb.clip(start, end); ++ ++ if (rayTraceResult.isPresent()) { ++ Vec3 rayTrace = rayTraceResult.get(); ++ double distanceTo = start.distanceToSqr(rayTrace); ++ if (distanceTo < distance || distance == 0.0D) { ++ result = new EntityHitResult(entity, rayTrace); ++ distance = distanceTo; ++ } ++ } ++ } ++ ++ return result; ++ } ++ + public int shieldBlockingDelay = level.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.entity.TargetEntityInfo; + import com.google.common.base.Preconditions; + import com.google.common.collect.Sets; + import java.util.ArrayList; +@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + new com.destroystokyo.paper.block.TargetBlockInfo(org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()), + net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection())); + } ++ ++ public Entity getTargetEntity(int maxDistance, boolean ignoreBlocks) { ++ net.minecraft.world.phys.EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : rayTrace.getEntity().getBukkitEntity(); ++ } ++ ++ public TargetEntityInfo getTargetEntityInfo(int maxDistance, boolean ignoreBlocks) { ++ net.minecraft.world.phys.EntityHitResult rayTrace = rayTraceEntity(maxDistance, ignoreBlocks); ++ return rayTrace == null ? null : new TargetEntityInfo(rayTrace.getEntity().getBukkitEntity(), new org.bukkit.util.Vector(rayTrace.getLocation().x, rayTrace.getLocation().y, rayTrace.getLocation().z)); ++ } ++ ++ public net.minecraft.world.phys.EntityHitResult rayTraceEntity(int maxDistance, boolean ignoreBlocks) { ++ net.minecraft.world.phys.EntityHitResult rayTrace = getHandle().getTargetEntity(maxDistance); ++ if (rayTrace == null) { ++ return null; ++ } ++ if (!ignoreBlocks) { ++ net.minecraft.world.phys.HitResult rayTraceBlocks = getHandle().getRayTrace(maxDistance, net.minecraft.world.level.ClipContext.Fluid.NONE); ++ if (rayTraceBlocks != null) { ++ net.minecraft.world.phys.Vec3 eye = getHandle().getEyePosition(1.0F); ++ if (eye.distanceToSqr(rayTraceBlocks.getLocation()) <= eye.distanceToSqr(rayTrace.getLocation())) { ++ return null; ++ } ++ } ++ } ++ return rayTrace; ++ } + // Paper end + + @Override diff --git a/patches/server/Add-MinecraftKey-Information-to-Objects.patch b/patches/server/Add-MinecraftKey-Information-to-Objects.patch new file mode 100644 index 0000000000..0b799c10de --- /dev/null +++ b/patches/server/Add-MinecraftKey-Information-to-Objects.patch @@ -0,0 +1,124 @@ +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 { + ServerChunkCache chunkProviderServer = world.getChunkSource(); + + world.getAllEntities().forEach(e -> { +- ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch ++ ResourceLocation key = e.getMinecraftKey(); + + MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); + ChunkPos chunk = e.chunkPosition(); +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.ResourceLocation; ++ ++// TODO(Mariell Hoversholm): Move stupid ass class ++public interface KeyedObject { ++ ResourceLocation getMinecraftKey(); ++ default String getMinecraftKeyString() { ++ ResourceLocation 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 Nameable, EntityAccess, CommandSource { ++public abstract class Entity implements Nameable, EntityAccess, CommandSource, net.minecraft.server.KeyedObject { // Paper + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + return true; + } + ++ // Paper start ++ private ResourceLocation entityKey; ++ private String entityKeyString; ++ ++ @Override ++ public ResourceLocation getMinecraftKey() { ++ if (entityKey == null) { ++ this.entityKey = EntityType.getKey(this.getType()); ++ 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 getEncodeId() { + EntityType entitytypes = this.getType(); + ResourceLocation minecraftkey = EntityType.getKey(entitytypes); + +- return entitytypes.canSerialize() && minecraftkey != null ? minecraftkey.toString() : null; ++ return entitytypes != null && entitytypes.canSerialize() ? getMinecraftKeyString() : null; ++ // Paper end + } + + protected abstract void readAdditionalSaveData(CompoundTag nbt); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -0,0 +0,0 @@ import org.bukkit.inventory.InventoryHolder; + + import org.spigotmc.CustomTimingsHandler; // Spigot + +-public abstract class BlockEntity { ++public abstract class BlockEntity 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 BlockEntity { + this.blockState = state; + } + ++ // Paper start ++ private String tileEntityKeyString = null; ++ private ResourceLocation tileEntityKey = null; ++ ++ @Override ++ public ResourceLocation getMinecraftKey() { ++ if (tileEntityKey == null) { ++ tileEntityKey = BlockEntityType.getKey(this.type); ++ 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 Level getLevel() { + return this.level; diff --git a/patches/server/Add-Mob-lookAt-API.patch b/patches/server/Add-Mob-lookAt-API.patch new file mode 100644 index 0000000000..fd6cb3e2d7 --- /dev/null +++ b/patches/server/Add-Mob-lookAt-API.patch @@ -0,0 +1,64 @@ +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/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().isSunBurnTick(); + } ++ ++ @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().getLookControl().setLookAt(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().getLookControl().setLookAt(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().getLookControl().setLookAt(((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().getLookControl().setLookAt(((CraftEntity) entity).getHandle(), headRotationSpeed, maxHeadPitch); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z) { ++ getHandle().getLookControl().setLookAt(x, y, z); ++ } ++ ++ @Override ++ public void lookAt(double x, double y, double z, float headRotationSpeed, float maxHeadPitch) { ++ getHandle().getLookControl().setLookAt(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/patches/server/Add-More-Creeper-API.patch similarity index 72% rename from Spigot-Server-Patches/Add-More-Creeper-API.patch rename to patches/server/Add-More-Creeper-API.patch index cd6be16983..201a06863f 100644 --- a/Spigot-Server-Patches/Add-More-Creeper-API.patch +++ b/patches/server/Add-More-Creeper-API.patch @@ -4,15 +4,15 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.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 { +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -0,0 +0,0 @@ public class Creeper extends Monster implements PowerableMob { } public void ignite() { -- this.datawatcher.set(EntityCreeper.d, true); +- this.entityData.set(Creeper.DATA_IS_IGNITED, true); + // Paper start + setIgnited(true); + } @@ -21,13 +21,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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()); ++ this.entityData.set(Creeper.DATA_IS_IGNITED, event.isIgnited()); + } + } + // Paper end } - public boolean canCauseHeadDrop() { + public boolean canDropMobsSkull() { 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 @@ -38,10 +38,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + + // Paper start ++ @Override + public void setIgnited(boolean ignited) { + getHandle().setIgnited(ignited); + } + ++ @Override + public boolean isIgnited() { + return getHandle().isIgnited(); + } diff --git a/Spigot-Server-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from Spigot-Server-Patches/Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/server/Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/Spigot-Server-Patches/Add-PhantomPreSpawnEvent.patch b/patches/server/Add-PhantomPreSpawnEvent.patch similarity index 51% rename from Spigot-Server-Patches/Add-PhantomPreSpawnEvent.patch rename to patches/server/Add-PhantomPreSpawnEvent.patch index 83c8df0848..04b70c1728 100644 --- a/Spigot-Server-Patches/Add-PhantomPreSpawnEvent.patch +++ b/patches/server/Add-PhantomPreSpawnEvent.patch @@ -4,36 +4,36 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.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 { +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { } - this.setSize(nbttagcompound.getInt("Size")); + this.setPhantomSize(nbt.getInt("Size")); + // Paper start -+ if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { -+ this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); ++ if (nbt.hasUUID("Paper.SpawningEntity")) { ++ this.spawningEntity = nbt.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()); +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { + nbt.putInt("AY", this.anchorPoint.getY()); + nbt.putInt("AZ", this.anchorPoint.getZ()); + nbt.putInt("Size", this.getPhantomSize()); + // Paper start + if (this.spawningEntity != null) { -+ nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); ++ nbt.putUUID("Paper.SpawningEntity", this.spawningEntity); + } + // Paper end } @Override -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - return entitysize.a(f); +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { + return entitysize.scale(f); } + // Paper start @@ -44,28 +44,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } + // Paper end -+ - class b extends PathfinderGoal { + private static enum AttackPhase { - 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 + CIRCLE, SWOOP; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.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 +--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.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.core.BlockPos; + import net.minecraft.nbt.CompoundTag; +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); + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.stats.ServerStatsCounter; +@@ -0,0 +0,0 @@ public class PhantomSpawner implements CustomSpawner { + int k = 1 + random.nextInt(difficultydamagescaler.getDifficulty().getId() + 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); ++ com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent event = new com.destroystokyo.paper.event.entity.PhantomPreSpawnEvent(MCUtil.toLocation(world, blockposition1), ((ServerPlayer) entityhuman).getBukkitEntity(), org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); + if (!event.callEvent()) { + if (event.shouldAbortSpawn()) { + break; @@ -73,12 +72,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + continue; + } + // Paper end - EntityPhantom entityphantom = (EntityPhantom) EntityTypes.PHANTOM.a((World) worldserver); + Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world); - -+ 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 ++ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper + entityphantom.moveTo(blockposition1, 0.0F, 0.0F); + groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); + world.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 @@ -89,6 +88,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + + // Paper start ++ @Override + public java.util.UUID getSpawningEntity() { + return getHandle().getSpawningEntity(); + } diff --git a/Spigot-Server-Patches/Add-PlayerArmorChangeEvent.patch b/patches/server/Add-PlayerArmorChangeEvent.patch similarity index 50% rename from Spigot-Server-Patches/Add-PlayerArmorChangeEvent.patch rename to patches/server/Add-PlayerArmorChangeEvent.patch index f39ec8aaf3..c8ce4adc8d 100644 --- a/Spigot-Server-Patches/Add-PlayerArmorChangeEvent.patch +++ b/patches/server/Add-PlayerArmorChangeEvent.patch @@ -4,10 +4,10 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -0,0 +0,0 @@ package net.minecraft.world.entity; @@ -15,29 +15,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + ItemStack itemstack1 = this.getItemBySlot(enumitemslot); if (!ItemStack.matches(itemstack1, itemstack)) { + // Paper start - PlayerArmorChangeEvent -+ if (this instanceof EntityPlayer && enumitemslot.getType() == EnumItemSlot.Function.ARMOR) { ++ if (this instanceof ServerPlayer && enumitemslot.getType() == EquipmentSlot.Type.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); + map = Maps.newEnumMap(EquipmentSlot.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/patches/server/Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/Add-PlayerAttackEntityCooldownResetEvent.patch new file mode 100644 index 0000000000..aac82f9255 --- /dev/null +++ b/patches/server/Add-PlayerAttackEntityCooldownResetEvent.patch @@ -0,0 +1,28 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity 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 net.minecraft.world.entity.player.Player) { +- ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired ++ // Paper start - PlayerAttackEntityCooldownResetEvent ++ if (damagesource.getEntity() instanceof ServerPlayer) { ++ ServerPlayer player = (ServerPlayer) damagesource.getEntity(); ++ if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackStrengthScale(0F)).callEvent()) { ++ player.resetAttackStrengthTicker(); ++ } ++ } else { ++ ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); ++ } ++ // Paper end + } + if (event.isCancelled()) { + return false; diff --git a/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch b/patches/server/Add-PlayerConnectionCloseEvent.patch similarity index 51% rename from Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch rename to patches/server/Add-PlayerConnectionCloseEvent.patch index 6acea9bc30..3de17ccbe6 100644 --- a/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch +++ b/patches/server/Add-PlayerConnectionCloseEvent.patch @@ -33,50 +33,47 @@ 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 +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.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")); +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic")); } - this.packetQueue.clear(); // Free up packet queue. + this.queue.clear(); // Free up packet queue. + // Paper start - Add PlayerConnectionCloseEvent -+ final PacketListener packetListener = this.j(); -+ if (packetListener instanceof PlayerConnection) { ++ final PacketListener packetListener = this.getPacketListener(); ++ if (packetListener instanceof ServerGamePacketListenerImpl) { + /* 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) { ++ final ServerGamePacketListenerImpl playerConnection = (ServerGamePacketListenerImpl) packetListener; ++ new com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent(playerConnection.player.getUUID(), ++ playerConnection.player.getScoreboardName(), ((java.net.InetSocketAddress)address).getAddress(), false).callEvent(); ++ } else if (packetListener instanceof ServerLoginPacketListenerImpl) { + /* Player is login stage */ -+ final LoginListener loginListener = (LoginListener) packetListener; -+ switch (loginListener.getLoginState()) { ++ final ServerLoginPacketListenerImpl loginListener = (ServerLoginPacketListenerImpl) packetListener; ++ switch (loginListener.state) { + 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(); ++ ((java.net.InetSocketAddress)address).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 +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.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; +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + public ServerLoginPacketListenerImpl.State state; + private int tick; + @Nullable +- GameProfile gameProfile; ++ GameProfile gameProfile; @Deprecated private void setGameProfile(final GameProfile profile) { this.gameProfile = profile; } @Deprecated public GameProfile getGameProfile() { return this.gameProfile; } // Paper - OBFHELPER + private final String serverId; + @Nullable + private ServerPlayer delayedAcceptPlayer; diff --git a/Spigot-Server-Patches/Add-PlayerInitialSpawnEvent.patch b/patches/server/Add-PlayerInitialSpawnEvent.patch similarity index 54% rename from Spigot-Server-Patches/Add-PlayerInitialSpawnEvent.patch rename to patches/server/Add-PlayerInitialSpawnEvent.patch index e52ae43861..64786e0d05 100644 --- a/Spigot-Server-Patches/Add-PlayerInitialSpawnEvent.patch +++ b/patches/server/Add-PlayerInitialSpawnEvent.patch @@ -15,34 +15,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class PlayerList { // Spigot start - spawn location event - Player bukkitPlayer = entityplayer.getBukkitEntity(); + Player bukkitPlayer = player.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); + this.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()); + player.setLevel(worldserver1); + player.gameMode.setLevel((ServerLevel) player.level); +- player.absMoveTo(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()); ++ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ()); ++ player.setRot(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/patches/server/Add-PlayerItemCooldownEvent.patch b/patches/server/Add-PlayerItemCooldownEvent.patch new file mode 100644 index 0000000000..909c4def78 --- /dev/null +++ b/patches/server/Add-PlayerItemCooldownEvent.patch @@ -0,0 +1,27 @@ +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/ServerItemCooldowns.java b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java ++++ b/src/main/java/net/minecraft/world/item/ServerItemCooldowns.java +@@ -0,0 +0,0 @@ public class ServerItemCooldowns extends ItemCooldowns { + this.player = player; + } + ++ // Paper start ++ @Override ++ public void addCooldown(Item item, int duration) { ++ io.papermc.paper.event.player.PlayerItemCooldownEvent event = new io.papermc.paper.event.player.PlayerItemCooldownEvent(this.player.getBukkitEntity(), org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(item), duration); ++ if (event.callEvent()) { ++ super.addCooldown(item, event.getCooldown()); ++ } ++ } ++ // Paper end ++ + @Override + protected void onCooldownStarted(Item item, int duration) { + super.onCooldownStarted(item, duration); diff --git a/Spigot-Server-Patches/Add-PlayerJumpEvent.patch b/patches/server/Add-PlayerJumpEvent.patch similarity index 60% rename from Spigot-Server-Patches/Add-PlayerJumpEvent.patch rename to patches/server/Add-PlayerJumpEvent.patch index ecd171d834..e012450b01 100644 --- a/Spigot-Server-Patches/Add-PlayerJumpEvent.patch +++ b/patches/server/Add-PlayerJumpEvent.patch @@ -4,43 +4,43 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser boolean flag = d8 > 0.0D; - if (this.player.isOnGround() && !packetplayinflying.b() && flag) { -- this.player.jump(); + if (this.player.isOnGround() && !packet.isOnGround() && flag) { +- this.player.jumpFromGround(); + // Paper start - Add player jump event -+ Player player = this.getPlayer(); ++ Player player = this.getCraftPlayer(); + Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch); // Get the Players previous Event location. + Location to = player.getLocation().clone(); // Start off the To location as the Players current location. + + // If the packet contains movement information then we update the To location with the correct XYZ. -+ if (packetplayinflying.hasPos) { -+ to.setX(packetplayinflying.x); -+ to.setY(packetplayinflying.y); -+ to.setZ(packetplayinflying.z); ++ if (packet.hasPos) { ++ to.setX(packet.x); ++ to.setY(packet.y); ++ to.setZ(packet.z); + } + + // If the packet contains look information then we update the To location with the correct Yaw & Pitch. -+ if (packetplayinflying.hasLook) { -+ to.setYaw(packetplayinflying.yaw); -+ to.setPitch(packetplayinflying.pitch); ++ if (packet.hasRot) { ++ to.setYaw(packet.yRot); ++ to.setPitch(packet.xRot); + } + + com.destroystokyo.paper.event.player.PlayerJumpEvent event = new com.destroystokyo.paper.event.player.PlayerJumpEvent(player, from, to); + + if (event.callEvent()) { -+ this.player.jump(); ++ this.player.jumpFromGround(); + } else { + from = event.getFrom(); -+ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet()); ++ this.internalTeleport(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch(), Collections.emptySet(), false); + return; + } + // Paper end } - this.player.move(EnumMoveType.PLAYER, new Vec3D(d7, d8, d9)); + this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); diff --git a/patches/server/Add-PlayerKickEvent-causes.patch b/patches/server/Add-PlayerKickEvent-causes.patch new file mode 100644 index 0000000000..ce7f7425e5 --- /dev/null +++ b/patches/server/Add-PlayerKickEvent-causes.patch @@ -0,0 +1,393 @@ +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 ReentrantBlockableEventLoop targets, Component reason) { + for(ServerPlayer serverPlayer : targets) { +- serverPlayer.connection.disconnect(reason); ++ serverPlayer.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause + source.sendSuccess(new TranslatableComponent("commands.kick.success", serverPlayer.getDisplayName(), reason), true); + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + if (this.clientIsFloating && !this.player.isSleeping()) { + if (++this.aboveGroundTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { + if (++this.aboveGroundVehicleTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + if (this.keepAlivePending) { + if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info +- this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); ++ this.disconnect(new TranslatableComponent("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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + if (this.player.getLastActionTime() > 0L && this.server.getPlayerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > (long) (this.server.getPlayerIdleTimeout() * 1000 * 60)) { + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause + } + + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + 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 Component reason) { +- this.disconnect(PaperAdventure.asAdventure(reason)); ++ this.disconnect(PaperAdventure.asAdventure(reason), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); ++ } ++ ++ public void disconnect(final Component 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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + 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.player.getBukkitEntity(), reason, leaveMessage); // Paper - Adventure ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), reason, leaveMessage, cause); // Paper - Adventure & kick event reason + + if (this.cserver.getServer().isRunning()) { + this.cserver.getPluginManager().callEvent(event); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (ServerGamePacketListenerImpl.containsInvalidValues(packet.getX(), packet.getY(), packet.getZ(), packet.getYRot(), packet.getXRot())) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_vehicle_movement")); ++ this.disconnect(new TranslatableComponent("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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); // Paper - run this async + // CraftBukkit start + if (this.chatSpamTickCount.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + // Paper start + String str = packet.getCommand(); int index = -1; + if (str.length() > 64 && ((index = str.indexOf(' ')) == -1 || index >= 64)) { +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // Paper start - validate pick item position + if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.getInventory().items.size())) { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().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.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + ListTag pageList = testStack.getTag().getList("pages", 8); + if (pageList.size() > 100) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; + if (byteLength > 256 * 4) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + if (byteTotal > byteAllowed) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); +- server.scheduleOnMain(() -> this.disconnect("Book too large!")); ++ server.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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + public void handleMovePlayer(ServerboundMovePlayerPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (ServerGamePacketListenerImpl.containsInvalidValues(packet.getX(0.0D), packet.getY(0.0D), packet.getZ(0.0D), packet.getYRot(0.0F), packet.getXRot(0.0F))) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause + } else { + ServerLevel worldserver = this.player.getLevel(); + +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.dropCount++; + if (this.dropCount >= 20) { + ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " 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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (packet.getAction() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) { + ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName()); +- this.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect")); ++ this.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect"), org.bukkit.event.player.PlayerKickEvent.Cause.RESOURCE_PACK_REJECTION); // Paper - add cause + } + // Paper start + PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.player.resetLastActionTime(); + } else { + ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); +- this.disconnect("Invalid hotbar selection (Hacking?)"); // CraftBukkit ++ 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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + for (int i = 0; i < s.length(); ++i) { + if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) { +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters")); ++ this.disconnect(new TranslatableComponent("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - add cause + return; + } + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + Waitable waitable = new Waitable() { + @Override + protected Object evaluate() { +- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam")); ++ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + return null; + } + }; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + throw new RuntimeException(e); + } + } else { +- this.disconnect(new TranslatableComponent("disconnect.spam")); ++ this.disconnect(new TranslatableComponent("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause + } + // CraftBukkit end + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // Spigot Start + if ( entity == this.player && !this.player.isSpectator() ) + { +- this.disconnect( "Cannot interact with self!" ); ++ this.disconnect( "Cannot interact with self!", org.bukkit.event.player.PlayerKickEvent.Cause.SELF_INTERACTION ); // Paper - add cause + return; + } + // Spigot End +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + // CraftBukkit end + } else { +- ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked")); ++ ServerGamePacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.invalid_entity_attacked"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_ENTITY_ATTACKED); // Paper - add cause + ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString()); + } + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // Paper start + if (!org.bukkit.Bukkit.isPrimaryThread()) { + if (recipeSpamPackets.addAndGet(com.destroystokyo.paper.PaperConfig.autoRecipeIncrement) > com.destroystokyo.paper.PaperConfig.autoRecipeLimit) { +- server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause + return; + } + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } else if (!this.isSingleplayerOwner()) { + // Paper start - This needs to be handled on the main thread for plugins + server.submit(() -> { +- this.disconnect(new TranslatableComponent("disconnect.timeout")); ++ this.disconnect(new TranslatableComponent("disconnect.timeout"), org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + }); + // Paper end + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + } catch (Exception ex) { + ServerGamePacketListenerImpl.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 (packet.identifier.equals(CUSTOM_UNREGISTER)) { + try { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + } catch (Exception ex) { + ServerGamePacketListenerImpl.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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data); + } catch (Exception ex) { + ServerGamePacketListenerImpl.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 = (ServerPlayer) iterator.next(); + this.save(entityplayer); // CraftBukkit - Force the player's inventory to be saved +- entityplayer.connection.disconnect(new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0])); ++ entityplayer.connection.disconnect(new TranslatableComponent("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 { + // Paper end + // CraftBukkit start - disconnect safely + for (ServerPlayer player : this.players) { +- if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage); else // Paper +- player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure ++ if (isRestarting) player.connection.disconnect(org.spigotmc.SpigotConfig.restartMessage, org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); else // Paper - kick event cause (cause is never used here) ++ player.connection.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 (this.getHandle().connection == null) return; + +- this.getHandle().connection.disconnect(message == null ? "" : message); ++ this.getHandle().connection.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 ServerGamePacketListenerImpl connection = this.getHandle().connection; + 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); + } + } + +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 ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) + { +- p.connection.disconnect(SpigotConfig.restartMessage); ++ p.connection.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/patches/server/Add-PlayerShearBlockEvent.patch b/patches/server/Add-PlayerShearBlockEvent.patch new file mode 100644 index 0000000000..cf67fece11 --- /dev/null +++ b/patches/server/Add-PlayerShearBlockEvent.patch @@ -0,0 +1,70 @@ +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/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +@@ -0,0 +0,0 @@ public class BeehiveBlock extends BaseEntityBlock { + } + + public static void dropHoneycomb(Level world, BlockPos pos) { +- popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); ++ popResource(world, pos, new ItemStack(Items.HONEYCOMB, 3)); // Paper - conflict on change, item needs to be set below + } + + @Override +@@ -0,0 +0,0 @@ public class BeehiveBlock extends BaseEntityBlock { + Item item = itemstack.getItem(); + + if (itemstack.is(Items.SHEARS)) { ++ // Paper start - Add PlayerShearBlockEvent ++ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (hand == InteractionHand.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 InteractionResult.PASS; ++ } ++ // Paper end + world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BEEHIVE_SHEAR, SoundSource.NEUTRAL, 1.0F, 1.0F); +- BeehiveBlock.dropHoneycomb(world, pos); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack itemDrop : event.getDrops()) { ++ popResource(world, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemDrop)); ++ } ++ // Paper end + itemstack.hurtAndBreak(1, player, (entityhuman1) -> { + entityhuman1.broadcastBreakEvent(hand); + }); +diff --git a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PumpkinBlock.java +@@ -0,0 +0,0 @@ public class PumpkinBlock extends StemGrownBlock { + ItemStack itemStack = player.getItemInHand(hand); + if (itemStack.is(Items.SHEARS)) { + if (!world.isClientSide) { ++ // Paper start - Add PlayerShearBlockEvent ++ io.papermc.paper.event.block.PlayerShearBlockEvent event = new io.papermc.paper.event.block.PlayerShearBlockEvent((org.bukkit.entity.Player) player.getBukkitEntity(), net.minecraft.server.MCUtil.toBukkitBlock(world, pos), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (hand == InteractionHand.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 InteractionResult.PASS; ++ } ++ // Paper end + Direction direction = hit.getDirection(); + Direction direction2 = direction.getAxis() == Direction.Axis.Y ? player.getDirection().getOpposite() : direction; + world.playSound((Player)null, pos, SoundEvents.PUMPKIN_CARVE, SoundSource.BLOCKS, 1.0F, 1.0F); + world.setBlock(pos, Blocks.CARVED_PUMPKIN.defaultBlockState().setValue(CarvedPumpkinBlock.FACING, direction2), 11); +- ItemEntity itemEntity = new ItemEntity(world, (double)pos.getX() + 0.5D + (double)direction2.getStepX() * 0.65D, (double)pos.getY() + 0.1D, (double)pos.getZ() + 0.5D + (double)direction2.getStepZ() * 0.65D, new ItemStack(Items.PUMPKIN_SEEDS, 4)); ++ // Paper start - Add PlayerShearBlockEvent ++ for (org.bukkit.inventory.ItemStack item : event.getDrops()) { ++ ItemEntity itemEntity = new ItemEntity(world, (double) pos.getX() + 0.5D + (double) direction2.getStepX() * 0.65D, (double) pos.getY() + 0.1D, (double) pos.getZ() + 0.5D + (double) direction2.getStepZ() * 0.65D, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item)); ++ // Paper end + itemEntity.setDeltaMovement(0.05D * (double)direction2.getStepX() + world.random.nextDouble() * 0.02D, 0.05D, 0.05D * (double)direction2.getStepZ() + world.random.nextDouble() * 0.02D); + world.addFreshEntity(itemEntity); ++ } // Paper - Add PlayerShearBlockEvent + itemStack.hurtAndBreak(1, player, (playerx) -> { + playerx.broadcastBreakEvent(hand); + }); diff --git a/patches/server/Add-PlayerUseUnknownEntityEvent.patch b/patches/server/Add-PlayerUseUnknownEntityEvent.patch new file mode 100644 index 0000000000..659f33894c --- /dev/null +++ b/patches/server/Add-PlayerUseUnknownEntityEvent.patch @@ -0,0 +1,63 @@ +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/ServerboundInteractPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundInteractPacket.java +@@ -0,0 +0,0 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.phys.Vec3; + + public class ServerboundInteractPacket implements Packet { +- private final int entityId; +- private final ServerboundInteractPacket.Action action; ++ private final int entityId; public final int getEntityId() { return this.entityId; } // Paper - add accessor ++ private final ServerboundInteractPacket.Action action; public final ServerboundInteractPacket.ActionType getActionType() { return this.action.getType(); } // Paper - add accessor + private final boolean usingSecondaryAction; + static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() { + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + }); + } + } ++ // Paper start - fire event ++ else { ++ packet.dispatch(new net.minecraft.network.protocol.game.ServerboundInteractPacket.Handler() { ++ @Override ++ public void onInteraction(net.minecraft.world.InteractionHand hand) { ++ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, hand); ++ } ++ ++ @Override ++ public void onInteraction(net.minecraft.world.InteractionHand hand, net.minecraft.world.phys.Vec3 pos) { ++ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, hand); ++ } ++ ++ @Override ++ public void onAttack() { ++ ServerGamePacketListenerImpl.this.callPlayerUseUnknownEntityEvent(packet, net.minecraft.world.InteractionHand.MAIN_HAND); ++ } ++ }); ++ } ++ ++ } + ++ private void callPlayerUseUnknownEntityEvent(ServerboundInteractPacket packet, InteractionHand hand) { ++ this.cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( ++ this.getCraftPlayer(), ++ packet.getEntityId(), ++ packet.getActionType() == ServerboundInteractPacket.ActionType.ATTACK, ++ hand == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND ++ )); + } ++ // Paper end + + @Override + public void handleClientCommand(ServerboundClientCommandPacket packet) { diff --git a/patches/server/Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/Add-Plugin-Tickets-to-API-Chunk-Methods.patch new file mode 100644 index 0000000000..ad599f25f1 --- /dev/null +++ b/patches/server/Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -0,0 +1,121 @@ +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 { + this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient"); + console.autosavePeriod = this.configuration.getInt("ticks-per.autosave"); + this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.timeout = Math.min(20, this.configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + this.minimumAPI = this.configuration.getString("settings.minimum-api"); + this.loadIcon(); + } +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + this.waterAmbientSpawn = this.configuration.getInt("spawn-limits.water-ambient"); + this.ambientSpawn = this.configuration.getInt("spawn-limits.ambient"); + this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); +- TicketType.PLUGIN.timeout = this.configuration.getInt("chunk-gc.period-in-ticks"); ++ TicketType.PLUGIN.timeout = Math.min(20, configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + this.minimumAPI = this.configuration.getString("settings.minimum-api"); + this.printSaveWarning = false; + console.autosavePeriod = this.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 @@ public class CraftWorld implements World { + + @Override + public Chunk getChunkAt(int x, int z) { +- return this.world.getChunkSource().getChunk(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.LevelChunk chunk = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ if (chunk == null) { ++ addTicket(x, z); ++ chunk = this.world.getChunkSource().getChunk(x, z, true); ++ } ++ return chunk.bukkitChunk; ++ // Paper end ++ } ++ ++ // Paper start ++ private void addTicket(int x, int z) { ++ net.minecraft.server.MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(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 (this.isChunkLoaded(x, z)) { +- this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); ++ this.world.getChunkSource().removeRegionTicket(TicketType.PLUGIN, new ChunkPos(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 + ChunkPos chunkPos = new ChunkPos(x, z); ++ ChunkAccess immediate = world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); // Paper ++ if (immediate != null) return true; // Paper + + if (!generate) { +- ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); ++ ++ //IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); // Paper + if (immediate == null) { + immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); + } +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { + return false; // not full status + } +- world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunk(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.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 0, Unit.INSTANCE); // Paper + world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); + return true; + // Paper end +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); ++ if (chunk != null) addTicket(x, z); // Paper + return java.util.concurrent.CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } diff --git a/Spigot-Server-Patches/Add-PrepareResultEvent.patch b/patches/server/Add-PrepareResultEvent.patch similarity index 58% rename from Spigot-Server-Patches/Add-PrepareResultEvent.patch rename to patches/server/Add-PrepareResultEvent.patch index 209aa2e059..e56d357714 100644 --- a/Spigot-Server-Patches/Add-PrepareResultEvent.patch +++ b/patches/server/Add-PrepareResultEvent.patch @@ -7,85 +7,73 @@ 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 +diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.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 { +--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +@@ -0,0 +0,0 @@ public class AnvilMenu extends ItemCombinerMenu { } - this.e(); + this.createResult(); + 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 + public int getCost() { +diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.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); +--- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java +@@ -0,0 +0,0 @@ public class CartographyTableMenu extends AbstractContainerMenu { + this.setupResultSlot(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 + private void setupResultSlot(ItemStack map, ItemStack item, ItemStack oldResult) { +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.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(); +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -0,0 +0,0 @@ public class GrindstoneMenu extends AbstractContainerMenu { + super.slotsChanged(inventory); + if (inventory == this.repairSlots) { + this.createResult(); + 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 +diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.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 { +--- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java +@@ -0,0 +0,0 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu { + super.slotsChanged(inventory); + if (inventory == this.inputSlots) { + this.createResult(); ++ org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 2); // Paper } - this.j(); -- this.c(); + } +diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +@@ -0,0 +0,0 @@ public class LoomMenu extends AbstractContainerMenu { + } + + this.setupResultSlot(); +- this.broadcastChanges(); + //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 + public void registerUpdateListener(Runnable inventoryChangeListener) { +diff --git a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java b/src/main/java/net/minecraft/world/inventory/SmithingMenu.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 { +--- a/src/main/java/net/minecraft/world/inventory/SmithingMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/SmithingMenu.java +@@ -0,0 +0,0 @@ public class SmithingMenu extends ItemCombinerMenu { // CraftBukkit end } @@ -93,18 +81,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @Override -diff --git a/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java b/src/main/java/net/minecraft/world/inventory/ContainerStonecutter.java +diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.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); +--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +@@ -0,0 +0,0 @@ public class StonecutterMenu extends AbstractContainerMenu { + this.setupRecipeList(inventory, itemstack); } + org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, 1); // Paper } - private void a(IInventory iinventory, ItemStack itemstack) { + private void setupRecipeList(Container input, ItemStack stack) { 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 @@ -140,7 +128,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + + // Paper start - support specific overrides for prepare result -+ public static void callPrepareResultEvent(Container container, int resultSlot) { ++ public static void callPrepareResultEvent(AbstractContainerMenu container, int resultSlot) { + com.destroystokyo.paper.event.inventory.PrepareResultEvent event; + InventoryView view = container.getBukkitView(); + org.bukkit.inventory.ItemStack origItem = view.getTopInventory().getItem(resultSlot); @@ -156,7 +144,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + event.callEvent(); + event.getInventory().setItem(resultSlot, event.getResult()); -+ container.notifyListeners(); ++ container.broadcastChanges();; + } + // Paper end diff --git a/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch b/patches/server/Add-ProjectileCollideEvent.patch similarity index 56% rename from Spigot-Server-Patches/Add-ProjectileCollideEvent.patch rename to patches/server/Add-ProjectileCollideEvent.patch index 246f6579d4..e0beced62f 100644 --- a/Spigot-Server-Patches/Add-ProjectileCollideEvent.patch +++ b/patches/server/Add-ProjectileCollideEvent.patch @@ -4,18 +4,18 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile { +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -0,0 +0,0 @@ public abstract class AbstractArrow extends Projectile { } } + // 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 (object instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)object); + if (event.isCancelled()) { + object = null; + movingobjectpositionentity = null; @@ -24,57 +24,57 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 + this.preOnHit((HitResult) object); // CraftBukkit - projectile hit event + this.hasImpulse = true; +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.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; - +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -0,0 +0,0 @@ import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.level.Level; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit -@@ -0,0 +0,0 @@ public abstract class EntityFireball extends IProjectile { +@@ -0,0 +0,0 @@ public abstract class AbstractHurtingProjectile extends Projectile { - MovingObjectPosition movingobjectposition = ProjectileHelper.a((Entity) this, this::a); + HitResult movingobjectposition = ProjectileUtil.getHitResult((Entity) this, this::canHitEntity); -- if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { +- if (movingobjectposition.getType() != HitResult.Type.MISS) { + // Paper start - Call ProjectileCollideEvent -+ if (movingobjectposition instanceof MovingObjectPositionEntity) { -+ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (MovingObjectPositionEntity)movingobjectposition); ++ if (movingobjectposition instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); + if (event.isCancelled()) { + movingobjectposition = null; + } + } + // Paper end + -+ if (movingobjectposition != null && movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS) { // Paper - add null check in case cancelled ++ if (movingobjectposition != null && movingobjectposition.getType() != HitResult.Type.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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.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; +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.BlockHitResult; ++import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; + import net.minecraft.world.phys.Vec3; - public abstract class EntityProjectile extends IProjectile { -@@ -0,0 +0,0 @@ public abstract class EntityProjectile extends IProjectile { +@@ -0,0 +0,0 @@ public abstract class ThrowableProjectile extends Projectile { } - if (movingobjectposition.getType() != MovingObjectPosition.EnumMovingObjectType.MISS && !flag) { + if (movingobjectposition.getType() != HitResult.Type.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 (movingobjectposition instanceof EntityHitResult) { ++ com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callProjectileCollideEvent(this, (EntityHitResult)movingobjectposition); + if (event.isCancelled()) { + movingobjectposition = null; + } @@ -85,7 +85,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper } - this.checkBlockCollisions(); + this.checkInsideBlocks(); 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 @@ -95,7 +95,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + // Paper start -+ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, MovingObjectPositionEntity position) { ++ public static com.destroystokyo.paper.event.entity.ProjectileCollideEvent callProjectileCollideEvent(Entity entity, EntityHitResult 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); diff --git a/Spigot-Server-Patches/Add-PufferFishStateChangeEvent.patch b/patches/server/Add-PufferFishStateChangeEvent.patch similarity index 64% rename from Spigot-Server-Patches/Add-PufferFishStateChangeEvent.patch rename to patches/server/Add-PufferFishStateChangeEvent.patch index 069c82b962..b93f250351 100644 --- a/Spigot-Server-Patches/Add-PufferFishStateChangeEvent.patch +++ b/patches/server/Add-PufferFishStateChangeEvent.patch @@ -4,46 +4,46 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.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 { +--- a/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Pufferfish.java +@@ -0,0 +0,0 @@ public class Pufferfish extends AbstractFish { public void tick() { - if (!this.world.isClientSide && this.isAlive() && this.doAITick()) { - if (this.c > 0) { + if (!this.level.isClientSide && this.isAlive() && this.isEffectiveAi()) { + if (this.inflateCounter > 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.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); this.setPuffState(1); + } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.c > 40 && this.getPuffState() == 1) { + } else if (this.inflateCounter > 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.playSound(SoundEvents.PUFFER_FISH_BLOW_UP, this.getSoundVolume(), this.getVoicePitch()); this.setPuffState(2); + } else { increase = false; } // Paper - Add PufferFishStateChangeEvent } + if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.c; + ++this.inflateCounter; + } // Paper - Add PufferFishStateChangeEvent } else if (this.getPuffState() != 0) { + boolean increase = true; // Paper - Add PufferFishStateChangeEvent - if (this.d > 60 && this.getPuffState() == 2) { + if (this.deflateTimer > 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.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); this.setPuffState(1); + } else { increase = false; } // Paper - Add PufferFishStateChangeEvent - } else if (this.d > 100 && this.getPuffState() == 1) { + } else if (this.deflateTimer > 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.playSound(SoundEvents.PUFFER_FISH_BLOW_OUT, this.getSoundVolume(), this.getVoicePitch()); this.setPuffState(0); + } else { increase = false; } // Paper - Add PufferFishStateChangeEvent } + if (increase) { // Paper - Add PufferFishStateChangeEvent - ++this.d; + ++this.deflateTimer; + } // Paper - Add PufferFishStateChangeEvent } } diff --git a/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch new file mode 100644 index 0000000000..e165b9612d --- /dev/null +++ b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch @@ -0,0 +1,58 @@ +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/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(); ++ CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).handle : CraftItemStack.asNMSCopy(item)).save(new CompoundTag()); ++ compound.putInt("DataVersion", getDataVersion()); ++ try { ++ net.minecraft.nbt.NbtIo.writeCompressed( ++ 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 { ++ CompoundTag compound = net.minecraft.nbt.NbtIo.readCompressed( ++ new java.io.ByteArrayInputStream(data) ++ ); ++ int dataVersion = compound.getInt("DataVersion"); ++ ++ Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); ++ Dynamic converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic(NbtOps.INSTANCE, compound), dataVersion, getDataVersion()); ++ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of((CompoundTag) 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/patches/server/Add-StructureLocateEvent.patch similarity index 58% rename from Spigot-Server-Patches/Add-StructureLocateEvent.patch rename to patches/server/Add-StructureLocateEvent.patch index afe6b4dc70..ac72e046c7 100644 --- a/Spigot-Server-Patches/Add-StructureLocateEvent.patch +++ b/patches/server/Add-StructureLocateEvent.patch @@ -19,23 +19,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class ChunkGenerator { @Nullable - public BlockPosition findNearestMapFeature(WorldServer worldserver, StructureGenerator structuregenerator, BlockPosition blockposition, int i, boolean flag) { + public BlockPos findNearestMapFeature(ServerLevel world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { + // 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); ++ org.bukkit.World world1 = world.getWorld(); ++ org.bukkit.Location originLocation = new org.bukkit.Location(world1, center.getX(), center.getY(), center.getZ()); ++ StructureLocateEvent event = new StructureLocateEvent(world1, originLocation, org.bukkit.StructureType.getStructureTypes().get(feature.getFeatureName()), radius, skipExistingChunks); + 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()); ++ if(event.getResult() != null) return new BlockPos(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()); ++ center = new BlockPos(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(); ++ world = ((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()); ++ radius = event.getRadius(); ++ skipExistingChunks = event.shouldFindUnexplored(); ++ feature = StructureFeature.STRUCTURES_REGISTRY.get(event.getType().getName()); + // Paper end - if (!this.b.a(structuregenerator)) { + if (!this.biomeSource.canGenerateStructure(feature)) { return null; - } else if (structuregenerator == StructureGenerator.STRONGHOLD) { + } else if (feature == StructureFeature.STRONGHOLD) { diff --git a/patches/server/Add-TNTPrimeEvent.patch b/patches/server/Add-TNTPrimeEvent.patch new file mode 100644 index 0000000000..cbf9df4310 --- /dev/null +++ b/patches/server/Add-TNTPrimeEvent.patch @@ -0,0 +1,115 @@ +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/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -0,0 +0,0 @@ public class EnderDragon extends Mob implements Enemy { + }); + craftBlock.getNMS().spawnAfterBreak((ServerLevel) level, blockposition, ItemStack.EMPTY); + } ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = level.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, explosionSource.getSourceMob().getBukkitEntity()).callEvent()) ++ continue; ++ // Paper end + nmsBlock.wasExploded(level, blockposition, explosionSource); + + this.level.removeBlock(blockposition, false); +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -0,0 +0,0 @@ public class FireBlock extends BaseFireBlock { + + world.setBlock(blockposition, this.getStateWithAge(world, blockposition, l), 3); + } else { +- world.removeBlock(blockposition, false); ++ if(iblockdata.getBlock() != Blocks.TNT) world.removeBlock(blockposition, false); // Paper - TNTPrimeEvent - We might be cancelling it below, move the setAir down + } + + Block block = iblockdata.getBlock(); +@@ -0,0 +0,0 @@ public class FireBlock extends BaseFireBlock { + if (block instanceof TntBlock) { + TntBlock blocktnt = (TntBlock) block; + ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.FIRE, null).callEvent()) { ++ return; ++ } ++ world.removeBlock(blockposition, false); ++ // Paper end + TntBlock.explode(world, blockposition); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/TntBlock.java b/src/main/java/net/minecraft/world/level/block/TntBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/TntBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TntBlock.java +@@ -0,0 +0,0 @@ public class TntBlock extends Block { + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.is(state.getBlock())) { + if (world.hasNeighborSignal(pos)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + TntBlock.explode(world, pos); + world.removeBlock(pos, false); + } +@@ -0,0 +0,0 @@ public class TntBlock extends Block { + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (world.hasNeighborSignal(pos)) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos);; ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.REDSTONE, null).callEvent()) ++ return; ++ // Paper end + TntBlock.explode(world, pos); + world.removeBlock(pos, false); + } +@@ -0,0 +0,0 @@ public class TntBlock extends Block { + @Override + public void wasExploded(Level world, BlockPos pos, Explosion explosion) { + if (!world.isClientSide) { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); ++ org.bukkit.entity.Entity source = explosion.source != null ? explosion.source.getBukkitEntity() : null; ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.EXPLOSION, source).callEvent()) ++ return; ++ // Paper end + PrimedTnt entitytntprimed = new PrimedTnt(world, (double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D, explosion.getSourceMob()); + int i = entitytntprimed.getFuse(); + +@@ -0,0 +0,0 @@ public class TntBlock extends Block { + if (!itemstack.is(Items.FLINT_AND_STEEL) && !itemstack.is(Items.FIRE_CHARGE)) { + return super.use(state, world, pos, player, hand, hit); + } else { ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, pos); ++ if(!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.ITEM, player.getBukkitEntity()).callEvent()) ++ return InteractionResult.FAIL; ++ // Paper end + TntBlock.explode(world, pos, (LivingEntity) player); + world.setBlock(pos, Blocks.AIR.defaultBlockState(), 11); + Item item = itemstack.getItem(); +@@ -0,0 +0,0 @@ public class TntBlock extends Block { + return; + } + // CraftBukkit end ++ // Paper start - TNTPrimeEvent ++ org.bukkit.block.Block tntBlock = net.minecraft.server.MCUtil.toBukkitBlock(world, blockposition); ++ if (!new com.destroystokyo.paper.event.block.TNTPrimeEvent(tntBlock, com.destroystokyo.paper.event.block.TNTPrimeEvent.PrimeReason.PROJECTILE, projectile.getBukkitEntity()).callEvent()) { ++ return; ++ } ++ // Paper end + TntBlock.explode(world, blockposition, entity instanceof LivingEntity ? (LivingEntity) entity : null); + world.removeBlock(blockposition, false); + } diff --git a/Spigot-Server-Patches/Add-ThrownEggHatchEvent.patch b/patches/server/Add-ThrownEggHatchEvent.patch similarity index 70% rename from Spigot-Server-Patches/Add-ThrownEggHatchEvent.patch rename to patches/server/Add-ThrownEggHatchEvent.patch index 183e2ac240..3ddc4a10ab 100644 --- a/Spigot-Server-Patches/Add-ThrownEggHatchEvent.patch +++ b/patches/server/Add-ThrownEggHatchEvent.patch @@ -6,11 +6,11 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.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 { +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java +@@ -0,0 +0,0 @@ public class ThrownEgg extends ThrowableItemProjectile { hatchingType = event.getHatchingType(); } @@ -22,8 +22,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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()); + Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass()); diff --git a/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch b/patches/server/Add-Unix-domain-socket-support.patch similarity index 53% rename from Spigot-Server-Patches/Add-Unix-domain-socket-support.patch rename to patches/server/Add-Unix-domain-socket-support.patch index 1a2c0f6c96..6f62cbd640 100644 --- a/Spigot-Server-Patches/Add-Unix-domain-socket-support.patch +++ b/patches/server/Add-Unix-domain-socket-support.patch @@ -10,11 +10,11 @@ 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 +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.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> { +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { // Spigot Start public SocketAddress getRawAddress() { @@ -30,13 +30,13 @@ diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b 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 +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + this.setEnforceWhitelist(dedicatedserverproperties.enforceWhitelist); + // this.worldData.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 (this.getLocalIp().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."); @@ -46,12 +46,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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())); ++ bindAddress = new io.netty.channel.unix.DomainSocketAddress(this.getLocalIp().substring("unix:".length())); + } else { InetAddress inetaddress = null; - if (!this.getServerIp().isEmpty()) { -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer + if (!this.getLocalIp().isEmpty()) { +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface if (this.getPort() < 0) { this.setPort(dedicatedserverproperties.serverPort); } @@ -59,28 +59,66 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end - this.P(); - DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getServerIp().isEmpty() ? "*" : this.getServerIp(), this.getPort()); + this.initializeKeyPair(); + DedicatedServer.LOGGER.info("Starting Minecraft server on {}:{}", this.getLocalIp().isEmpty() ? "*" : this.getLocalIp(), this.getPort()); try { -- this.getServerConnection().a(inetaddress, this.getPort()); -+ this.getServerConnection().bind(bindAddress); // Paper - Unix domain socket support +- this.getConnection().startTcpServerListener(inetaddress, this.getPort()); ++ this.getConnection().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 +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.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); +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + this.running = true; + } + ++ // Paper start + public void startTcpServerListener(@Nullable InetAddress address, int port) throws IOException { ++ bind(new java.net.InetSocketAddress(address, port)); ++ } ++ public void bind(java.net.SocketAddress address) throws IOException { ++ // Paper end + List list = this.channels; + + synchronized (this.channels) { +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + LazyLoadedValue lazyinitvar; + + if (Epoll.isAvailable() && this.server.isEpollEnabled()) { ++ if (address instanceof io.netty.channel.unix.DomainSocketAddress) { ++ oclass = io.netty.channel.epoll.EpollServerDomainSocketChannel.class; ++ } else { + oclass = EpollServerSocketChannel.class; ++ } + lazyinitvar = ServerConnectionListener.SERVER_EPOLL_EVENT_GROUP; + ServerConnectionListener.LOGGER.info("Using epoll channel type"); + } else { +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + io.papermc.paper.network.ChannelInitializeListenerHolder.callListeners(channel); // Paper + } +- }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address, port)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit ++ }).group((EventLoopGroup) lazyinitvar.get()).localAddress(address)).option(ChannelOption.AUTO_READ, false).bind().syncUninterruptibly()); // CraftBukkit // Paper + } + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + this.connection.setProtocol(ConnectionProtocol.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 ++ if (!(this.connection.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 { + long connectionThrottle = this.server.server.getConnectionThrottle(); + InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL } } } @@ -88,54 +126,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } 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 { +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL //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 + String[] split = packet.hostName.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.BYPASS_HOSTCHECK || ServerHandshakePacketListenerImpl.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); ++ java.net.SocketAddress socketAddress = connection.getRemoteAddress(); + packet.hostName = split[0]; +- connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getPort()); ++ connection.address = 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] ); + connection.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/patches/server/Add-UnknownCommandEvent.patch similarity index 100% rename from Spigot-Server-Patches/Add-UnknownCommandEvent.patch rename to patches/server/Add-UnknownCommandEvent.patch diff --git a/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch b/patches/server/Add-Velocity-IP-Forwarding-Support.patch similarity index 52% rename from Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch rename to patches/server/Add-Velocity-IP-Forwarding-Support.patch index d75f2ceb46..f08ebe2e75 100644 --- a/Spigot-Server-Patches/Add-Velocity-IP-Forwarding-Support.patch +++ b/patches/server/Add-Velocity-IP-Forwarding-Support.patch @@ -35,10 +35,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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; @@ -52,7 +51,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + velocitySecretKey = secret.getBytes(StandardCharsets.UTF_8); + } + } - } ++ + public static boolean asyncChunks = false; + private static void asyncChunks() { + ConfigurationSection section; 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 @@ -65,9 +67,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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; @@ -75,12 +74,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; ++import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.resources.ResourceLocation; + +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 final ResourceLocation PLAYER_INFO_CHANNEL = new ResourceLocation("velocity", "player_info"); + -+ public static boolean checkIntegrity(final PacketDataSerializer buf) { ++ public static boolean checkIntegrity(final FriendlyByteBuf buf) { + final byte[] signature = new byte[32]; + buf.readBytes(signature); + @@ -106,158 +107,89 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return true; + } + -+ public static InetAddress readAddress(final PacketDataSerializer buf) { -+ return InetAddresses.forString(buf.readUTF(Short.MAX_VALUE)); ++ public static InetAddress readAddress(final FriendlyByteBuf 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)); ++ public static GameProfile createProfile(final FriendlyByteBuf 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) { ++ private static void readProperties(final FriendlyByteBuf 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; ++ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.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 { @@ -283,13 +215,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + gameProfile.getName(), ex); + } + }); + return; + } + // Paper end - this.disconnect(new ChatMessage("multiplayer.disconnect.unexpected_query_response")); + this.disconnect(new TranslatableComponent("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 diff --git a/patches/server/Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/Add-Wandering-Trader-spawn-rate-config-options.patch new file mode 100644 index 0000000000..997d3c93be --- /dev/null +++ b/patches/server/Add-Wandering-Trader-spawn-rate-config-options.patch @@ -0,0 +1,111 @@ +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 { + } + } + ++ 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); ++ } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -0,0 +0,0 @@ public class WanderingTraderSpawner implements CustomSpawner { + + public WanderingTraderSpawner(ServerLevelData properties) { + this.serverLevelData = properties; +- this.tickDelay = 1200; +- this.spawnDelay = properties.getWanderingTraderSpawnDelay(); +- this.spawnChance = properties.getWanderingTraderSpawnChance(); +- if (this.spawnDelay == 0 && this.spawnChance == 0) { +- this.spawnDelay = 24000; +- properties.setWanderingTraderSpawnDelay(this.spawnDelay); +- this.spawnChance = 25; +- properties.setWanderingTraderSpawnChance(this.spawnChance); +- } ++ // Paper start ++ this.tickDelay = Integer.MIN_VALUE; ++ //this.spawnDelay = properties.getWanderingTraderSpawnDelay(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //this.spawnChance = properties.getWanderingTraderSpawnChance(); // Paper - This value is read from the world file only for the first spawn, after which vanilla uses a hardcoded value ++ //if (this.spawnDelay == 0 && this.spawnChance == 0) { ++ // this.spawnDelay = 24000; ++ // properties.setWanderingTraderSpawnDelay(this.spawnDelay); ++ // this.spawnChance = 25; ++ // properties.setWanderingTraderSpawnChance(this.spawnChance); ++ //} ++ // Paper end + + } + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { ++ // Paper start ++ if (this.tickDelay == Integer.MIN_VALUE) { ++ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks; ++ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks; ++ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin; ++ } + if (!world.getGameRules().getBoolean(GameRules.RULE_DO_TRADER_SPAWNING)) { + return 0; +- } else if (--this.tickDelay > 0) { ++ } else if (this.tickDelay - 1 > 0) { ++ this.tickDelay = this.tickDelay - 1; + return 0; + } else { +- this.tickDelay = 1200; +- this.spawnDelay -= 1200; +- this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); ++ this.tickDelay = world.paperConfig.wanderingTraderSpawnMinuteTicks; ++ this.spawnDelay = this.spawnDelay - world.paperConfig.wanderingTraderSpawnMinuteTicks; ++ //this.serverLevelData.setWanderingTraderSpawnDelay(this.spawnDelay); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways + if (this.spawnDelay > 0) { + return 0; + } else { +- this.spawnDelay = 24000; ++ this.spawnDelay = world.paperConfig.wanderingTraderSpawnDayTicks; + if (!world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { + return 0; + } else { + int i = this.spawnChance; + +- this.spawnChance = Mth.clamp(this.spawnChance + 25, 25, 75); +- this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); ++ this.spawnChance = Mth.clamp(i + world.paperConfig.wanderingTraderSpawnChanceFailureIncrement, world.paperConfig.wanderingTraderSpawnChanceMin, world.paperConfig.wanderingTraderSpawnChanceMax); ++ //this.serverLevelData.setWanderingTraderSpawnChance(this.spawnChance); // Paper - We don't need to save this value to disk if it gets set back to a hardcoded value anyways + if (this.random.nextInt(100) > i) { + return 0; + } else if (this.spawn(world)) { +- this.spawnChance = 25; ++ this.spawnChance = world.paperConfig.wanderingTraderSpawnChanceMin; ++ // Paper end + return 1; + } else { + return 0; diff --git a/patches/server/Add-World-Util-Methods.patch b/patches/server/Add-World-Util-Methods.patch new file mode 100644 index 0000000000..e30e7e94dd --- /dev/null +++ b/patches/server/Add-World-Util-Methods.patch @@ -0,0 +1,53 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + +- public LevelChunk getChunkIfLoaded(int x, int z) { ++ @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); + } + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + @Override +- public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ public final FluidState getFluidIfLoaded(BlockPos blockposition) { + ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); + + return chunk == null ? null : chunk.getFluidState(blockposition); + } ++ ++ public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline ++ return getWorldBorder().isWithinBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; ++ } ++ ++ public LevelChunk getChunkIfLoaded(int x, int z) { // Overridden in WorldServer for ABI compat which has final ++ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(x, z); ++ } ++ public final LevelChunk getChunkIfLoaded(BlockPos blockposition) { ++ return ((ServerLevel) this).getChunkSource().getChunkAtIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ } ++ ++ // reduces need to do isLoaded before getType ++ public final BlockState getTypeIfLoadedAndInBounds(BlockPos blockposition) { ++ return getWorldBorder().isWithinBounds(blockposition) ? getTypeIfLoaded(blockposition) : null; ++ } + // Paper end + + @Override diff --git a/Spigot-Server-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 50% rename from Spigot-Server-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/server/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch index 56e162de3b..9e64ecebf7 100644 --- a/Spigot-Server-Patches/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ b/patches/server/Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -5,36 +5,74 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.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 { +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -0,0 +0,0 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + return MobType.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 aiStep() { +- boolean flag = this.isSunBurnTick(); ++ boolean flag = shouldBurnInDay && this.isSunBurnTick(); // Paper - Configurable Burning + + if (flag) { + ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); +@@ -0,0 +0,0 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + public void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); + this.reassessWeaponGoal(); ++ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); // Paper ++ } ++ ++ // Paper start ++ @Override ++ public void addAdditionalSaveData(CompoundTag nbt) { ++ super.addAdditionalSaveData(nbt); ++ nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); + } ++ // Paper end @Override - public void movementTick() { -- if (this.isAlive() && this.eG()) { -+ if (this.isAlive() && shouldBurnInDay && this.eG()) { // Paper - Configurable Burning - this.setOnFire(8); + public void setItemSlot(EquipmentSlot slot, ItemStack stack) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { + + @Override + public void aiStep() { +- if (this.isAlive() && this.isSunBurnTick()) { ++ if (this.isAlive() && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning + this.setSecondsOnFire(8); } -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { - if (nbttagcompound.hasUUID("Paper.SpawningEntity")) { - this.spawningEntity = nbttagcompound.getUUID("Paper.SpawningEntity"); +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { + if (nbt.hasUUID("Paper.SpawningEntity")) { + this.spawningEntity = nbt.getUUID("Paper.SpawningEntity"); } -+ this.shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); ++ this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); // Paper end } -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { if (this.spawningEntity != null) { - nbttagcompound.setUUID("Paper.SpawningEntity", this.spawningEntity); + nbt.putUUID("Paper.SpawningEntity", this.spawningEntity); } -+ nbttagcompound.setBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); ++ nbt.putBoolean("Paper.ShouldBurnInDay", shouldBurnInDay); // Paper end } -@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster { +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { return spawningEntity; } public void setSpawningEntity(java.util.UUID entity) { this.spawningEntity = entity; } @@ -43,46 +81,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public boolean shouldBurnInDay() { return shouldBurnInDay; } + public void setShouldBurnInDay(boolean shouldBurnInDay) { this.shouldBurnInDay = shouldBurnInDay; } // Paper end + private static enum AttackPhase { - 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 @@ -107,9 +107,9 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/sr 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."); +@@ -0,0 +0,0 @@ public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton, co + public SkeletonType getSkeletonType() { + return SkeletonType.NORMAL; } + + // Paper start diff --git a/patches/server/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch b/patches/server/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch new file mode 100644 index 0000000000..99ba4f06ff --- /dev/null +++ b/patches/server/Add-a-way-to-get-translation-keys-for-blocks-entitie.patch @@ -0,0 +1,65 @@ +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/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().defaultBlockState().getSoundType()); + } ++ ++ @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).getDescriptionId(); ++ } ++ return getItem(mat).getDescriptionId(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.block.Block block) { ++ return ((org.bukkit.craftbukkit.block.CraftBlock)block).getNMS().getBlock().getDescriptionId(); ++ } ++ ++ @Override ++ public String getTranslationKey(org.bukkit.entity.EntityType type) { ++ return net.minecraft.world.entity.EntityType.byString(type.getName()).map(net.minecraft.world.entity.EntityType::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/patches/server/Add-ability-to-configure-frosted_ice-properties.patch b/patches/server/Add-ability-to-configure-frosted_ice-properties.patch new file mode 100644 index 0000000000..ed71800121 --- /dev/null +++ b/patches/server/Add-ability-to-configure-frosted_ice-properties.patch @@ -0,0 +1,52 @@ +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/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +@@ -0,0 +0,0 @@ public class FrostedIceBlock extends IceBlock { + + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { ++ if (!world.paperConfig.frostedIceEnabled) return; // Paper - add ability to disable frosted ice + if ((random.nextInt(3) == 0 || this.fewerNeigboursThan(world, pos, 4)) && world.getMaxLocalRawBrightness(pos) > 11 - state.getValue(AGE) - state.getLightBlock(world, pos) && this.slightlyMelt(state, world, pos)) { + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + +@@ -0,0 +0,0 @@ public class FrostedIceBlock extends IceBlock { + mutableBlockPos.setWithOffset(pos, direction); + BlockState blockState = world.getBlockState(mutableBlockPos); + if (blockState.is(this) && !this.slightlyMelt(blockState, world, mutableBlockPos)) { +- world.getBlockTicks().scheduleTick(mutableBlockPos, this, Mth.nextInt(random, 20, 40)); ++ world.getBlockTicks().scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + + } else { +- world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, 20, 40)); ++ world.getBlockTicks().scheduleTick(pos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } + } + diff --git a/Spigot-Server-Patches/Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/Add-additional-open-container-api-to-HumanEntity.patch similarity index 87% rename from Spigot-Server-Patches/Add-additional-open-container-api-to-HumanEntity.patch rename to patches/server/Add-additional-open-container-api-to-HumanEntity.patch index d9f286da23..c35cfeb1d7 100644 --- a/Spigot-Server-Patches/Add-additional-open-container-api-to-HumanEntity.patch +++ b/patches/server/Add-additional-open-container-api-to-HumanEntity.patch @@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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(); + return this.getHandle().containerMenu.getBukkitView(); } + // Paper start - Add additional containers @@ -70,12 +70,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } 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(); ++ getHandle().openMenu(block.getMenuProvider(null, getHandle().level, new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()))); ++ getHandle().containerMenu.checkReachable = !force; ++ return getHandle().containerMenu.getBukkitView(); + } + // Paper end + @Override public void closeInventory() { - // Paper start + this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); diff --git a/patches/server/Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server/Add-and-implement-PlayerRecipeBookClickEvent.patch new file mode 100644 index 0000000000..351e9bb0c8 --- /dev/null +++ b/patches/server/Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -0,0 +1,27 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + this.player.resetLastActionTime(); + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) { +- this.server.getRecipeManager().byKey(packet.getRecipe()).ifPresent((irecipe) -> { +- ((RecipeBookMenu) this.player.containerMenu).handlePlacement(packet.isShiftDown(), 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(packet.getRecipe()), packet.isShiftDown()); ++ if (event.callEvent()) { ++ this.server.getRecipeManager().byKey(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getRecipe())).ifPresent((irecipe) -> { ++ ((RecipeBookMenu) this.player.containerMenu).handlePlacement(event.isMakeAll(), irecipe, this.player); + }); ++ } // Paper end + } + } + diff --git a/patches/server/Add-basic-Datapack-API.patch b/patches/server/Add-basic-Datapack-API.patch new file mode 100644 index 0000000000..0b3fce60b2 --- /dev/null +++ b/patches/server/Add-basic-Datapack-API.patch @@ -0,0 +1,125 @@ +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.Pack; ++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(Pack loader, boolean enabled) { ++ this.name = loader.getId(); ++ this.compatibility = Compatibility.valueOf(loader.getCompatibility().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.getPackRepository().getSelectedPacks().stream().map(Pack::getId).collect(Collectors.toList()); ++ if (enabled) { ++ enabledKeys.add(this.name); ++ } else { ++ enabledKeys.remove(this.name); ++ } ++ server.reloadResources(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 java.util.Collection; ++import java.util.stream.Collectors; ++import net.minecraft.server.packs.repository.Pack; ++import net.minecraft.server.packs.repository.PackRepository; ++ ++public class PaperDatapackManager implements DatapackManager { ++ private final PackRepository repository; ++ ++ public PaperDatapackManager(PackRepository repository) { ++ this.repository = repository; ++ } ++ ++ @Override ++ public Collection getPacks() { ++ Collection enabledPacks = repository.getSelectedPacks(); ++ return repository.getAvailablePacks().stream().map(loader -> new PaperDatapack(loader, enabledPacks.contains(loader))).collect(Collectors.toList()); ++ } ++ ++ @Override ++ public Collection getEnabledPacks() { ++ return repository.getSelectedPacks().stream().map(loader -> new PaperDatapack(loader, true)).collect(Collectors.toList()); ++ } ++} +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; ++ private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper + public static Exception excessiveVelEx; // Paper - Velocity warnings + + static { +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + TicketType.PLUGIN.timeout = Math.min(20, this.configuration.getInt("chunk-gc.period-in-ticks")); // Paper - cap plugin loads to 1 second + this.minimumAPI = this.configuration.getString("settings.minimum-api"); + this.loadIcon(); ++ datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // 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 io.papermc.paper.datapack.PaperDatapackManager getDatapackManager() { ++ return datapackManager; ++ } ++ + // Paper end + } diff --git a/patches/server/Add-bypass-host-check.patch b/patches/server/Add-bypass-host-check.patch new file mode 100644 index 0000000000..9e706e3fc5 --- /dev/null +++ b/patches/server/Add-bypass-host-check.patch @@ -0,0 +1,30 @@ +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/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + private static final Component IGNORE_STATUS_REASON = new TextComponent("Ignoring status request"); + private final MinecraftServer server; + private final Connection connection; ++ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper + + public ServerHandshakePacketListenerImpl(MinecraftServer server, Connection connection) { + this.server = server; +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + // Spigot Start + //if (org.spigotmc.SpigotConfig.bungee) { // Paper - comment out, we check above! + String[] split = packet.hostName.split("\00"); +- if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { ++ if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.BYPASS_HOSTCHECK || ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { // Paper + packet.hostName = split[0]; + connection.address = new java.net.InetSocketAddress(split[1], ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getPort()); + connection.spoofedUUID = com.mojang.util.UUIDTypeAdapter.fromString( split[2] ); diff --git a/patches/server/Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/server/Add-cause-to-Weather-ThunderChangeEvents.patch new file mode 100644 index 0000000000..e5ad404dbf --- /dev/null +++ b/patches/server/Add-cause-to-Weather-ThunderChangeEvents.patch @@ -0,0 +1,127 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.serverLevelData.setClearWeatherTime(clearDuration); + this.serverLevelData.setRainTime(rainDuration); + this.serverLevelData.setThunderTime(rainDuration); +- this.serverLevelData.setRaining(raining); +- this.serverLevelData.setThundering(thundering); ++ this.serverLevelData.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.COMMAND); // Paper ++ this.serverLevelData.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.COMMAND); // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.serverLevelData.setThunderTime(j); + this.serverLevelData.setRainTime(k); + this.serverLevelData.setClearWeatherTime(i); +- this.serverLevelData.setThundering(flag1); +- this.serverLevelData.setRaining(flag2); ++ this.serverLevelData.setThundering(flag1, org.bukkit.event.weather.ThunderChangeEvent.Cause.NATURAL); // Paper ++ this.serverLevelData.setRaining(flag2, org.bukkit.event.weather.WeatherChangeEvent.Cause.NATURAL); // Paper + } + + this.oThunderLevel = this.thunderLevel; +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + private void stopWeather() { + // CraftBukkit start +- this.serverLevelData.setRaining(false); ++ this.serverLevelData.setRaining(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.serverLevelData.isRaining()) { + this.serverLevelData.setRainTime(0); + } + // CraftBukkit end +- this.serverLevelData.setThundering(false); ++ this.serverLevelData.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/PrimaryLevelData.java b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java ++++ b/src/main/java/net/minecraft/world/level/storage/PrimaryLevelData.java +@@ -0,0 +0,0 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { + + @Override + public void setThundering(boolean thundering) { ++ // Paper start ++ this.setThundering(thundering, 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 == thundering) { ++ if (this.thundering == flag) { + return; + } + + org.bukkit.World world = Bukkit.getWorld(this.getLevelName()); + if (world != null) { +- ThunderChangeEvent thunder = new ThunderChangeEvent(world, thundering); ++ ThunderChangeEvent thunder = new ThunderChangeEvent(world, flag, cause); // Paper + Bukkit.getServer().getPluginManager().callEvent(thunder); + if (thunder.isCancelled()) { + return; + } + } + // CraftBukkit end +- this.thundering = thundering; ++ this.thundering = flag; + } + + @Override +@@ -0,0 +0,0 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { + + @Override + public void setRaining(boolean raining) { ++ // Paper start ++ this.setRaining(raining, org.bukkit.event.weather.WeatherChangeEvent.Cause.UNKNOWN); ++ } ++ ++ public void setRaining(boolean raining, org.bukkit.event.weather.WeatherChangeEvent.Cause cause) { ++ // Paper end + // CraftBukkit start + if (this.raining == raining) { + return; +@@ -0,0 +0,0 @@ public class PrimaryLevelData implements ServerLevelData, WorldData { + + org.bukkit.World world = Bukkit.getWorld(this.getLevelName()); + if (world != null) { +- WeatherChangeEvent weather = new WeatherChangeEvent(world, raining); ++ WeatherChangeEvent weather = new WeatherChangeEvent(world, raining, 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.levelData.setRaining(hasStorm); ++ world.serverLevelData.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper + this.setWeatherDuration(0); // Reset weather duration (legacy behaviour) + this.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.serverLevelData.setThundering(thundering); ++ world.serverLevelData.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper + this.setThunderDuration(0); // Reset weather duration (legacy behaviour) + this.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/patches/server/Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 93% rename from Spigot-Server-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/Add-command-line-option-to-load-extra-plugin-jars-no.patch index de900ec33c..35ae529878 100644 --- a/Spigot-Server-Patches/Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ b/patches/server/Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -15,13 +15,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 File pluginFolder = (File) console.options.valueOf("plugins"); - if (pluginFolder.exists()) { -- Plugin[] plugins = pluginManager.loadPlugins(pluginFolder); +- Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder); + // Paper start + if (true || pluginFolder.exists()) { + if (!pluginFolder.exists()) { + pluginFolder.mkdirs(); + } -+ Plugin[] plugins = pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); ++ Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); + // Paper end for (Plugin plugin : plugins) { try { @@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void enablePlugins(PluginLoadOrder type) { if (type == PluginLoadOrder.STARTUP) { - helpMap.clear(); + this.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 diff --git a/patches/server/Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server/Add-config-to-disable-ender-dragon-legacy-check.patch new file mode 100644 index 0000000000..528f6629e5 --- /dev/null +++ b/patches/server/Add-config-to-disable-ender-dragon-legacy-check.patch @@ -0,0 +1,35 @@ +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/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -0,0 +0,0 @@ public class EndDragonFight { + private List respawnCrystals; + + public EndDragonFight(ServerLevel world, long gatewaysSeed, CompoundTag nbt) { ++ // Paper start ++ this.needsStateScanning = world.paperConfig.scanForLegacyEnderDragon; ++ if (!this.needsStateScanning) this.dragonKilled = true; ++ // Paper end + this.level = world; + if (nbt.contains("NeedsStateScanning")) { + this.needsStateScanning = nbt.getBoolean("NeedsStateScanning"); diff --git a/Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch b/patches/server/Add-configurable-despawn-distances-for-living-entiti.patch similarity index 64% rename from Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch rename to patches/server/Add-configurable-despawn-distances-for-living-entiti.patch index 974c7c1e57..6548ecac98 100644 --- a/Spigot-Server-Patches/Add-configurable-despawn-distances-for-living-entiti.patch +++ b/patches/server/Add-configurable-despawn-distances-for-living-entiti.patch @@ -29,27 +29,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.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(); +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + int i = this.getType().getCategory().getDespawnDistance(); 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(); ++ if (d0 > (double) level.paperConfig.hardDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.discard(); } - int k = this.getEntityType().e().g(); + int k = this.getType().getCategory().getNoDespawnDistance(); 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(); +- if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > (double) l) { // CraftBukkit - remove isTypeNotPersistent() check ++ if (this.noActionTime > 600 && this.random.nextInt(800) == 0 && d0 > level.paperConfig.softDespawnDistance) { // CraftBukkit - remove isTypeNotPersistent() check // Paper - custom despawn distances + this.discard(); - } else if (d0 < (double) l) { -+ } else if (d0 < world.paperConfig.softDespawnDistance) { // Paper - custom despawn distances - this.ticksFarFromPlayer = 0; ++ } else if (d0 < level.paperConfig.softDespawnDistance) { // Paper - custom despawn distances + this.noActionTime = 0; } } diff --git a/Spigot-Server-Patches/Add-configurable-portal-search-radius.patch b/patches/server/Add-configurable-portal-search-radius.patch similarity index 54% rename from Spigot-Server-Patches/Add-configurable-portal-search-radius.patch rename to patches/server/Add-configurable-portal-search-radius.patch index 584b4ae3a9..d833b08182 100644 --- a/Spigot-Server-Patches/Add-configurable-portal-search-radius.patch +++ b/patches/server/Add-configurable-portal-search-radius.patch @@ -26,31 +26,31 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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)); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + double d4 = DimensionType.getTeleportationScale(this.level.dimensionType(), destination.dimensionType()); + BlockPos blockposition = new BlockPos(Mth.clamp(this.getX() * d4, d0, d2), this.getY(), Mth.clamp(this.getZ() * d4, d1, d3)); // CraftBukkit start -- CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); +- CraftPortalEvent event = this.callPortalEvent(this, destination, 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()); ++ int portalSearchRadius = destination.paperConfig.portalSearchRadius; ++ if (level.paperConfig.portalSearchVanillaDimensionScaling && flag2) { // == THE_NETHER ++ portalSearchRadius = (int) (portalSearchRadius / destination.dimensionType().coordinateScale()); + } + // Paper end -+ CraftPortalEvent event = callPortalEvent(this, worldserver, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, worldserver.paperConfig.portalCreateRadius); // Paper start - configurable portal radius ++ CraftPortalEvent event = this.callPortalEvent(this, destination, blockposition, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, portalSearchRadius, destination.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 +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.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 { +--- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java +@@ -0,0 +0,0 @@ public class PortalForcer { - public Optional findPortal(BlockPosition blockposition, boolean flag) { + public Optional findPortalAround(BlockPos destPos, boolean destIsNether) { // CraftBukkit start -- return findPortal(blockposition, flag ? 16 : 128); // Search Radius -+ return findPortal(blockposition, flag ? world.paperConfig.portalCreateRadius : world.paperConfig.portalSearchRadius); // Paper - search Radius +- return this.findPortal(destPos, destIsNether ? 16 : 128); // Search Radius ++ return this.findPortal(destPos, destIsNether ? level.paperConfig.portalCreateRadius : level.paperConfig.portalSearchRadius); // Search Radius // Paper - search Radius } - public Optional findPortal(BlockPosition blockposition, int i) { + public Optional findPortal(BlockPos blockposition, int i) { diff --git a/Spigot-Server-Patches/Add-configuration-option-to-prevent-player-names-fro.patch b/patches/server/Add-configuration-option-to-prevent-player-names-fro.patch similarity index 100% rename from Spigot-Server-Patches/Add-configuration-option-to-prevent-player-names-fro.patch rename to patches/server/Add-configuration-option-to-prevent-player-names-fro.patch diff --git a/Spigot-Server-Patches/Reduce-sync-loads.patch b/patches/server/Add-debug-for-sync-chunk-loads.patch similarity index 70% rename from Spigot-Server-Patches/Reduce-sync-loads.patch rename to patches/server/Add-debug-for-sync-chunk-loads.patch index 41ac7f9723..081077acbe 100644 --- a/Spigot-Server-Patches/Reduce-sync-loads.patch +++ b/patches/server/Add-debug-for-sync-chunk-loads.patch @@ -1,12 +1,11 @@ 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 +Subject: [PATCH] Add debug for sync chunk 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 +This patch adds a tool to find calls to getChunkAt which would load +chunks, 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 @@ -17,23 +16,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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.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.resources.ResourceLocation; +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 net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; import java.io.File; @@ -42,19 +40,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.io.StringWriter; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; - import java.util.ArrayList; + import java.util.ArrayDeque; @@ -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(); +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight", "syncloadinfo").build(); public PaperCommand(String name) { super(name); @@ -0,0 +0,0 @@ public class PaperCommand extends Command { - case "chunkinfo": - doChunkInfo(sender, args); + case "fixlight": + this.doFixLight(sender, args); break; + case "syncloadinfo": + this.doSyncLoadInfo(sender, args); @@ -122,13 +120,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; -+import net.minecraft.world.level.World; ++import net.minecraft.world.level.Level; + +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 WeakHashMap> SYNC_LOADS = new WeakHashMap<>(); + + private static final class SyncLoadInformation { + @@ -137,14 +135,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public final Long2IntOpenHashMap coordinateTimes = new Long2IntOpenHashMap(); + } + -+ public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { ++ public static void logSyncLoad(final Level 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) -> { ++ SYNC_LOADS.compute(world, (final Level keyInMap, Object2ObjectOpenHashMap map) -> { + if (map == null) { + map = new Object2ObjectOpenHashMap<>(); + } @@ -172,8 +170,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + final JsonArray worldsData = new JsonArray(); + -+ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { -+ final World world = entry.getKey(); ++ for (final Map.Entry> entry : SYNC_LOADS.entrySet()) { ++ final Level world = entry.getKey(); + + final JsonObject worldData = new JsonObject(); + @@ -280,63 +278,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } +} -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.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); +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); // 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.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info + this.level.timings.syncChunkLoad.startTiming(); // Paper + chunkproviderserver_a.managedBlock(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 +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 { +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl }; 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; ++ public boolean hasChunk(int chunkX, int chunkZ) { ++ return this.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ) != 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); + // Paper start - optimise getPlayerByUUID + @Nullable diff --git a/patches/server/Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/server/Add-dropLeash-variable-to-EntityUnleashEvent.patch new file mode 100644 index 0000000000..0740c351dd --- /dev/null +++ b/patches/server/Add-dropLeash-variable-to-EntityUnleashEvent.patch @@ -0,0 +1,140 @@ +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/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == player) { + // CraftBukkit start - fire PlayerUnleashEntityEvent +- if (CraftEventFactory.callPlayerUnleashEntityEvent(this, player).isCancelled()) { ++ // Paper start - drop leash variable ++ org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(this, player, !player.getAbilities().instabuild); ++ if (event.isCancelled()) { ++ // Paper end + ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); + return InteractionResult.PASS; + } + // CraftBukkit end +- this.dropLeash(true, !player.getAbilities().instabuild); ++ this.dropLeash(true, event.isDropLeash()); // Paper - drop leash variable + return InteractionResult.sidedSuccess(this.level.isClientSide); + } else { + InteractionResult enuminteractionresult = this.checkAndHandleImportantInteractions(player, hand); +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? UnleashReason.PLAYER_UNLEASH : UnleashReason.HOLDER_GONE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + } +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + boolean flag1 = super.startRiding(entity, force); + + if (flag1 && this.isLeashed()) { +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + return flag1; +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + @Override + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN)); // CraftBukkit +- this.dropLeash(true, false); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.UNKNOWN, false); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + this.getAllSlots().forEach((itemstack) -> { + if (!itemstack.isEmpty()) itemstack.setCount(0); // CraftBukkit + }); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -0,0 +0,0 @@ public abstract class PathfinderMob extends Mob { + + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { + if (f > entity.level.paperConfig.maxLeashDistance) { // Paper +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + } + + return; +@@ -0,0 +0,0 @@ public abstract class PathfinderMob extends Mob { + + this.onLeashDistance(f); + if (f > entity.level.paperConfig.maxLeashDistance) { // Paper +- this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit +- this.dropLeash(true, true); ++ // Paper start - drop leash variable ++ EntityUnleashEvent event = new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE, true); ++ this.level.getCraftServer().getPluginManager().callEvent(event); // CraftBukkit ++ this.dropLeash(true, event.isDropLeash()); ++ // Paper end + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); + } else if (f > 6.0F) { + double d0 = (entity.getX() - this.getX()) / (double) f; +diff --git a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/LeashFenceKnotEntity.java +@@ -0,0 +0,0 @@ public class LeashFenceKnotEntity extends HangingEntity { + entityinsentient = (Mob) iterator.next(); + if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == this) { + // CraftBukkit start +- if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player).isCancelled()) { ++ // Paper start - drop leash variable ++ org.bukkit.event.player.PlayerUnleashEntityEvent event = CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, player, !player.getAbilities().instabuild); ++ if (event.isCancelled()) { ++ // Paper end + die = false; + continue; + } +- entityinsentient.dropLeash(true, !player.getAbilities().instabuild); // false -> survival mode boolean ++ entityinsentient.dropLeash(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(Mob entity, net.minecraft.world.entity.player.Player player) { +- PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity()); ++ // Paper start - drop leash variable ++ public static PlayerUnleashEntityEvent callPlayerUnleashEntityEvent(Mob entity, net.minecraft.world.entity.player.Player player, boolean dropLeash) { ++ PlayerUnleashEntityEvent event = new PlayerUnleashEntityEvent(entity.getBukkitEntity(), (Player) player.getBukkitEntity(), dropLeash); ++ // Paper end + entity.level.getCraftServer().getPluginManager().callEvent(event); + return event; + } diff --git a/Spigot-Server-Patches/Add-effect-to-block-break-naturally.patch b/patches/server/Add-effect-to-block-break-naturally.patch similarity index 72% rename from Spigot-Server-Patches/Add-effect-to-block-break-naturally.patch rename to patches/server/Add-effect-to-block-break-naturally.patch index 4c183d1106..59e3609911 100644 --- a/Spigot-Server-Patches/Add-effect-to-block-break-naturally.patch +++ b/patches/server/Add-effect-to-block-break-naturally.patch @@ -20,13 +20,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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.state.BlockState 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 + if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) { + net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), position, this.world.getBlockEntity(position), null, nmsItem); ++ if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper result = true; } diff --git a/Spigot-Server-Patches/Add-entity-liquid-API.patch b/patches/server/Add-entity-liquid-API.patch similarity index 53% rename from Spigot-Server-Patches/Add-entity-liquid-API.patch rename to patches/server/Add-entity-liquid-API.patch index a531656cd1..a8c4164158 100644 --- a/Spigot-Server-Patches/Add-entity-liquid-API.patch +++ b/patches/server/Add-entity-liquid-API.patch @@ -8,36 +8,13 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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; +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + return this.isInWater() || this.isInRain(); } -- 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; +- @Deprecated public final boolean isInWaterOrRainOrBubble() { return isInWaterRainOrBubble(); } // Paper - OBFHELPER + public boolean isInWaterRainOrBubble() { + return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); } 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 @@ -61,11 +38,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + public boolean isInWaterOrBubbleColumn() { -+ return getHandle().isInWaterOrBubbleColumn(); ++ return getHandle().isInWaterOrBubble(); + } + + public boolean isInWaterOrRainOrBubbleColumn() { -+ return getHandle().isInWaterOrRainOrBubble(); ++ return getHandle().isInWaterRainOrBubble(); + } + + public boolean isInLava() { diff --git a/Spigot-Server-Patches/Add-environment-variable-to-disable-server-gui.patch b/patches/server/Add-environment-variable-to-disable-server-gui.patch similarity index 94% rename from Spigot-Server-Patches/Add-environment-variable-to-disable-server-gui.patch rename to patches/server/Add-environment-variable-to-disable-server-gui.patch index 7b868cfcda..656ff73e78 100644 --- a/Spigot-Server-Patches/Add-environment-variable-to-disable-server-gui.patch +++ b/patches/server/Add-environment-variable-to-disable-server-gui.patch @@ -14,5 +14,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if(!Boolean.parseBoolean(System.getenv().getOrDefault("PAPER_DISABLE_SERVER_GUI", String.valueOf(false)))) // Paper if (flag1 && !GraphicsEnvironment.isHeadless()) { - dedicatedserver1.bd(); + dedicatedserver1.showGui(); } diff --git a/Spigot-Server-Patches/Add-exception-reporting-event.patch b/patches/server/Add-exception-reporting-event.patch similarity index 59% rename from Spigot-Server-Patches/Add-exception-reporting-event.patch rename to patches/server/Add-exception-reporting-event.patch index cc82314f53..7962710f99 100644 --- a/Spigot-Server-Patches/Add-exception-reporting-event.patch +++ b/patches/server/Add-exception-reporting-event.patch @@ -48,22 +48,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return internalTask; + } +} -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 { +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return true; } catch (Exception exception) { - PlayerChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception); + ChunkMap.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 +diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.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 +--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java ++++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java @@ -0,0 +0,0 @@ package net.minecraft.server.players; @@ -71,16 +71,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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)); +@@ -0,0 +0,0 @@ public class OldUsersConverter { + root = NbtIo.readCompressed(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)); +@@ -0,0 +0,0 @@ public class OldUsersConverter { + NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2)); } catch (Exception exception) { exception.printStackTrace(); + ServerInternalException.reportInternalException(exception); // Paper @@ -98,39 +98,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); + import net.minecraft.core.BlockPos; +@@ -0,0 +0,0 @@ public class VillageSiege implements CustomSpawner { + entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) 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 +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java @@ -0,0 +0,0 @@ package net.minecraft.world.level; @@ -142,62 +122,82 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + tickConsumer.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("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); ++ String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); + System.err.println(msg); throwable.printStackTrace(); -+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); - entity.dead = true; - return; ++ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable))); + entity.discard(); // 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 + } +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.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 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + } + } catch (Exception exception) { + NaturalSpawner.LOGGER.warn("Failed to create mob", exception); ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper + return null; + } + } +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + entity = biomesettingsmobs_c.type.create((Level) world.getLevel()); + } catch (Exception exception) { + NaturalSpawner.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/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -0,0 +0,0 @@ package net.minecraft.world.level.chunk; + import com.google.common.collect.ImmutableList; +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); + import com.google.common.collect.UnmodifiableIterator; +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + this.removeBlockEntity(blockEntity.getBlockPos()); // 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)); +- System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() +- + " (" + this.getBlockState(blockposition) + ") where there was no entity tile!"); +- System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.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)); ++ "Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," ++ + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() ++ + " (" + getBlockState(blockposition) + ") where there was no entity tile!\n" + ++ "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); + e.printStackTrace(); + ServerInternalException.reportInternalException(e); + // Paper end // CraftBukkit end } } +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + gameprofilerfiller.pop(); + } catch (Throwable throwable) { + // Paper start - Prevent tile entity and entity crashes +- System.err.println("TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ()); ++ String msg = "TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ(); ++ System.err.println(msg); + throwable.printStackTrace(); ++ net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new ServerInternalException(msg, throwable))); + LevelChunk.this.removeBlockEntity(this.getPos()); + // Paper end + // Spigot start 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 @@ -211,25 +211,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + ((java.nio.Buffer) bytebuffer).position(5); // CraftBukkit - decompile error filechannel.write(bytebuffer); - } catch (Throwable throwable1) { - throwable = throwable1; + } catch (Throwable throwable) { + 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 + try { + filechannel.close(); +diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.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) { +--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +@@ -0,0 +0,0 @@ public class DimensionDataStorage { + + pushbackInputStream.close(); + } catch (Throwable var15) { ++ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(var15); // Paper + try { + fileInputStream.close(); + } catch (Throwable var10) { 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 @@ -252,13 +252,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task))); // Paper end } finally { - currentTask = null; + this.currentTask = null; @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); + this.parsePending(); } else { - debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); -- executor.execute(task); -+ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); +- this.executor.execute(task); ++ this.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/patches/server/Add-fast-alternative-constructor-for-Rotations.patch b/patches/server/Add-fast-alternative-constructor-for-Rotations.patch new file mode 100644 index 0000000000..81a66d2f29 --- /dev/null +++ b/patches/server/Add-fast-alternative-constructor-for-Rotations.patch @@ -0,0 +1,30 @@ +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 Rotations + +Signed-off-by: Irmo van den Berge + +diff --git a/src/main/java/net/minecraft/core/Rotations.java b/src/main/java/net/minecraft/core/Rotations.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/Rotations.java ++++ b/src/main/java/net/minecraft/core/Rotations.java +@@ -0,0 +0,0 @@ public class Rotations { + this(serialized.getFloat(0), serialized.getFloat(1), serialized.getFloat(2)); + } + ++ // Paper start - faster alternative constructor ++ private Rotations(float x, float y, float z, Void dummy_var) { ++ this.x = x; ++ this.y = y; ++ this.z = z; ++ } ++ ++ public static Rotations createWithoutValidityChecks(float x, float y, float z) { ++ return new Rotations(x, y, z, null); ++ } ++ // Paper end ++ + public ListTag save() { + ListTag listTag = new ListTag(); + listTag.add(FloatTag.valueOf(this.x)); diff --git a/Spigot-Server-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/server/Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from Spigot-Server-Patches/Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/server/Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/Spigot-Server-Patches/Add-getOfflinePlayerIfCached-String.patch b/patches/server/Add-getOfflinePlayerIfCached-String.patch similarity index 93% rename from Spigot-Server-Patches/Add-getOfflinePlayerIfCached-String.patch rename to patches/server/Add-getOfflinePlayerIfCached-String.patch index 96ab5c9c1f..3783e2967d 100644 --- a/Spigot-Server-Patches/Add-getOfflinePlayerIfCached-String.patch +++ b/patches/server/Add-getOfflinePlayerIfCached-String.patch @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + OfflinePlayer result = getPlayerExact(name); + if (result == null) { -+ GameProfile profile = console.getUserCache().getProfileIfCached(name); ++ GameProfile profile = console.getProfileCache().getProfileIfCached(name); + + if (profile != null) { + result = getOfflinePlayer(profile); diff --git a/patches/server/Add-hand-to-bucket-events.patch b/patches/server/Add-hand-to-bucket-events.patch new file mode 100644 index 0000000000..3e29e8b866 --- /dev/null +++ b/patches/server/Add-hand-to-bucket-events.patch @@ -0,0 +1,196 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); + } + +- public BlockPos getSharedSpawnPos() { +- BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); +- +- if (!this.getWorldBorder().isWithinBounds(blockposition)) { +- blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); +- } +- +- return blockposition; +- } ++ // Paper - moved up to Level ++ //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 getSharedSpawnAngle() { + return this.levelData.getSpawnAngle(); +diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java +@@ -0,0 +0,0 @@ public class Cow extends Animal { + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { + // CraftBukkit start - Got milk? +- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); ++ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand + + if (event.isCancelled()) { + return InteractionResult.PASS; +diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java ++++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java +@@ -0,0 +0,0 @@ public class Goat extends Animal { + + if (itemstack.is(Items.BUCKET) && !this.isBaby()) { + // CraftBukkit start - Got milk? +- org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET); ++ org.bukkit.event.player.PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level, player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand); // Paper - add enumHand + + if (event.isCancelled()) { + return InteractionResult.PASS; +diff --git a/src/main/java/net/minecraft/world/item/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/BucketItem.java ++++ b/src/main/java/net/minecraft/world/item/BucketItem.java +@@ -0,0 +0,0 @@ public class BucketItem extends Item implements DispensibleContainerItem { + BucketPickup ifluidsource = (BucketPickup) iblockdata.getBlock(); + // CraftBukkit start + ItemStack dummyFluid = ifluidsource.pickupBlock(DummyGeneratorAccess.INSTANCE, blockposition, iblockdata); +- PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem()); ++ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand); // Paper - add enumhand + + if (event.isCancelled()) { + ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) +@@ -0,0 +0,0 @@ public class BucketItem extends Item implements DispensibleContainerItem { + iblockdata = world.getBlockState(blockposition); + BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1; + +- if (this.a(user, world, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack)) { // CraftBukkit ++ if (this.emptyContents(user, world, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit // Paper - add enumhand + this.checkExtraContent(user, world, itemstack, blockposition2); + if (user instanceof ServerPlayer) { + CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack); +@@ -0,0 +0,0 @@ public class BucketItem extends Item implements DispensibleContainerItem { + + @Override + public boolean emptyContents(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult hitResult) { +- return this.a(player, world, pos, hitResult, null, null, null); ++ // Paper start - add enumHand ++ return emptyContents(player, world, pos, hitResult, null, null, null, null); + } + +- public boolean a(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack) { ++ public boolean emptyContents(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) { ++ // Paper end + // CraftBukkit end + if (!(this.content instanceof FlowingFluid)) { + return false; +@@ -0,0 +0,0 @@ public class BucketItem extends Item implements DispensibleContainerItem { + + // CraftBukkit start + if (flag1 && entityhuman != null) { +- PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack); ++ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand); // Paper - add enumhand + if (event.isCancelled()) { + ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity + ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541 +@@ -0,0 +0,0 @@ public class BucketItem extends Item implements DispensibleContainerItem { + } + // CraftBukkit end + if (!flag1) { +- return movingobjectpositionblock != null && this.a(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack); // CraftBukkit ++ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit // Paper - add enumhand + } else if (world.dimensionType().ultraWarm() && this.content.is((Tag) FluidTags.WATER)) { + int i = blockposition.getX(); + int j = blockposition.getY(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return true; + } + // Paper end ++ // Paper start - moved up from ServerLevel ++ public BlockPos getSharedSpawnPos() { ++ BlockPos blockposition = new BlockPos(this.levelData.getXSpawn(), this.levelData.getYSpawn(), this.levelData.getZSpawn()); ++ ++ if (!this.getWorldBorder().isWithinBounds(blockposition)) { ++ blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, new BlockPos(this.getWorldBorder().getCenterX(), 0.0D, this.getWorldBorder().getCenterZ())); ++ } ++ ++ return blockposition; ++ } ++ // Paper end + @Override + public boolean isClientSide() { + return this.isClientSide; +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + void run(Mob entity, ChunkAccess chunk); + } + } ++ +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(ServerLevel world, Player player, int x, int z) { ++ private static boolean canBuild(Level world, Player player, int x, int z) { + int spawnSize = Bukkit.getServer().getSpawnRadius(); + + if (world.dimension() != Level.OVERWORLD) return true; +@@ -0,0 +0,0 @@ public class CraftEventFactory { + } + + private static PlayerEvent getPlayerBucketEvent(boolean isFilling, ServerLevel world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction 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(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, InteractionHand enumHand) { ++ return (PlayerBucketEmptyEvent) getPlayerBucketEvent(false, world, who, changed, clicked, clickedFace, itemstack, Items.BUCKET, enumHand); ++ } ++ ++ public static PlayerBucketFillEvent callPlayerBucketFillEvent(Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemInHand, net.minecraft.world.item.Item bucket, InteractionHand enumHand) { ++ return (PlayerBucketFillEvent) getPlayerBucketEvent(true, world, who, clicked, changed, clickedFace, itemInHand, bucket, enumHand); ++ } ++ ++ private static PlayerEvent getPlayerBucketEvent(boolean isFilling, Level world, net.minecraft.world.entity.player.Player who, BlockPos changed, BlockPos clicked, Direction clickedFace, ItemStack itemstack, net.minecraft.world.item.Item item, InteractionHand 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 == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketFillEvent) event).setCancelled(!CraftEventFactory.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 == InteractionHand.OFF_HAND ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); // Paper - add enumHand + ((PlayerBucketEmptyEvent) event).setCancelled(!CraftEventFactory.canBuild(world, player, changed.getX(), changed.getZ())); + } + diff --git a/patches/server/Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/server/Add-handshake-event-to-allow-plugins-to-handle-clien.patch new file mode 100644 index 0000000000..32d3ca2b1b --- /dev/null +++ b/patches/server/Add-handshake-event-to-allow-plugins-to-handle-clien.patch @@ -0,0 +1,48 @@ +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/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + this.connection.disconnect(chatmessage); + } else { + this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection)); ++ // 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.connection.address; ++ 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(packet.hostName, hostnameOfRemote, !proxyLogicEnabled); ++ if (event.callEvent()) { ++ // If we've failed somehow, let the client know so and go no further. ++ if (event.isFailed()) { ++ TranslatableComponent chatmessage = new TranslatableComponent(event.getFailMessage()); ++ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); ++ this.connection.disconnect(chatmessage); ++ return; ++ } ++ ++ if (event.getServerHostname() != null) packet.hostName = event.getServerHostname(); ++ if (event.getSocketAddressHostname() != null) this.connection.address = new java.net.InetSocketAddress(event.getSocketAddressHostname(), socketAddress instanceof java.net.InetSocketAddress ? ((java.net.InetSocketAddress) socketAddress).getPort() : 0); ++ this.connection.spoofedUUID = event.getUniqueId(); ++ this.connection.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 = packet.hostName.split("\00"); + if ( ( split.length == 3 || split.length == 4 ) && ( ServerHandshakePacketListenerImpl.HOST_PATTERN.matcher( split[1] ).matches() ) ) { + packet.hostName = split[0]; diff --git a/Spigot-Server-Patches/Add-ignore-discounts-API.patch b/patches/server/Add-ignore-discounts-API.patch similarity index 56% rename from Spigot-Server-Patches/Add-ignore-discounts-API.patch rename to patches/server/Add-ignore-discounts-API.patch index 728df9b6ac..cdfe19c508 100644 --- a/Spigot-Server-Patches/Add-ignore-discounts-API.patch +++ b/patches/server/Add-ignore-discounts-API.patch @@ -4,31 +4,31 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.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 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler while (iterator.hasNext()) { - MerchantRecipe merchantrecipe = (MerchantRecipe) iterator.next(); + MerchantOffer merchantrecipe = (MerchantOffer) 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 + int bonus = -Mth.floor((float) i * merchantrecipe.getPriceMultiplier()); +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler while (iterator1.hasNext()) { - MerchantRecipe merchantrecipe1 = (MerchantRecipe) iterator1.next(); + MerchantOffer merchantrecipe1 = (MerchantOffer) 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()); + int k = (int) Math.floor(d0 * (double) merchantrecipe1.getBaseCostA().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 +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.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 { +--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +@@ -0,0 +0,0 @@ public class MerchantOffer { private int demand; public float priceMultiplier; public int xp; @@ -36,54 +36,54 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start private CraftMerchantRecipe bukkitHandle; -@@ -0,0 +0,0 @@ public class MerchantRecipe { +@@ -0,0 +0,0 @@ public class MerchantOffer { } - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { + public MerchantOffer(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int uses, int maxUses, int experience, float priceMultiplier, CraftMerchantRecipe bukkit) { - this(itemstack, itemstack1, itemstack2, uses, maxUses, experience, priceMultiplier); + // 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); ++ public MerchantOffer(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, 0, ignoreDiscounts); + // Paper end this.bukkitHandle = bukkit; } // CraftBukkit end -@@ -0,0 +0,0 @@ public class MerchantRecipe { +@@ -0,0 +0,0 @@ public class MerchantOffer { - this.specialPrice = nbttagcompound.getInt("specialPrice"); - this.demand = nbttagcompound.getInt("demand"); -+ this.ignoreDiscounts = nbttagcompound.getBoolean("Paper.IgnoreDiscounts"); // Paper + this.specialPriceDiff = nbt.getInt("specialPrice"); + this.demand = nbt.getInt("demand"); ++ this.ignoreDiscounts = nbt.getBoolean("Paper.IgnoreDiscounts"); // Paper } - public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, int i, int j, float f) { -@@ -0,0 +0,0 @@ public class MerchantRecipe { + public MerchantOffer(ItemStack buyItem, ItemStack sellItem, int maxUses, int merchantExperience, float priceMultiplier) { +@@ -0,0 +0,0 @@ public class MerchantOffer { } - 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); + public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier) { +- this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 0); + // Paper start - add ignoreDiscounts param -+ this(itemstack, itemstack1, itemstack2, i, j, k, f, false); ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 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 MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, boolean ignoreDiscounts) { ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, 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 MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus) { ++ this(firstBuyItem, secondBuyItem, sellItem, uses, maxUses, merchantExperience, priceMultiplier, demandBonus, false); + } -+ public MerchantRecipe(ItemStack itemstack, ItemStack itemstack1, ItemStack itemstack2, int i, int j, int k, float f, int l, boolean ignoreDiscounts) { ++ public MerchantOffer(ItemStack firstBuyItem, ItemStack secondBuyItem, ItemStack sellItem, int uses, int maxUses, int merchantExperience, float priceMultiplier, int demandBonus, 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 + this.baseCostA = firstBuyItem; +@@ -0,0 +0,0 @@ public class MerchantOffer { + nbttagcompound.putFloat("priceMultiplier", this.priceMultiplier); + nbttagcompound.putInt("specialPrice", this.specialPriceDiff); + nbttagcompound.putInt("demand", this.demand); ++ nbttagcompound.putBoolean("Paper.IgnoreDiscounts", this.ignoreDiscounts); // Paper return nbttagcompound; } @@ -102,9 +102,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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, + this.handle = new net.minecraft.world.item.trading.MerchantOffer( + net.minecraft.world.item.ItemStack.EMPTY, + net.minecraft.world.item.ItemStack.EMPTY, @@ -0,0 +0,0 @@ public class CraftMerchantRecipe extends MerchantRecipe { maxUses, experience, @@ -129,7 +129,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + - public net.minecraft.world.item.trading.MerchantRecipe toMinecraft() { + public net.minecraft.world.item.trading.MerchantOffer toMinecraft() { List ingredients = getIngredients(); Preconditions.checkState(!ingredients.isEmpty(), "No offered ingredients"); @@ -0,0 +0,0 @@ public class CraftMerchantRecipe extends MerchantRecipe { diff --git a/Spigot-Server-Patches/Add-method-to-open-already-placed-sign.patch b/patches/server/Add-method-to-open-already-placed-sign.patch similarity index 69% rename from Spigot-Server-Patches/Add-method-to-open-already-placed-sign.patch rename to patches/server/Add-method-to-open-already-placed-sign.patch index 98dfbce4ef..30d2d47b6b 100644 --- a/Spigot-Server-Patches/Add-method-to-open-already-placed-sign.patch +++ b/patches/server/Add-method-to-open-already-placed-sign.patch @@ -8,14 +8,6 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b 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 { } } @@ -25,12 +17,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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(); ++ net.minecraft.world.level.block.entity.SignBlockEntity teSign = craftSign.getTileEntity(); + // Make sign editable temporarily, will be set back to false in PlayerConnection later + teSign.isEditable = true; -+ getHandle().openSign(teSign); ++ this.getHandle().openTextEdit(teSign); + } + // Paper end @Override public boolean dropItem(boolean dropAll) { - return getHandle().dropItem(dropAll); + return this.getHandle().drop(dropAll); diff --git a/Spigot-Server-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server/Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 89% rename from Spigot-Server-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to patches/server/Add-methods-for-working-with-arrows-stuck-in-living-.patch index c0fd3c8a40..7a2edb4154 100644 --- a/Spigot-Server-Patches/Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ b/patches/server/Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + this.getHandle().persistentInvisibility = invisible; + this.getHandle().setSharedFlag(5, invisible); } + + // Paper start diff --git a/Spigot-Server-Patches/Add-missing-strikeLighting-call-to-World-spigot-stri.patch b/patches/server/Add-missing-strikeLighting-call-to-World-spigot-stri.patch similarity index 87% rename from Spigot-Server-Patches/Add-missing-strikeLighting-call-to-World-spigot-stri.patch rename to patches/server/Add-missing-strikeLighting-call-to-World-spigot-stri.patch index 05f3a8899b..0b87484b5d 100644 --- a/Spigot-Server-Patches/Add-missing-strikeLighting-call-to-World-spigot-stri.patch +++ b/patches/server/Add-missing-strikeLighting-call-to-World-spigot-stri.patch @@ -10,8 +10,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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.moveTo( loc.getX(), loc.getY(), loc.getZ() ); + lightning.visualOnly = true; lightning.isSilent = isSilent; + world.strikeLightning( lightning ); return (LightningStrike) lightning.getBukkitEntity(); diff --git a/Spigot-Server-Patches/Add-moon-phase-API.patch b/patches/server/Add-moon-phase-API.patch similarity index 95% rename from Spigot-Server-Patches/Add-moon-phase-API.patch rename to patches/server/Add-moon-phase-API.patch index 3ff89190eb..46bb9a53d6 100644 --- a/Spigot-Server-Patches/Add-moon-phase-API.patch +++ b/patches/server/Add-moon-phase-API.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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(); + return world.players().size(); } + + @Override diff --git a/patches/server/Add-more-Evoker-API.patch b/patches/server/Add-more-Evoker-API.patch new file mode 100644 index 0000000000..0b853fe9ad --- /dev/null +++ b/patches/server/Add-more-Evoker-API.patch @@ -0,0 +1,35 @@ +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/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.Sheep; + import net.minecraft.world.entity.monster.SpellcasterIllager; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.entity.EntityType; +@@ -0,0 +0,0 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { + public void setCurrentSpell(Evoker.Spell spell) { + this.getHandle().setIsCastingSpell(spell == null ? SpellcasterIllager.IllagerSpell.NONE : SpellcasterIllager.IllagerSpell.byId(spell.ordinal())); + } ++ ++ // Paper start ++ @Override ++ public org.bukkit.entity.Sheep getWololoTarget() { ++ Sheep 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/patches/server/Add-more-WanderingTrader-API.patch similarity index 50% rename from Spigot-Server-Patches/Add-more-WanderingTrader-API.patch rename to patches/server/Add-more-WanderingTrader-API.patch index df08a10a91..3f9ee2352e 100644 --- a/Spigot-Server-Patches/Add-more-WanderingTrader-API.patch +++ b/patches/server/Add-more-WanderingTrader-API.patch @@ -4,41 +4,41 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.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 { +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -0,0 +0,0 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill @Nullable - private BlockPosition bp; + private BlockPos wanderTarget; 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 + public WanderingTrader(EntityType type, Level world) { + super(type, world); +@@ -0,0 +0,0 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(0, new UseItemGoal<>(this, PotionUtils.setPotion(new ItemStack(Items.POTION), Potions.INVISIBILITY), SoundEvents.WANDERING_TRADER_DISAPPEARED, (entityvillagertrader) -> { +- return this.level.isNight() && !entityvillagertrader.isInvisible(); ++ return this.canDrinkPotion && this.level.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.addGoal(0, new UseItemGoal<>(this, new ItemStack(Items.MILK_BUCKET), SoundEvents.WANDERING_TRADER_REAPPEARED, (entityvillagertrader) -> { +- return this.level.isDay() && entityvillagertrader.isInvisible(); ++ return canDrinkMilk && this.level.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)); + this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this)); + this.goalSelector.addGoal(1, new AvoidEntityGoal<>(this, Zombie.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); + this.getHandle().setDespawnDelay(despawnDelay); } + + // Paper start - Add more WanderingTrader API diff --git a/Spigot-Server-Patches/Add-more-Witch-API.patch b/patches/server/Add-more-Witch-API.patch similarity index 54% rename from Spigot-Server-Patches/Add-more-Witch-API.patch rename to patches/server/Add-more-Witch-API.patch index 57c5028e01..652ad2934c 100644 --- a/Spigot-Server-Patches/Add-more-Witch-API.patch +++ b/patches/server/Add-more-Witch-API.patch @@ -4,52 +4,27 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.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 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.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 { +@@ -0,0 +0,0 @@ public class Witch extends Raider implements RangedAttackMob { } if (potionregistry != null) { - // Paper start - ItemStack potion = PotionUtil.a(new ItemStack(Items.POTION), potionregistry); + ItemStack potion = PotionUtils.setPotion(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)); +- this.setItemSlot(EquipmentSlot.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)); @@ -66,49 +41,49 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +// attributemodifiable.removeModifier(EntityWitch.bo); +// attributemodifiable.b(EntityWitch.bo); // Paper end -- this.bq = this.getItemInMainHand().k(); -- this.v(true); +- this.usingTime = this.getMainHandItem().getUseDuration(); +- this.setUsingItem(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); +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); - } - -- AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); - -- attributemodifiable.removeModifier(EntityWitch.bo); -- attributemodifiable.b(EntityWitch.bo); +- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); +- attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); } } -@@ -0,0 +0,0 @@ public class EntityWitch extends EntityRaider implements IRangedEntity { - super.movementTick(); +@@ -0,0 +0,0 @@ public class Witch extends Raider implements RangedAttackMob { + super.aiStep(); } + // 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)); ++ this.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); + // Paper end -+ this.bq = this.getItemInMainHand().k(); -+ this.v(true); ++ this.usingTime = this.getMainHandItem().getUseDuration(); ++ this.setUsingItem(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); ++ this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); + } + -+ AttributeModifiable attributemodifiable = this.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + -+ attributemodifiable.removeModifier(EntityWitch.bo); -+ attributemodifiable.b(EntityWitch.bo); ++ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); ++ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); + } + // Paper end + @Override - public SoundEffect eL() { - return SoundEffects.ENTITY_WITCH_CELEBRATE; + public SoundEvent getCelebrateSound() { + return SoundEvents.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; +@@ -0,0 +0,0 @@ package org.bukkit.craftbukkit.entity; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.EntityType; import org.bukkit.entity.Witch; @@ -120,8 +95,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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) { + public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { @@ -0,0 +0,0 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. public EntityType getType() { return EntityType.WITCH; @@ -133,16 +108,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + public int getPotionUseTimeLeft() { -+ return getHandle().getPotionUseTimeLeft(); ++ return getHandle().usingTime; + } + + @Override + public void setPotionUseTimeLeft(int ticks) { -+ getHandle().setPotionUseTimeLeft(ticks); ++ getHandle().usingTime = ticks; + } + + public ItemStack getDrinkingPotion() { -+ return CraftItemStack.asCraftMirror(getHandle().getItemInMainHand()); ++ return CraftItemStack.asCraftMirror(getHandle().getMainHandItem()); + } + + public void setDrinkingPotion(ItemStack potion) { diff --git a/Spigot-Server-Patches/Add-more-Zombie-API.patch b/patches/server/Add-more-Zombie-API.patch similarity index 51% rename from Spigot-Server-Patches/Add-more-Zombie-API.patch rename to patches/server/Add-more-Zombie-API.patch index 189522f35d..d8f3c6c419 100644 --- a/Spigot-Server-Patches/Add-more-Zombie-API.patch +++ b/patches/server/Add-more-Zombie-API.patch @@ -4,70 +4,68 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.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; +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + private int inWaterTime; + public int conversionTime; 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(); + public Zombie(EntityType type, Level world) { + super(type, world); +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + super.aiStep(); } + // Paper start + public void stopDrowning() { -+ this.drownedConversionTime = -1; -+ this.getDataWatcher().set(EntityZombie.DROWN_CONVERTING, false); ++ this.conversionTime = -1; ++ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, false); + } + // Paper end - public void startDrownedConversion(int i) { + public void startUnderWaterConversion(int ticksUntilWaterConversion) { this.lastTick = MinecraftServer.currentTick; // CraftBukkit - this.drownedConversionTime = i; -@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { - + this.conversionTime = ticksUntilWaterConversion; +@@ -0,0 +0,0 @@ public class Zombie extends Monster { } -+ public boolean shouldBurnInDay() { return T_(); } // Paper - OBFHELPER - protected boolean T_() { + public boolean isSunSensitive() { - 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 + public boolean hurt(DamageSource source, float amount) { + if (!super.hurt(source, amount)) { +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + nbt.putBoolean("CanBreakDoors", this.canBreakDoors()); + nbt.putInt("InWaterTime", this.isInWater() ? this.inWaterTime : -1); + nbt.putInt("DrownedConversionTime", this.isUnderWaterConverting() ? this.conversionTime : -1); ++ nbt.putBoolean("Paper.ShouldBurnInDay", this.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")); +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + if (nbt.contains("DrownedConversionTime", 99) && nbt.getInt("DrownedConversionTime") > -1) { + this.startUnderWaterConversion(nbt.getInt("DrownedConversionTime")); } -- + // Paper start -+ if (nbttagcompound.hasKey("Paper.ShouldBurnInDay")) { -+ shouldBurnInDay = nbttagcompound.getBoolean("Paper.ShouldBurnInDay"); ++ if (nbt.contains("Paper.ShouldBurnInDay")) { ++ this.shouldBurnInDay = nbt.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 @@ -79,12 +77,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + @Override + public boolean isDrowning() { -+ return getHandle().isDrownConverting(); ++ return getHandle().isUnderWaterConverting(); + } + + @Override + public void startDrowning(int drownedConversionTime) { -+ getHandle().startDrownedConversion(drownedConversionTime); ++ getHandle().startUnderWaterConversion(drownedConversionTime); + } + + @Override @@ -94,7 +92,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public boolean shouldBurnInDay() { -+ return getHandle().shouldBurnInDay(); ++ return getHandle().isSunSensitive(); + } + + @Override diff --git a/patches/server/Add-more-line-of-sight-methods.patch b/patches/server/Add-more-line-of-sight-methods.patch new file mode 100644 index 0000000000..416e08904a --- /dev/null +++ b/patches/server/Add-more-line-of-sight-methods.patch @@ -0,0 +1,74 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); + Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); + ++ // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists + return vec3d1.distanceTo(vec3d) > 128.0D ? false : this.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() == HitResult.Type.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; ++ Vec3 vec3d = new Vec3(from.getX(), from.getY(), from.getZ()); ++ Vec3 vec3d1 = new Vec3(to.getX(), to.getY(), to.getZ()); ++ if (vec3d1.distanceTo(vec3d) > 128.0D) return false; ++ ++ return this.getHandle().clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, null)).getType() == HitResult.Type.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 @@ import net.minecraft.world.entity.projectile.ThrownEgg; + import net.minecraft.world.entity.projectile.ThrownEnderpearl; + import net.minecraft.world.entity.projectile.ThrownExperienceBottle; + import net.minecraft.world.entity.projectile.ThrownTrident; ++import net.minecraft.world.level.ClipContext; ++import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; + 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 { + return this.getHandle().hasLineOfSight(((CraftEntity) other).getHandle()); + } + ++ // Paper start ++ @Override ++ public boolean hasLineOfSight(Location loc) { ++ if (this.getHandle().level != ((CraftWorld) loc.getWorld()).getHandle()) return false; ++ Vec3 vec3d = new Vec3(this.getHandle().getX(), this.getHandle().getEyeY(), this.getHandle().getZ()); ++ Vec3 vec3d1 = new Vec3(loc.getX(), loc.getY(), loc.getZ()); ++ if (vec3d1.distanceTo(vec3d) > 128.0D) return false; ++ ++ return this.getHandle().level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this.getHandle())).getType() == HitResult.Type.MISS; ++ } ++ // Paper end ++ + @Override + public boolean getRemoveWhenFarAway() { + return this.getHandle() instanceof Mob && !((Mob) this.getHandle()).persistenceRequired; diff --git a/Spigot-Server-Patches/Add-option-for-console-having-all-permissions.patch b/patches/server/Add-option-for-console-having-all-permissions.patch similarity index 81% rename from Spigot-Server-Patches/Add-option-for-console-having-all-permissions.patch rename to patches/server/Add-option-for-console-having-all-permissions.patch index 50b1dad655..04bfb9f787 100644 --- a/Spigot-Server-Patches/Add-option-for-console-having-all-permissions.patch +++ b/patches/server/Add-option-for-console-having-all-permissions.patch @@ -18,19 +18,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } -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 diff --git a/Spigot-Server-Patches/Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 63% rename from Spigot-Server-Patches/Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch index 68e6e34cd7..b0277b9302 100644 --- a/Spigot-Server-Patches/Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ b/patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -20,16 +20,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.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); +--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java ++++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java +@@ -0,0 +0,0 @@ public class IronGolem extends AbstractGolem implements NeutralMob { + BlockPos blockposition1 = blockposition.below(); + BlockState iblockdata = world.getBlockState(blockposition1); -- if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this)) { -+ if (!iblockdata.a((IBlockAccess) iworldreader, blockposition1, (Entity) this) && !world.paperConfig.ironGolemsCanSpawnInAir) { // Paper +- if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this)) { ++ if (!iblockdata.entityCanStandOn((BlockGetter) world, blockposition1, (Entity) this) && !level.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/patches/server/Add-option-to-disable-pillager-patrols.patch similarity index 63% rename from Spigot-Server-Patches/Add-option-to-disable-pillager-patrols.patch rename to patches/server/Add-option-to-disable-pillager-patrols.patch index 7eefb50579..8b10a00df6 100644 --- a/Spigot-Server-Patches/Add-option-to-disable-pillager-patrols.patch +++ b/patches/server/Add-option-to-disable-pillager-patrols.patch @@ -18,15 +18,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.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 { +--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -0,0 +0,0 @@ public class PatrolSpawner implements CustomSpawner { @Override - public int a(WorldServer worldserver, boolean flag, boolean flag1) { -+ if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper - if (!flag) { + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { ++ if (world.paperConfig.disablePillagerPatrols) return 0; // Paper + if (!spawnMonsters) { return 0; - } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { + } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { diff --git a/Spigot-Server-Patches/Add-option-to-fix-items-merging-through-walls.patch b/patches/server/Add-option-to-fix-items-merging-through-walls.patch similarity index 54% rename from Spigot-Server-Patches/Add-option-to-fix-items-merging-through-walls.patch rename to patches/server/Add-option-to-fix-items-merging-through-walls.patch index 5886e3653f..4d659ec01e 100644 --- a/Spigot-Server-Patches/Add-option-to-fix-items-merging-through-walls.patch +++ b/patches/server/Add-option-to-fix-items-merging-through-walls.patch @@ -18,22 +18,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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()) { +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { + ItemEntity entityitem = (ItemEntity) iterator.next(); + + if (entityitem.isMergable()) { + // 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; ++ if (this.level.paperConfig.fixItemsMergingThroughWalls) { ++ net.minecraft.world.level.ClipContext rayTrace = new net.minecraft.world.level.ClipContext(this.position(), entityitem.position(), ++ net.minecraft.world.level.ClipContext.Block.COLLIDER, net.minecraft.world.level.ClipContext.Fluid.NONE, this); ++ net.minecraft.world.phys.BlockHitResult rayTraceResult = level.clip(rayTrace); ++ if (rayTraceResult.getType() == net.minecraft.world.phys.HitResult.Type.BLOCK) continue; + } + // Paper End - this.a(entityitem); - if (this.dead) { + this.tryToMerge(entityitem); + if (this.isRemoved()) { break; diff --git a/Spigot-Server-Patches/Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server/Add-option-to-make-parrots-stay-on-shoulders-despite.patch similarity index 52% rename from Spigot-Server-Patches/Add-option-to-make-parrots-stay-on-shoulders-despite.patch rename to patches/server/Add-option-to-make-parrots-stay-on-shoulders-despite.patch index bdf6f0c58e..f720fb5f0b 100644 --- a/Spigot-Server-Patches/Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ b/patches/server/Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -25,34 +25,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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()) { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + switch (packet.getAction()) { case PRESS_SHIFT_KEY: - this.player.setSneaking(true); + this.player.setShiftKeyDown(true); + -+ // Paper start - Hang on! -+ if (this.player.world.paperConfig.parrotsHangOnBetter) { -+ this.player.releaseShoulderEntities(); -+ } -+ // Paper end ++ // Paper start - Hang on! ++ if (this.player.level.paperConfig.parrotsHangOnBetter) { ++ this.player.removeEntitiesOnShoulder(); ++ } ++ // 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 + this.player.setShiftKeyDown(false); +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.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! +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + this.playShoulderEntityAmbientSound(this.getShoulderEntityLeft()); + this.playShoulderEntityAmbientSound(this.getShoulderEntityRight()); + if (!this.level.isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.flying || this.isSleeping() || this.isInPowderSnow) { +- this.removeEntitiesOnShoulder(); ++ if (!this.level.paperConfig.parrotsHangOnBetter) this.removeEntitiesOnShoulder(); // Paper - Hang on! } } diff --git a/Spigot-Server-Patches/Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 53% rename from Spigot-Server-Patches/Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch index 26a44dc336..11e9704dd0 100644 --- a/Spigot-Server-Patches/Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -9,20 +9,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + } - } ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n 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 @@ -30,42 +32,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected int numCollisions = 0; // Paper public void inactiveTick() { } // Spigot end -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n if (spawnedViaMobSpawner) { - nbttagcompound.setBoolean("Paper.FromMobSpawner", true); + nbt.putBoolean("Paper.FromMobSpawner", true); } + if (fromNetherPortal) { -+ nbttagcompound.setBoolean("Paper.FromNetherPortal", true); ++ nbt.putBoolean("Paper.FromNetherPortal", true); + } // Paper end - return nbttagcompound; + return nbt; } catch (Throwable throwable) { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - 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"); + spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ fromNetherPortal = nbt.getBoolean("Paper.FromNetherPortal"); + if (nbt.contains("Paper.SpawnReason")) { + String spawnReasonName = nbt.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 +diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.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 { +--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -0,0 +0,0 @@ public class NetherPortalBlock extends Block { if (entity != null) { - entity.resetPortalCooldown(); + entity.setPortalCooldown(); + entity.fromNetherPortal = true; // Paper -+ if (worldserver.paperConfig.nerfNetherPortalPigmen) ((EntityInsentient) entity).aware = false; // Paper ++ if (world.paperConfig.nerfNetherPortalPigmen) ((net.minecraft.world.entity.Mob) entity).aware = false; // Paper } } } diff --git a/patches/server/Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server/Add-option-to-prevent-players-from-moving-into-unloa.patch new file mode 100644 index 0000000000..8f6ba0bf62 --- /dev/null +++ b/patches/server/Add-option-to-prevent-players-from-moving-into-unloa.patch @@ -0,0 +1,64 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + speed *= 2f; // TODO: Get the speed of the vehicle instead of the player + ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && worldserver.getChunkIfLoadedImmediately((int) Math.floor(packet.getX()) >> 4, (int) Math.floor(packet.getZ()) >> 4) == null) { ++ this.connection.send(new ClientboundMoveVehiclePacket(entity)); ++ return; ++ } ++ // Paper end ++ + if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) { + // CraftBukkit end + ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getName().getString(), this.player.getName().getString(), d6, d7, d8); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + float prevYaw = this.player.getYRot(); + float prevPitch = this.player.getXRot(); + // CraftBukkit end +- double d3 = this.player.getX(); ++ double d3 = this.player.getX(); final double toX = d3; // Paper - OBFHELPER + double d4 = this.player.getY(); +- double d5 = this.player.getZ(); ++ double d5 = this.player.getZ(); final double toZ = d5; // Paper - OBFHELPER + double d6 = this.player.getY(); + double d7 = d0 - this.firstGoodX; + double d8 = d1 - this.firstGoodY; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } else { + speed = this.player.getAbilities().walkingSpeed * 10f; + } ++ // Paper start - Prevent moving into unloaded chunks ++ if (player.level.paperConfig.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.hasChunk((int) Math.floor(toX) >> 4, (int) Math.floor(toZ) >> 4)) { ++ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet(), true); ++ return; ++ } ++ // Paper end + + if (!this.player.isChangingDimension() && (!this.player.getLevel().getGameRules().getBoolean(GameRules.RULE_DISABLE_ELYTRA_MOVEMENT_CHECK) || !this.player.isFallFlying())) { + float f2 = this.player.isFallFlying() ? 300.0F : 100.0F; diff --git a/patches/server/Add-permission-for-command-blocks.patch b/patches/server/Add-permission-for-command-blocks.patch new file mode 100644 index 0000000000..be6324bc19 --- /dev/null +++ b/patches/server/Add-permission-for-command-blocks.patch @@ -0,0 +1,79 @@ +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/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + BlockEntity tileentity = this.level.getBlockEntity(pos); + Block block = iblockdata.getBlock(); + +- if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) { ++ if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks() && !(block instanceof net.minecraft.world.level.block.CommandBlock && (this.player.isCreative() && this.player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + this.level.sendBlockUpdated(pos, iblockdata, iblockdata, 3); + return false; + } else if (this.player.blockActionRestricted((Level) this.level, pos, this.gameModeForPlayer)) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); +- } else if (!this.player.canUseGameMasterBlocks()) { ++ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); + } else { + BaseCommandBlock commandblocklistenerabstract = null; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (!this.server.isCommandBlockEnabled()) { + this.player.sendMessage(new TranslatableComponent("advMode.notEnabled"), Util.NIL_UUID); +- } else if (!this.player.canUseGameMasterBlocks()) { ++ } else if (!this.player.canUseGameMasterBlocks() && !this.player.isCreative() && !this.player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + this.player.sendMessage(new TranslatableComponent("advMode.notAllowed"), Util.NIL_UUID); + } else { + BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level); +diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +@@ -0,0 +0,0 @@ public abstract class BaseCommandBlock implements CommandSource { + } + + public InteractionResult usedBy(Player player) { +- if (!player.canUseGameMasterBlocks()) { ++ if (!player.canUseGameMasterBlocks() && !player.isCreative() && !player.getBukkitEntity().hasPermission("minecraft.commandblock")) { // Paper - command block permission + return InteractionResult.PASS; + } else { + if (player.getCommandSenderWorld().isClientSide) { +diff --git a/src/main/java/net/minecraft/world/level/block/CommandBlock.java b/src/main/java/net/minecraft/world/level/block/CommandBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/CommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CommandBlock.java +@@ -0,0 +0,0 @@ public class CommandBlock extends BaseEntityBlock implements GameMasterBlock { + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { + BlockEntity tileentity = world.getBlockEntity(pos); + +- if (tileentity instanceof CommandBlockEntity && player.canUseGameMasterBlocks()) { ++ if (tileentity instanceof CommandBlockEntity && (player.canUseGameMasterBlocks() || (player.isCreative() && player.getBukkitEntity().hasPermission("minecraft.commandblock")))) { // Paper - command block permission + player.openCommandBlock((CommandBlockEntity) tileentity); + return InteractionResult.sidedSuccess(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(CraftDefaultPermissions.ROOT + ".nbt.copy", "Gives the user the ability to copy NBT in creative", org.bukkit.permissions.PermissionDefault.TRUE, parent); + DefaultPermissions.registerPermission(CraftDefaultPermissions.ROOT + ".debugstick", "Gives the user the ability to use the debug stick in creative", org.bukkit.permissions.PermissionDefault.OP, parent); + DefaultPermissions.registerPermission(CraftDefaultPermissions.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(CraftDefaultPermissions.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/patches/server/Add-phantom-creative-and-insomniac-controls.patch b/patches/server/Add-phantom-creative-and-insomniac-controls.patch new file mode 100644 index 0000000000..5a435e25ac --- /dev/null +++ b/patches/server/Add-phantom-creative-and-insomniac-controls.patch @@ -0,0 +1,61 @@ +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 { + 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); ++ } ++ + public int noTickViewDistance; + private void viewDistance() { + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -0,0 +0,0 @@ public final class EntitySelector { + public static final Predicate NO_SPECTATORS = (entity) -> { + return !entity.isSpectator(); + }; ++ public static Predicate isInsomniac = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper + + private EntitySelector() {} + // Paper start +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { + Player entityhuman = (Player) iterator.next(); + + if (Phantom.this.canAttack((LivingEntity) entityhuman, TargetingConditions.DEFAULT)) { ++ if (!level.paperConfig.phantomOnlyAttackInsomniacs || EntitySelector.isInsomniac.test(entityhuman)) // Paper + Phantom.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/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +@@ -0,0 +0,0 @@ public class PhantomSpawner implements CustomSpawner { + while (iterator.hasNext()) { + Player entityhuman = (Player) iterator.next(); + +- if (!entityhuman.isSpectator()) { ++ if (!entityhuman.isSpectator() && (!world.paperConfig.phantomIgnoreCreative || !entityhuman.isCreative())) { // Paper + BlockPos blockposition = entityhuman.blockPosition(); + + if (!world.dimensionType().hasSkyLight() || blockposition.getY() >= world.getSeaLevel() && world.canSeeSky(blockposition)) { diff --git a/Spigot-Server-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/server/Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 85% rename from Spigot-Server-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/server/Add-playPickupItemAnimation-to-LivingEntity.patch index 3c35084a97..e9c74d32a0 100644 --- a/Spigot-Server-Patches/Add-playPickupItemAnimation-to-LivingEntity.patch +++ b/patches/server/Add-playPickupItemAnimation-to-LivingEntity.patch @@ -9,13 +9,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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(); + ((Mob) getHandle()).getJumpControl().jump(); } } + + @Override + public void playPickupItemAnimation(org.bukkit.entity.Item item, int quantity) { -+ getHandle().receive(((CraftItem) item).getHandle(), quantity); ++ getHandle().take(((CraftItem) item).getHandle(), quantity); + } // Paper end } diff --git a/Spigot-Server-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/server/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 52% rename from Spigot-Server-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/server/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch index db20b2fb7b..247114d7a6 100644 --- a/Spigot-Server-Patches/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch +++ b/patches/server/Add-raw-address-to-AsyncPlayerPreLoginEvent.patch @@ -4,20 +4,20 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.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; +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // Paper end + String playerName = ServerLoginPacketListenerImpl.this.gameProfile.getName(); + java.net.InetAddress address = ((java.net.InetSocketAddress) ServerLoginPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(); ++ java.net.InetAddress rawAddress = ((java.net.InetSocketAddress) connection.getRawAddress()).getAddress(); // Paper + java.util.UUID uniqueId = ServerLoginPacketListenerImpl.this.gameProfile.getId(); + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; // Paper start - PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(getGameProfile()); + PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile); - AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, rawAddress, uniqueId, profile); server.getPluginManager().callEvent(asyncEvent); diff --git a/patches/server/Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server/Add-ray-tracing-methods-to-LivingEntity.patch new file mode 100644 index 0000000000..cf6261cfad --- /dev/null +++ b/patches/server/Add-ray-tracing-methods-to-LivingEntity.patch @@ -0,0 +1,90 @@ +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/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 { + return getNMSWorld(entity.getWorld()); + } + ++ public static ClipContext.Fluid getNMSFluidCollisionOption(com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ switch (fluidMode) { ++ case NEVER: ++ return ClipContext.Fluid.NONE; ++ case SOURCE_ONLY: ++ return ClipContext.Fluid.SOURCE_ONLY; ++ case ALWAYS: ++ return ClipContext.Fluid.ANY; ++ } ++ return null; ++ } ++ + public static BlockFace toBukkitBlockFace(Direction enumDirection) { + switch (enumDirection) { + case DOWN: +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + // Paper start ++ public HitResult getRayTrace(int maxDistance) { ++ return getRayTrace(maxDistance, ClipContext.Fluid.NONE); ++ } ++ ++ public HitResult getRayTrace(int maxDistance, ClipContext.Fluid fluidCollisionOption) { ++ if (maxDistance < 1 || maxDistance > 120) { ++ throw new IllegalArgumentException("maxDistance must be between 1-120"); ++ } ++ ++ Vec3 start = new Vec3(getX(), getY() + getEyeHeight(), getZ()); ++ org.bukkit.util.Vector dir = getBukkitEntity().getLocation().getDirection().multiply(maxDistance); ++ Vec3 end = new Vec3(start.x + dir.getX(), start.y + dir.getY(), start.z + dir.getZ()); ++ ClipContext raytrace = new ClipContext(start, end, ClipContext.Block.OUTLINE, fluidCollisionOption, this); ++ ++ return level.clip(raytrace); ++ } ++ + public int shieldBlockingDelay = level.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 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return blocks.get(0); + } + ++ // Paper start ++ @Override ++ public Block getTargetBlock(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()); ++ } ++ ++ @Override ++ public org.bukkit.block.BlockFace getTargetBlockFace(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection()); ++ } ++ ++ @Override ++ public com.destroystokyo.paper.block.TargetBlockInfo getTargetBlockInfo(int maxDistance, com.destroystokyo.paper.block.TargetBlockInfo.FluidMode fluidMode) { ++ net.minecraft.world.phys.HitResult rayTrace = getHandle().getRayTrace(maxDistance, net.minecraft.server.MCUtil.getNMSFluidCollisionOption(fluidMode)); ++ return !(rayTrace instanceof net.minecraft.world.phys.BlockHitResult) ? null : ++ new com.destroystokyo.paper.block.TargetBlockInfo(org.bukkit.craftbukkit.block.CraftBlock.at(getHandle().level, ((net.minecraft.world.phys.BlockHitResult)rayTrace).getBlockPos()), ++ net.minecraft.server.MCUtil.toBukkitBlockFace(((net.minecraft.world.phys.BlockHitResult)rayTrace).getDirection())); ++ } ++ // Paper end ++ + @Override + public List getLastTwoTargetBlocks(Set transparent, int maxDistance) { + return this.getLineOfSight(transparent, maxDistance, 2); diff --git a/patches/server/Add-recipe-to-cook-events.patch b/patches/server/Add-recipe-to-cook-events.patch new file mode 100644 index 0000000000..4585456c82 --- /dev/null +++ b/patches/server/Add-recipe-to-cook-events.patch @@ -0,0 +1,44 @@ +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/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result); ++ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result, (org.bukkit.inventory.CookingRecipe) irecipe.toBukkitRecipe()); // Paper + world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent); + + if (furnaceSmeltEvent.isCancelled()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -0,0 +0,0 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { + + if (campfire.cookingProgress[i] >= campfire.cookingTime[i]) { + SimpleContainer inventorysubcontainer = new SimpleContainer(new ItemStack[]{itemstack}); +- ItemStack itemstack1 = (ItemStack) world.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, world).map((recipecampfire) -> { ++ // Paper start ++ Optional recipe = world.getRecipeManager().getRecipeFor(RecipeType.CAMPFIRE_COOKING, inventorysubcontainer, world); ++ ItemStack itemstack1 = (ItemStack) recipe.map((recipecampfire) -> { ++ // Paper end + return recipecampfire.assemble(inventorysubcontainer); + }).orElse(itemstack); + +@@ -0,0 +0,0 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { + CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); + +- BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, pos), source, result); ++ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, pos), source, result, (org.bukkit.inventory.CookingRecipe) recipe.map(CampfireCookingRecipe::toBukkitRecipe).orElse(null)); // Paper + world.getCraftServer().getPluginManager().callEvent(blockCookEvent); + + if (blockCookEvent.isCancelled()) { diff --git a/Spigot-Server-Patches/Add-sendOpLevel-API.patch b/patches/server/Add-sendOpLevel-API.patch similarity index 57% rename from Spigot-Server-Patches/Add-sendOpLevel-API.patch rename to patches/server/Add-sendOpLevel-API.patch index fd9e335ef8..ed45760712 100644 --- a/Spigot-Server-Patches/Add-sendOpLevel-API.patch +++ b/patches/server/Add-sendOpLevel-API.patch @@ -11,22 +11,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class PlayerList { } - private void a(EntityPlayer entityplayer, int i) { + private void sendPlayerPermissionLevel(ServerPlayer player, int permissionLevel) { +- if (player.connection != null) { + // Paper start - add recalculatePermissions parameter -+ this.sendPlayerOperatorStatus(entityplayer, i, true); ++ this.sendPlayerOperatorStatus(player, permissionLevel, true); + } -+ public void sendPlayerOperatorStatus(EntityPlayer entityplayer, int i, boolean recalculatePermissions) { ++ public void sendPlayerOperatorStatus(ServerPlayer entityplayer, int i, boolean recalculatePermissions) { + // Paper end - if (entityplayer.playerConnection != null) { ++ if (entityplayer.connection != null) { byte b0; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityStatus(entityplayer, b0)); +- if (permissionLevel <= 0) { ++ if (i <= 0) { + b0 = 24; +- } else if (permissionLevel >= 4) { ++ } else if (i >= 4) { + b0 = 28; + } else { +- b0 = (byte) (24 + permissionLevel); ++ b0 = (byte) (24 + i); + } + +- player.connection.send(new ClientboundEntityEventPacket(player, b0)); ++ entityplayer.connection.send(new ClientboundEntityEventPacket(entityplayer, b0)); } +- player.getBukkitEntity().recalculatePermissions(); // CraftBukkit +- this.server.getCommands().sendCommands(player); + if (recalculatePermissions) { // Paper - entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit - this.server.getCommandDispatcher().a(entityplayer); ++ entityplayer.getBukkitEntity().recalculatePermissions(); // CraftBukkit ++ this.server.getCommands().sendCommands(entityplayer); + } // Paper } @@ -44,8 +58,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ this.getHandle().getServer().getPlayerList().sendPlayerOperatorStatus(this.getHandle(), level, false); + } // Paper end - // Spigot start + @Override diff --git a/Spigot-Server-Patches/Add-server-name-parameter.patch b/patches/server/Add-server-name-parameter.patch similarity index 100% rename from Spigot-Server-Patches/Add-server-name-parameter.patch rename to patches/server/Add-server-name-parameter.patch diff --git a/Spigot-Server-Patches/Add-setMaxPlayers-API.patch b/patches/server/Add-setMaxPlayers-API.patch similarity index 83% rename from Spigot-Server-Patches/Add-setMaxPlayers-API.patch rename to patches/server/Add-setMaxPlayers-API.patch index 4feada0071..9ab4824b66 100644 --- a/Spigot-Server-Patches/Add-setMaxPlayers-API.patch +++ b/patches/server/Add-setMaxPlayers-API.patch @@ -9,20 +9,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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; + public final PlayerDataStorage playerIo; + private boolean doWhiteList; + private final RegistryAccess.RegistryHolder registryHolder; - 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; + private boolean allowCheatsForAllPlayers; + private static final boolean ALLOW_LOGOUTIVATOR = false; 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(); + return this.playerList.getMaxPlayers(); } + // Paper start diff --git a/Spigot-Server-Patches/Add-setPlayerProfile-API-for-Skulls.patch b/patches/server/Add-setPlayerProfile-API-for-Skulls.patch similarity index 69% rename from Spigot-Server-Patches/Add-setPlayerProfile-API-for-Skulls.patch rename to patches/server/Add-setPlayerProfile-API-for-Skulls.patch index d38f2172eb..f0fbc0242a 100644 --- a/Spigot-Server-Patches/Add-setPlayerProfile-API-for-Skulls.patch +++ b/patches/server/Add-setPlayerProfile-API-for-Skulls.patch @@ -18,15 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +@@ -0,0 +0,0 @@ public class CraftSkull extends CraftBlockEntityState implemen } } @@ -37,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.profile = CraftPlayerProfile.asAuthlibCopy(profile); + } + -+ @Nullable ++ @javax.annotation.Nullable + @Override + public PlayerProfile getPlayerProfile() { + return profile != null ? CraftPlayerProfile.asBukkitCopy(profile) : null; @@ -51,10 +43,14 @@ diff --git a/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; +@@ -0,0 +0,0 @@ import com.google.common.collect.ImmutableMap.Builder; + import com.mojang.authlib.GameProfile; + import java.util.Map; + import java.util.UUID; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.NbtUtils; +-import net.minecraft.nbt.Tag; +-import net.minecraft.world.level.block.entity.SkullBlockEntity; +import com.destroystokyo.paper.profile.CraftPlayerProfile; +import com.destroystokyo.paper.profile.PlayerProfile; import org.bukkit.Bukkit; @@ -65,11 +61,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import org.bukkit.inventory.meta.SkullMeta; +import javax.annotation.Nullable; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtUtils; ++import net.minecraft.nbt.Tag; ++import net.minecraft.world.level.block.entity.SkullBlockEntity; @DelegateDeserialization(SerializableMeta.class) class CraftMetaSkull extends CraftMetaItem implements SkullMeta { @@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta { - return hasOwner() ? profile.getName() : null; + return this.hasOwner() ? this.profile.getName() : null; } + // Paper start @@ -87,13 +87,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @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); + if (this.hasOwner()) { diff --git a/Spigot-Server-Patches/Add-setting-for-proxy-online-mode-status.patch b/patches/server/Add-setting-for-proxy-online-mode-status.patch similarity index 62% rename from Spigot-Server-Patches/Add-setting-for-proxy-online-mode-status.patch rename to patches/server/Add-setting-for-proxy-online-mode-status.patch index f7766069ab..bd3134d0b0 100644 --- a/Spigot-Server-Patches/Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server/Add-setting-for-proxy-online-mode-status.patch @@ -3,6 +3,7 @@ From: Gabriele C Date: Fri, 5 Aug 2016 01:03:08 +0200 Subject: [PATCH] Add setting for proxy online mode status +TODO: Add isProxyOnlineMode check to Metrics diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -30,41 +31,41 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/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 { +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -0,0 +0,0 @@ public class GameProfileCache { } }; + if (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode()) // Paper - only run in online mode - 100 COL - gameprofilerepository.findProfilesByNames(new String[]{s}, Agent.MINECRAFT, profilelookupcallback); + repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); GameProfile gameprofile = (GameProfile) atomicreference.get(); -@@ -0,0 +0,0 @@ public class UserCache { +@@ -0,0 +0,0 @@ public class GameProfileCache { } - private static boolean c() { -- return UserCache.b; + private static boolean usesAuthentication() { +- return GameProfileCache.usesAuthentication; + return com.destroystokyo.paper.PaperConfig.isProxyOnlineMode(); // Paper } - public synchronized void a(GameProfile gameprofile) { // Paper - synchronize + public synchronized void add(GameProfile profile) { // Paper - synchronize +diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java ++++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java +@@ -0,0 +0,0 @@ public class OldUsersConverter { + return new String[i]; + }); + +- if (server.usesAuthentication() || org.spigotmc.SpigotConfig.bungee) { // Spigot: bungee = online mode, for now. ++ if (server.usesAuthentication() ++ || (com.destroystokyo.paper.PaperConfig.isProxyOnlineMode())) { // Spigot: bungee = online mode, for now. // Paper - Handle via setting + server.getProfileRepository().findProfilesByNames(astring, Agent.MINECRAFT, callback); + } else { + String[] astring1 = astring; 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 @@ -73,9 +74,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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 +- if ( this.getOnlineMode() || org.spigotmc.SpigotConfig.bungee ) ++ if ( this.getOnlineMode() || com.destroystokyo.paper.PaperConfig.isProxyOnlineMode() ) // Paper - Handle via setting { - profile = console.getUserCache().getProfile( name ); + profile = this.console.getProfileCache().get( name ); } diff --git a/patches/server/Add-source-to-PlayerExpChangeEvent.patch b/patches/server/Add-source-to-PlayerExpChangeEvent.patch new file mode 100644 index 0000000000..49b1a821fa --- /dev/null +++ b/patches/server/Add-source-to-PlayerExpChangeEvent.patch @@ -0,0 +1,41 @@ +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/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + int i = this.repairPlayerItems(player, this.value); + + if (i > 0) { +- player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() ++ player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, this).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object + } + + --this.count; +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 - Add orb ++ public static PlayerExpChangeEvent callPlayerExpChangeEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb 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(Level world, BlockPos pos, net.minecraft.world.level.block.state.BlockState block) { + return CraftEventFactory.handleBlockGrowEvent(world, pos, block, 3); + } diff --git a/Spigot-Server-Patches/Add-sun-related-API.patch b/patches/server/Add-sun-related-API.patch similarity index 63% rename from Spigot-Server-Patches/Add-sun-related-API.patch rename to patches/server/Add-sun-related-API.patch index cc41e5cd6a..448a77da13 100644 --- a/Spigot-Server-Patches/Add-sun-related-API.patch +++ b/patches/server/Add-sun-related-API.patch @@ -4,18 +4,6 @@ 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 @@ -33,20 +21,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public long getGameTime() { - return world.worldData.getTime(); + return world.levelData.getGameTime(); 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; + return this.getHandle().lootTableSeed; } + + // Paper start + @Override + public boolean isInDaylight() { -+ return getHandle().isInDaylight(); ++ return getHandle().isSunBurnTick(); + } + // Paper end } diff --git a/Spigot-Server-Patches/Add-support-for-hex-color-codes-in-console.patch b/patches/server/Add-support-for-hex-color-codes-in-console.patch similarity index 93% rename from Spigot-Server-Patches/Add-support-for-hex-color-codes-in-console.patch rename to patches/server/Add-support-for-hex-color-codes-in-console.patch index ca4d56563e..1eeab1c72f 100644 --- a/Spigot-Server-Patches/Add-support-for-hex-color-codes-in-console.patch +++ b/patches/server/Add-support-for-hex-color-codes-in-console.patch @@ -5,6 +5,18 @@ 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/build.gradle.kts b/build.gradle.kts +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + Scanning takes about 1-2 seconds so adding this speeds up the server start. + */ + implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation ++ annotationProcessor("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - Needed to generate meta for out hex color converter plugin + // Paper end + implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper + implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper 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 diff --git a/Spigot-Server-Patches/Add-tick-times-API-and-mspt-command.patch b/patches/server/Add-tick-times-API-and-mspt-command.patch similarity index 87% rename from Spigot-Server-Patches/Add-tick-times-API-and-mspt-command.patch rename to patches/server/Add-tick-times-API-and-mspt-command.patch index 7be8315621..7ec40a9845 100644 --- a/Spigot-Server-Patches/Add-tick-times-API-and-mspt-command.patch +++ b/patches/server/Add-tick-times-API-and-mspt-command.patch @@ -90,36 +90,35 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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 gossips = Maps.newHashMap(); ++ private final Map gossips = Maps.newHashMap(); public Map getReputations() { return this.gossips; } // Paper - add getter for reputations -- 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); + @VisibleForDebug + public Map> getGossipEntries() { +@@ -0,0 +0,0 @@ public class GossipContainer { + public void remove(GossipType gossipType) { + this.entries.removeInt(gossipType); } + + // 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); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MAJOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_NEGATIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE.ordinal()] = entries.getOrDefault(GossipType.MINOR_POSITIVE, 0); ++ reputation[com.destroystokyo.paper.entity.villager.ReputationType.TRADING.ordinal()] = entries.getOrDefault(GossipType.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); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_NEGATIVE)) != 0) this.entries.put(GossipType.MAJOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MAJOR_POSITIVE)) != 0) this.entries.put(GossipType.MAJOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_NEGATIVE)) != 0) this.entries.put(GossipType.MINOR_NEGATIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.MINOR_POSITIVE)) != 0) this.entries.put(GossipType.MINOR_POSITIVE, val); ++ if ((val = rep.getReputation(com.destroystokyo.paper.entity.villager.ReputationType.TRADING)) != 0) this.entries.put(GossipType.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; - } + static class GossipEntry { 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 @@ -104,16 +78,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public class CraftVillager extends CraftAbstractVillager implements Villager { - public CraftVillager(CraftServer server, EntityVillager entity) { + public CraftVillager(CraftServer server, net.minecraft.world.entity.npc.Villager 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())); + return Registry.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); ++ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips rep = getHandle().getGossips().getReputations().get(uniqueId); + if (rep == null) { + return new Reputation(Maps.newHashMap()); + } @@ -123,17 +97,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public Map getReputations() { -+ return getHandle().getReputation().getReputations().entrySet() ++ return getHandle().getGossips().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( ++ net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips nmsReputation = ++ getHandle().getGossips().getReputations().computeIfAbsent( + uniqueId, -+ key -> new net.minecraft.world.entity.ai.gossip.Reputation.a() ++ key -> new net.minecraft.world.entity.ai.gossip.GossipContainer.EntityGossips() + ); + nmsReputation.assignFromPaperReputation(reputation); + } @@ -147,7 +121,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public void clearReputations() { -+ getHandle().getReputation().getReputations().clear(); ++ getHandle().getGossips().getReputations().clear(); + } + // Paper end } diff --git a/patches/server/Add-worldborder-events.patch b/patches/server/Add-worldborder-events.patch new file mode 100644 index 0000000000..adbe3853c3 --- /dev/null +++ b/patches/server/Add-worldborder-events.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +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 @@ public class WorldBorder { + } + + public void setCenter(double x, double z) { +- this.centerX = x; +- this.centerZ = z; ++ // Paper start ++ io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderCenterChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), new org.bukkit.Location(world.getWorld(), this.getCenterX(), 0, this.getCenterZ()), new org.bukkit.Location(world.getWorld(), x, 0, z)); ++ if (!event.callEvent()) return; ++ this.centerX = event.getNewCenter().getX(); ++ this.centerZ = event.getNewCenter().getZ(); ++ // Paper end + this.extent.onCenterChange(); + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderCenterSet(this, x, z); ++ iworldborderlistener.onBorderCenterSet(this, event.getNewCenter().getX(), event.getNewCenter().getZ()); // Paper + } + + } +@@ -0,0 +0,0 @@ public class WorldBorder { + } + + public void setSize(double size) { +- this.extent = new WorldBorder.StaticBorderExtent(size); ++ // Paper start ++ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE, getSize(), size, 0); ++ if (!event.callEvent()) return; ++ if (event.getType() == io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.STARTED_MOVE && event.getDuration() > 0) { // If changed to a timed transition ++ lerpSizeBetween(event.getOldSize(), event.getNewSize(), event.getDuration()); ++ return; ++ } ++ this.extent = new WorldBorder.StaticBorderExtent(event.getNewSize()); ++ // Paper end + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderSizeSet(this, size); ++ iworldborderlistener.onBorderSizeSet(this, event.getNewSize()); // Paper + } + + } + + public void lerpSizeBetween(double fromSize, double toSize, long time) { +- this.extent = (WorldBorder.BorderExtent) (fromSize == toSize ? new WorldBorder.StaticBorderExtent(toSize) : new WorldBorder.MovingBorderExtent(fromSize, toSize, time)); ++ // Paper start ++ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type type; ++ if (fromSize == toSize) { // new size = old size ++ type = io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.INSTANT_MOVE; // Use INSTANT_MOVE because below it creates a Static border if they are equal. ++ } else { ++ type = io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent.Type.STARTED_MOVE; ++ } ++ io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent event = new io.papermc.paper.event.world.border.WorldBorderBoundsChangeEvent(world.getWorld(), world.getWorld().getWorldBorder(), type, fromSize, toSize, time); ++ if (!event.callEvent()) return; ++ this.extent = (WorldBorder.BorderExtent) (fromSize == event.getNewSize() ? new WorldBorder.StaticBorderExtent(event.getNewSize()) : new WorldBorder.MovingBorderExtent(fromSize, event.getNewSize(), event.getDuration())); ++ // Paper end + Iterator iterator = this.getListeners().iterator(); + + while (iterator.hasNext()) { + BorderChangeListener iworldborderlistener = (BorderChangeListener) iterator.next(); + +- iworldborderlistener.onBorderSizeLerping(this, fromSize, toSize, time); ++ iworldborderlistener.onBorderSizeLerping(this, fromSize, event.getNewSize(), event.getDuration()); // Paper + } + + } +@@ -0,0 +0,0 @@ public class WorldBorder { + + @Override + public WorldBorder.BorderExtent update() { ++ if (this.getLerpRemainingTime() <= 0L) new io.papermc.paper.event.world.border.WorldBorderBoundsChangeFinishEvent(world.getWorld(), world.getWorld().getWorldBorder(), this.from, this.to, this.lerpDuration).callEvent(); // Paper + return (WorldBorder.BorderExtent) (this.getLerpRemainingTime() <= 0L ? WorldBorder.this.new StaticBorderExtent(this.to) : this); + } + diff --git a/patches/server/Add-zombie-targets-turtle-egg-config.patch b/patches/server/Add-zombie-targets-turtle-egg-config.patch new file mode 100644 index 0000000000..b99215963d --- /dev/null +++ b/patches/server/Add-zombie-targets-turtle-egg-config.patch @@ -0,0 +1,35 @@ +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 { + } + } + ++ public boolean zombiesTargetTurtleEggs = true; ++ private void zombiesTargetTurtleEggs() { ++ zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); ++ } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); ++ if (level.paperConfig.zombiesTargetTurtleEggs) this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); // Paper + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.addBehaviourGoals(); diff --git a/patches/server/Added-PlayerBedFailEnterEvent.patch b/patches/server/Added-PlayerBedFailEnterEvent.patch new file mode 100644 index 0000000000..65a2f0c540 --- /dev/null +++ b/patches/server/Added-PlayerBedFailEnterEvent.patch @@ -0,0 +1,36 @@ +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/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java +@@ -0,0 +0,0 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock + BlockPos finalblockposition = pos; + // CraftBukkit end + player.startSleepInBed(pos).ifLeft((entityhuman_enumbedresult) -> { ++ // Paper start - PlayerBedFailEnterEvent ++ if (entityhuman_enumbedresult != null) { ++ io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.VALUES[entityhuman_enumbedresult.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(world, finalblockposition), entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE, io.papermc.paper.adventure.PaperAdventure.asAdventure(entityhuman_enumbedresult.getMessage())); ++ if (!event.callEvent()) { ++ return; ++ } ++ // Paper end + // CraftBukkit start - handling bed explosion from below here +- if (entityhuman_enumbedresult == Player.BedSleepingProblem.NOT_POSSIBLE_HERE) { ++ if (event.getWillExplode()) { // Paper + this.explodeBed(finaliblockdata, world, finalblockposition); + } else + // CraftBukkit end + if (entityhuman_enumbedresult != null) { +- player.displayClientMessage(entityhuman_enumbedresult.getMessage(), true); ++ final net.kyori.adventure.text.Component message = event.getMessage(); // Paper ++ if(message != null) player.displayClientMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(message), true); // Paper + } ++ } // Paper + + }); + return InteractionResult.SUCCESS; diff --git a/patches/server/Added-PlayerDeepSleepEvent.patch b/patches/server/Added-PlayerDeepSleepEvent.patch new file mode 100644 index 0000000000..1a556f2b4b --- /dev/null +++ b/patches/server/Added-PlayerDeepSleepEvent.patch @@ -0,0 +1,22 @@ +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/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + + if (this.isSleeping()) { + ++this.sleepCounter; ++ // Paper start ++ if (this.sleepCounter == 100) { ++ if (!new io.papermc.paper.event.player.PlayerDeepSleepEvent((org.bukkit.entity.Player) getBukkitEntity()).callEvent()) { this.sleepCounter = Integer.MIN_VALUE; } ++ } ++ // Paper end + if (this.sleepCounter > 100) { + this.sleepCounter = 100; + } diff --git a/patches/server/Added-PlayerLecternPageChangeEvent.patch b/patches/server/Added-PlayerLecternPageChangeEvent.patch new file mode 100644 index 0000000000..97329fa653 --- /dev/null +++ b/patches/server/Added-PlayerLecternPageChangeEvent.patch @@ -0,0 +1,46 @@ +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/LecternMenu.java b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/LecternMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LecternMenu.java +@@ -0,0 +0,0 @@ public class LecternMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + int j; ++ io.papermc.paper.event.player.PlayerLecternPageChangeEvent playerLecternPageChangeEvent; CraftInventoryLectern bukkitView; // Paper + + if (id >= 100) { + j = id - 100; +@@ -0,0 +0,0 @@ public class LecternMenu extends AbstractContainerMenu { + switch (id) { + case 1: + j = this.lecternData.get(0); +- this.setData(0, j - 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.LEFT, j, j - 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 2: + j = this.lecternData.get(0); +- this.setData(0, j + 1); ++ // Paper start ++ bukkitView = (CraftInventoryLectern) getBukkitView().getTopInventory(); ++ playerLecternPageChangeEvent = new io.papermc.paper.event.player.PlayerLecternPageChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), bukkitView.getHolder(), bukkitView.getBook(), io.papermc.paper.event.player.PlayerLecternPageChangeEvent.PageChangeDirection.RIGHT, j, j + 1); ++ if (!playerLecternPageChangeEvent.callEvent()) { ++ return false; ++ } ++ this.setData(0, playerLecternPageChangeEvent.getNewPage()); ++ // Paper end + return true; + case 3: + if (!player.mayBuild()) { diff --git a/patches/server/Added-PlayerLoomPatternSelectEvent.patch b/patches/server/Added-PlayerLoomPatternSelectEvent.patch new file mode 100644 index 0000000000..799661d6d9 --- /dev/null +++ b/patches/server/Added-PlayerLoomPatternSelectEvent.patch @@ -0,0 +1,34 @@ +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/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java +@@ -0,0 +0,0 @@ public class LoomMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (id > 0 && id <= BannerPattern.AVAILABLE_PATTERNS) { +- this.selectedBannerPatternIndex.set(id); ++ // Paper start ++ int enumBannerPatternTypeOrdinal = id; ++ io.papermc.paper.event.player.PlayerLoomPatternSelectEvent event = new io.papermc.paper.event.player.PlayerLoomPatternSelectEvent((Player) player.getBukkitEntity(), ((CraftInventoryLoom) getBukkitView().getTopInventory()), org.bukkit.block.banner.PatternType.getByIdentifier(BannerPattern.values()[id].getHashname())); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ for (BannerPattern nms : BannerPattern.values()) { ++ if (event.getPatternType().getIdentifier().equals(nms.getHashname())) { ++ enumBannerPatternTypeOrdinal = nms.ordinal(); ++ break; ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.selectedBannerPatternIndex.set(enumBannerPatternTypeOrdinal); ++ // Paper end + this.setupResultSlot(); + return true; + } else { diff --git a/patches/server/Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/server/Added-PlayerStonecutterRecipeSelectEvent.patch new file mode 100644 index 0000000000..a572cf9e23 --- /dev/null +++ b/patches/server/Added-PlayerStonecutterRecipeSelectEvent.patch @@ -0,0 +1,51 @@ +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/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java +@@ -0,0 +0,0 @@ public class StonecutterMenu extends AbstractContainerMenu { + + public StonecutterMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) { + super(MenuType.STONECUTTER, syncId); +- this.selectedRecipeIndex = DataSlot.standalone(); ++ this.selectedRecipeIndex = addDataSlot(DataSlot.shared(new int[1], 0)); // Paper - allow replication + this.recipes = Lists.newArrayList(); + this.input = ItemStack.EMPTY; + this.slotUpdateListener = () -> { +@@ -0,0 +0,0 @@ public class StonecutterMenu extends AbstractContainerMenu { + @Override + public boolean clickMenuButton(net.minecraft.world.entity.player.Player player, int id) { + if (this.isValidRecipeIndex(id)) { +- this.selectedRecipeIndex.set(id); ++ // Paper start ++ int recipeIndex = id; ++ this.selectedRecipeIndex.set(recipeIndex); ++ this.selectedRecipeIndex.checkAndClearUpdateFlag(); // mark as changed ++ if (this.isValidRecipeIndex(id)) { ++ io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent event = new io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent((Player) player.getBukkitEntity(), (org.bukkit.inventory.StonecutterInventory) getBukkitView().getTopInventory(), (org.bukkit.inventory.StonecuttingRecipe) this.getRecipes().get(id).toBukkitRecipe()); ++ if (!event.callEvent()) { ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ return false; ++ } ++ int newRecipeIndex; ++ if (!this.getRecipes().get(recipeIndex).getId().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).getId().equals(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(event.getStonecuttingRecipe().getKey()))) { ++ recipeIndex = newRecipeIndex; ++ break; ++ } ++ } ++ } ++ } ++ ((Player) player.getBukkitEntity()).updateInventory(); ++ this.selectedRecipeIndex.set(recipeIndex); // set new index, so that listeners can read it ++ // Paper end + this.setupResultSlot(); + } + diff --git a/patches/server/Added-ServerResourcesReloadedEvent.patch b/patches/server/Added-ServerResourcesReloadedEvent.patch new file mode 100644 index 0000000000..e35ab8dee3 --- /dev/null +++ b/patches/server/Added-ServerResourcesReloadedEvent.patch @@ -0,0 +1,54 @@ +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 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop reloadResources(Collection datapacks) { ++ return this.reloadResources(datapacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); ++ } ++ public CompletableFuture reloadResources(Collection datapacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause cause) { ++ // Paper end + CompletableFuture completablefuture = CompletableFuture.supplyAsync(() -> { + Stream stream = datapacks.stream(); // CraftBukkit - decompile error + PackRepository resourcepackrepository = this.packRepository; +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop dataPacks, CommandSourceStack source) { +- source.getServer().reloadResources(dataPacks).exceptionally((throwable) -> { ++ source.getServer().reloadResources(dataPacks, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.COMMAND).exceptionally((throwable) -> { + ReloadCommand.LOGGER.warn("Failed to execute reload", throwable); + source.sendFailure(new TranslatableComponent("commands.reload.failure")); + return null; +@@ -0,0 +0,0 @@ public class ReloadCommand { + WorldData savedata = minecraftserver.getWorldData(); + Collection collection = resourcepackrepository.getSelectedIds(); + Collection collection1 = ReloadCommand.discoverNewPacks(resourcepackrepository, savedata, collection); +- minecraftserver.reloadResources(collection1); ++ minecraftserver.reloadResources(collection1, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper + } + // CraftBukkit end + diff --git a/Spigot-Server-Patches/Added-Vanilla-Entity-Tags.patch b/patches/server/Added-Vanilla-Entity-Tags.patch similarity index 67% rename from Spigot-Server-Patches/Added-Vanilla-Entity-Tags.patch rename to patches/server/Added-Vanilla-Entity-Tags.patch index 65f5f03299..1ac4368de4 100644 --- a/Spigot-Server-Patches/Added-Vanilla-Entity-Tags.patch +++ b/patches/server/Added-Vanilla-Entity-Tags.patch @@ -12,9 +12,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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; @@ -22,21 +19,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.tags.TagCollection; + -+public class CraftEntityTag extends CraftTag, EntityType> { ++public class CraftEntityTag extends CraftTag, EntityType> { + -+ public CraftEntityTag(Tags> registry, MinecraftKey tag) { ++ public CraftEntityTag(TagCollection> registry, ResourceLocation tag) { + super(registry, tag); + } + + @Override + public boolean isTagged(EntityType item) { -+ return getHandle().isTagged(CraftMagicNumbers.getEntityTypes(item)); ++ return getHandle().contains(CraftMagicNumbers.getEntityTypes(item)); + } + + @Override + public Set getValues() { -+ return Collections.unmodifiableSet(getHandle().getTagged().stream().map(CraftMagicNumbers::getEntityType).collect(Collectors.toSet())); ++ return Collections.unmodifiableSet(getHandle().getValues().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 @@ -46,11 +45,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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); + return (org.bukkit.Tag) new CraftFluidTag(FluidTags.getAllTags(), 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); ++ return (org.bukkit.Tag) new io.papermc.paper.CraftEntityTag(net.minecraft.tags.EntityTypeTags.getAllTags(), key); + // Paper end default: throw new IllegalArgumentException(); @@ -62,30 +61,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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<>(); + 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<>(); ++ 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); ++ ENTITY_TYPE_ENTITY_TYPES.put(type, net.minecraft.core.Registry.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(type.getKey()))); ++ ENTITY_TYPES_ENTITY_TYPE.put(net.minecraft.core.Registry.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))); + for (Block block : net.minecraft.core.Registry.BLOCK) { + BLOCK_MATERIAL.put(block, Material.getMaterial(net.minecraft.core.Registry.BLOCK.getKey(block).getPath().toUpperCase(Locale.ROOT))); } @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public static MinecraftKey key(Material mat) { + public static ResourceLocation key(Material mat) { return CraftNamespacedKey.toMinecraft(mat.getKey()); } + // Paper start -+ public static net.minecraft.world.entity.EntityTypes getEntityTypes(org.bukkit.entity.EntityType type) { ++ public static net.minecraft.world.entity.EntityType 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) { ++ public static org.bukkit.entity.EntityType getEntityType(net.minecraft.world.entity.EntityType entityTypes) { + return ENTITY_TYPES_ENTITY_TYPE.get(entityTypes); + } + // Paper end diff --git a/patches/server/Added-WorldGameRuleChangeEvent.patch b/patches/server/Added-WorldGameRuleChangeEvent.patch new file mode 100644 index 0000000000..fc31b4135c --- /dev/null +++ b/patches/server/Added-WorldGameRuleChangeEvent.patch @@ -0,0 +1,98 @@ +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/GameRuleCommand.java b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/commands/GameRuleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameRuleCommand.java +@@ -0,0 +0,0 @@ public class GameRuleCommand { + CommandSourceStack commandlistenerwrapper = (CommandSourceStack) context.getSource(); + T t0 = commandlistenerwrapper.getLevel().getGameRules().getRule(key); // CraftBukkit + +- t0.setFromArgument(context, "value"); ++ t0.setFromArgument(context, "value", key); // Paper + commandlistenerwrapper.sendSuccess(new TranslatableComponent("commands.gamerule.set", new Object[]{key.getId(), t0.toString()}), true); + return t0.getCommandResult(); + } +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 @@ public class GameRules { + this.type = type; + } + +- protected abstract void updateFromArgument(CommandContext context, String name); ++ protected abstract void updateFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey); // Paper + +- public void setFromArgument(CommandContext context, String name) { +- this.updateFromArgument(context, name); ++ public void setFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey) { // Paper ++ this.updateFromArgument(context, name, gameRuleKey); // Paper + this.onChanged(((CommandSourceStack) context.getSource()).getServer()); + } + +@@ -0,0 +0,0 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = BoolArgumentType.getBool(context, name); ++ protected void updateFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey) { // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(BoolArgumentType.getBool(context, name))); ++ if (!event.callEvent()) return; ++ this.value = Boolean.parseBoolean(event.getValue()); ++ // Paper end + } + + public boolean get() { +@@ -0,0 +0,0 @@ public class GameRules { + } + + @Override +- protected void updateFromArgument(CommandContext context, String name) { +- this.value = IntegerArgumentType.getInteger(context, name); ++ protected void updateFromArgument(CommandContext context, String name, GameRules.Key gameRuleKey) { // Paper start ++ io.papermc.paper.event.world.WorldGameRuleChangeEvent event = new io.papermc.paper.event.world.WorldGameRuleChangeEvent(context.getSource().getBukkitWorld(), context.getSource().getBukkitSender(), (org.bukkit.GameRule) org.bukkit.GameRule.getByName(gameRuleKey.toString()), String.valueOf(IntegerArgumentType.getInteger(context, name))); ++ if (!event.callEvent()) return; ++ this.value = Integer.parseInt(event.getValue()); ++ // Paper end + } + + public int get() { +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 (!this.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.Value handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule)); +- handle.deserialize(value); ++ handle.deserialize(event.getValue()); // Paper + handle.onChanged(this.getHandle().getServer()); + return true; + } +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + + if (!this.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.Value handle = this.getHandle().getGameRules().getRule(CraftWorld.getGameRulesNMS().get(rule.getName())); +- handle.deserialize(newValue.toString()); ++ handle.deserialize(event.getValue()); // Paper + handle.onChanged(this.getHandle().getServer()); + return true; + } diff --git a/patches/server/Added-firing-of-PlayerChangeBeaconEffectEvent.patch b/patches/server/Added-firing-of-PlayerChangeBeaconEffectEvent.patch new file mode 100644 index 0000000000..53a437635b --- /dev/null +++ b/patches/server/Added-firing-of-PlayerChangeBeaconEffectEvent.patch @@ -0,0 +1,28 @@ +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/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java +@@ -0,0 +0,0 @@ public class BeaconMenu extends AbstractContainerMenu { + + public void updateEffects(int primaryEffectId, int secondaryEffectId) { + if (this.paymentSlot.hasItem()) { +- this.beaconData.set(1, primaryEffectId); +- this.beaconData.set(2, secondaryEffectId); ++ // Paper start ++ io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent event = new io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), org.bukkit.potion.PotionEffectType.getById(primaryEffectId), org.bukkit.potion.PotionEffectType.getById(secondaryEffectId), this.access.getLocation().getBlock()); ++ if (event.callEvent()) { ++ this.beaconData.set(1, event.getPrimary() == null ? 0 : event.getPrimary().getId()); ++ this.beaconData.set(2, event.getSecondary() == null ? 0 : event.getSecondary().getId()); ++ if (!event.willConsumeItem()) return; + this.paymentSlot.remove(1); ++ } ++ // Paper end + } + + } diff --git a/patches/server/Added-missing-default-perms-for-commands.patch b/patches/server/Added-missing-default-perms-for-commands.patch new file mode 100644 index 0000000000..aa1f7c7189 --- /dev/null +++ b/patches/server/Added-missing-default-perms-for-commands.patch @@ -0,0 +1,70 @@ +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(CommandPermissions.PREFIX + "effect", "Allows the user to add/remove effects on players", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "selector", "Allows the use of selectors", PermissionDefault.OP, commands); + DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "trigger", "Allows the use of the trigger command", PermissionDefault.TRUE, commands); ++ // Paper start ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "attribute", "Allows the user to query, add, remove or set an entity attribute", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "advancement", "Allows the user to give, remove, or check player advancements", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban", "Allows the user to add players to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "ban-ip", "Allows the user to add ip address to banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "banlist", "Allows the user to display banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "bossbar", "Allows the user to create and modify bossbars", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clear", "Allows the user to clear items from player inventory", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "clone", "Allows the user to copy blocks from one place to another", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "data", "Allows the user to get, merge, modify, and remove block entity and entity NBT data", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "datapack", "Allows the user to control loaded data packs", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "debug", "Allows the user to start or stop a debugging session", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "deop", "Allows the user to revoke operator status from a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "difficulty", "Allows the user to set the difficulty level", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "enchant", "Allows the user to enchant a player item", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "execute", "Allows the user to execute another command", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "fill", "Allows the user to fill a region with a specific block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "forceload", "Allows the user to force chunks to be constantly loaded or not", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "function", "Allows the user to run a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "gamerule", "Allows a user to set or query a game rule value", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locate", "Allows the user to locate the closest structure", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "locatebiome", "Allows the user to locate the closest biome", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "loot", "Allows the user to drop items from an inventory slot onto the ground", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "op", "Allows the user to grant operator status to a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "pardon", "Allows the user to remove entries from the banlist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "particle", "Allows the user to create particles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "playsound", "Allows the user to play a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "recipe", "Allows the user to give or take recipes", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "reload", "Allows the user to reload loot tables, advancements, and functions from disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "item", "Allows the user to replace items in inventories", PermissionDefault.OP, commands); // Remove in 1.17 (replaced by /item) ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-all", "Allows the user to save the server to disk", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-off", "Allows the user disable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "save-on", "Allows the user enable automatic server saves", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "schedule", "Allows the user to delay the execution of a function", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "scoreboard", "Allows the user manage scoreboard objectives and players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setblock", "Allows the user to change a block to another block", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setidletimeout", "Allows the user to set the time before idle players are kicked", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "setworldspawn", "Allows the user to set the world spawn", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spawnpoint", "Allows the user to set the spawn point for a player", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spectate", "Allows the user to make one player in spectator mode spectate an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "spreadplayers", "Allows the user to teleport entities to random locations", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "stopsound", "Allows the user to stop a sound", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "summon", "Allows the user to summon an entity", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tag", "Allows the user to control entity tags", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "team", "Allows the user to control teams", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "teammsg", "Allows the user to specify the message to send to team", PermissionDefault.TRUE, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "tellraw", "Allows the user to display a JSON message to players", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "time", "Allows the user to change or query the world's game time", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "title", "Allows the user to manage screen titles", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "weather", "Allows the user to set the weather", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.PREFIX + "whitelist", "Allows the user to manage the server whitelist", PermissionDefault.OP, commands); ++ DefaultPermissions.registerPermission(CommandPermissions.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/patches/server/Added-world-settings-for-mobs-picking-up-loot.patch similarity index 54% rename from Spigot-Server-Patches/Added-world-settings-for-mobs-picking-up-loot.patch rename to patches/server/Added-world-settings-for-mobs-picking-up-loot.patch index d5f02bcb45..210a3583c7 100644 --- a/Spigot-Server-Patches/Added-world-settings-for-mobs-picking-up-loot.patch +++ b/patches/server/Added-world-settings-for-mobs-picking-up-loot.patch @@ -23,29 +23,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.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()) { +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -0,0 +0,0 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + this.populateDefaultEquipmentSlots(difficulty); + this.populateDefaultEquipmentEnchantments(difficulty); + this.reassessWeaponGoal(); +- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); ++ this.setCanPickUpLoot(this.level.paperConfig.skeletonsAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper + if (this.getItemBySlot(EquipmentSlot.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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.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(); +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + Object object = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityNbt); + float f = difficulty.getSpecialMultiplier(); -- this.setCanPickupLoot(this.random.nextFloat() < 0.55F * f); -+ this.setCanPickupLoot(this.world.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper +- this.setCanPickUpLoot(this.random.nextFloat() < 0.55F * f); ++ this.setCanPickUpLoot(this.level.paperConfig.zombiesAlwaysCanPickUpLoot || this.random.nextFloat() < 0.55F * f); // Paper if (object == null) { - object = new EntityZombie.GroupDataZombie(a(worldaccess.getRandom()), true); + object = new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(world.getRandom()), true); } diff --git a/Spigot-Server-Patches/Additional-Block-Material-API-s.patch b/patches/server/Additional-Block-Material-API-s.patch similarity index 75% rename from Spigot-Server-Patches/Additional-Block-Material-API-s.patch rename to patches/server/Additional-Block-Material-API-s.patch index 969de70cfa..346a59c3e6 100644 --- a/Spigot-Server-Patches/Additional-Block-Material-API-s.patch +++ b/patches/server/Additional-Block-Material-API-s.patch @@ -13,17 +13,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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(); + return this.getNMS().getMaterial().isLiquid(); } + // Paper start + @Override + public boolean isBuildable() { -+ return getNMS().getMaterial().isBuildable(); ++ return getNMS().getMaterial().isSolid(); // This is in fact isSolid, despite the fact that isSolid below returns blocksMotion + } + @Override + public boolean isBurnable() { -+ return getNMS().getMaterial().isBurnable(); ++ return getNMS().getMaterial().isFlammable(); + } + @Override + public boolean isReplaceable() { @@ -31,10 +31,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + @Override + public boolean isSolid() { -+ return getNMS().getMaterial().isSolid(); ++ return getNMS().getMaterial().blocksMotion(); + } + // Paper end + @Override public PistonMoveReaction getPistonMoveReaction() { - return PistonMoveReaction.getById(getNMS().getPushReaction().ordinal()); + return PistonMoveReaction.getById(this.getNMS().getPistonPushReaction().ordinal()); diff --git a/Spigot-Server-Patches/Adventure.patch b/patches/server/Adventure.patch similarity index 68% rename from Spigot-Server-Patches/Adventure.patch rename to patches/server/Adventure.patch index 937c8d69a4..bf72bfedc5 100644 --- a/Spigot-Server-Patches/Adventure.patch +++ b/patches/server/Adventure.patch @@ -35,22 +35,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.network.chat.MutableComponent; ++import net.minecraft.network.chat.Style; ++import net.minecraft.util.FormattedCharSequence; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + -+public final class AdventureComponent implements IChatBaseComponent { ++public final class AdventureComponent implements net.minecraft.network.chat.Component { + final Component wrapped; -+ private @MonotonicNonNull IChatBaseComponent converted; ++ private net.minecraft.network.chat.@MonotonicNonNull Component converted; + + public AdventureComponent(final Component wrapped) { + this.wrapped = wrapped; + } + -+ public IChatBaseComponent deepConverted() { -+ IChatBaseComponent converted = this.converted; ++ public net.minecraft.network.chat.Component deepConverted() { ++ net.minecraft.network.chat.Component converted = this.converted; + if (converted == null) { + converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped); + this.converted = converted; @@ -58,21 +58,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return converted; + } + -+ public @Nullable IChatBaseComponent deepConvertedIfPresent() { ++ public net.minecraft.network.chat.@Nullable Component deepConvertedIfPresent() { + return this.converted; + } + + @Override -+ public ChatModifier getChatModifier() { -+ return this.deepConverted().getChatModifier(); ++ public Style getStyle() { ++ return this.deepConverted().getStyle(); + } + + @Override -+ public String getText() { ++ public String getContents() { + if (this.wrapped instanceof TextComponent) { + return ((TextComponent) this.wrapped).content(); + } else { -+ return this.deepConverted().getText(); ++ return this.deepConverted().getContents(); + } + } + @@ -82,18 +82,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public List getSiblings() { ++ public List getSiblings() { + return this.deepConverted().getSiblings(); + } + + @Override -+ public IChatMutableComponent g() { -+ return this.deepConverted().g(); ++ public MutableComponent plainCopy() { ++ return this.deepConverted().plainCopy(); + } + + @Override -+ public IChatMutableComponent mutableCopy() { -+ return this.deepConverted().mutableCopy(); ++ public MutableComponent copy() { ++ return this.deepConverted().copy(); ++ } ++ ++ @Override ++ public FormattedCharSequence getVisualOrderText() { ++ return this.deepConverted().getVisualOrderText(); + } + + public static class Serializer implements JsonSerializer { @@ -115,6 +120,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import io.papermc.paper.event.player.AbstractChatEvent; +import io.papermc.paper.event.player.AsyncChatEvent; +import io.papermc.paper.event.player.ChatEvent; ++import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; @@ -125,9 +131,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.server.level.ServerPlayer; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.util.LazyPlayerSet; @@ -154,12 +159,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build(); + // copied from adventure-text-serializer-legacy --> + final MinecraftServer server; -+ final EntityPlayer player; ++ final ServerPlayer player; + final String message; + final boolean async; + final Component originalMessage; + -+ public ChatProcessor(final MinecraftServer server, final EntityPlayer player, final String message, final boolean async) { ++ public ChatProcessor(final MinecraftServer server, final ServerPlayer player, final String message, final boolean async) { + this.server = server; + this.player = player; + this.message = message; @@ -174,7 +179,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + event -> { + this.processModern( + legacyRenderer(event.getFormat()), -+ event.getRecipients(), ++ this.viewersFromLegacy(event.getRecipients()), + PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), + event.isCancelled() + ); @@ -183,7 +188,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + event -> { + this.processModern( + legacyRenderer(event.getFormat()), -+ event.getRecipients(), ++ this.viewersFromLegacy(event.getRecipients()), + PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), + event.isCancelled() + ); @@ -192,7 +197,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + () -> { + this.processModern( + ChatRenderer.defaultRenderer(), -+ new LazyPlayerSet(this.server), ++ new LazyChatAudienceSet(this.server), + Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), + false + ); @@ -200,6 +205,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ); + } + ++ private Set viewersFromLegacy(final Set recipients) { ++ if (recipients instanceof LazyPlayerSet lazyPlayerSet && lazyPlayerSet.isLazy()) { ++ return new LazyChatAudienceSet(this.server); ++ } ++ final HashSet viewers = new HashSet<>(recipients); ++ viewers.add(this.server.console); ++ return viewers; ++ } ++ + @SuppressWarnings("deprecation") + private void processingLegacyFirst( + final Consumer continueAfterAsync, @@ -231,8 +245,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ 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); ++ private void processModern(final ChatRenderer renderer, final Set viewers, final Component message, final boolean cancelled) { ++ final AsyncChatEvent ae = this.createAsync(renderer, viewers, message); + ae.setCancelled(cancelled); // propagate cancelled state + post(ae); + final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); @@ -247,7 +261,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.queueIfAsyncOrRunImmediately(new Waitable() { + @Override + protected Void evaluate() { -+ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.recipients(), ae.viewers(), ae.message()); ++ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.viewers(), ae.message()); + se.setCancelled(ae.isCancelled()); // propagate cancelled state + post(se); + ChatProcessor.this.complete(se); @@ -267,26 +281,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ ++ if (viewers instanceof LazyChatAudienceSet lazyAudienceSet && lazyAudienceSet.isLazy()) { ++ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); ++ for (final ServerPlayer viewer : this.server.getPlayerList().getPlayers()) { ++ final Player bukkit = viewer.getBukkitEntity(); ++ bukkit.sendMessage(player, renderer.render(player, displayName, message, bukkit), 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); ++ for (final Audience viewer : viewers) { ++ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), 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 AsyncChatEvent createAsync(final ChatRenderer renderer, final Set viewers, final Component message) { ++ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), 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 ChatEvent createSync(final ChatRenderer renderer, final Set viewers, final Component message) { ++ return new ChatEvent(this.player.getBukkitEntity(), viewers, renderer, message, this.originalMessage); + } + + private static String legacyDisplayName(final CraftPlayer player) { @@ -332,7 +346,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.adventure; + -+import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.ServerPlayer; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.entity.CraftPlayer; + @@ -344,7 +358,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return getLegacy(player.getHandle()); + } + -+ public static String getLegacy(final EntityPlayer player) { ++ public static String getLegacy(final ServerPlayer player) { + final String legacy = player.displayName; + if (legacy != null) { + return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); @@ -360,6 +374,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.adventure; + ++import java.util.HashSet; ++import java.util.Set; +import net.kyori.adventure.audience.Audience; +import net.minecraft.server.MinecraftServer; +import org.bukkit.Bukkit; @@ -367,13 +383,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import org.bukkit.craftbukkit.util.LazyPlayerSet; +import org.bukkit.entity.Player; + -+import java.util.HashSet; -+import java.util.Set; -+ +final class LazyChatAudienceSet extends LazyHashSet { ++ private final MinecraftServer server; ++ ++ public LazyChatAudienceSet(final MinecraftServer server) { ++ this.server = server; ++ } ++ + @Override + protected Set makeReference() { -+ final Set playerSet = LazyPlayerSet.makePlayerSet(MinecraftServer.getServer()); ++ final Set playerSet = LazyPlayerSet.makePlayerSet(this.server); + final HashSet audiences = new HashSet<>(playerSet); + audiences.add(Bukkit.getConsoleSender()); + return audiences; @@ -397,13 +416,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.nbt.TagParser; + +final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer { + public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer(); -+ private static final Codec SNBT_CODEC = Codec.of(MojangsonParser::parse, NBTBase::toString); ++ private static final Codec SNBT_CODEC = Codec.of(TagParser::parseTag, Tag::toString); + + static final String ITEM_TYPE = "id"; + static final String ITEM_COUNT = "Count"; @@ -420,11 +439,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ final CompoundTag contents = SNBT_CODEC.decode(raw); ++ final CompoundTag tag = contents.getCompound(ITEM_TAG); + return HoverEvent.ShowItem.of( + Key.key(contents.getString(ITEM_TYPE)), -+ contents.hasKey(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, ++ contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1, + tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC) + ); + } catch (final CommandSyntaxException ex) { @@ -436,7 +455,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ final CompoundTag contents = SNBT_CODEC.decode(raw); + return HoverEvent.ShowEntity.of( + Key.key(contents.getString(ENTITY_TYPE)), + UUID.fromString(contents.getString(ENTITY_ID)), @@ -449,12 +468,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @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()); ++ final CompoundTag tag = new CompoundTag(); ++ tag.putString(ITEM_TYPE, input.item().asString()); ++ tag.putByte(ITEM_COUNT, (byte) input.count()); + if (input.nbt() != null) { + try { -+ tag.set(ITEM_TAG, input.nbt().get(SNBT_CODEC)); ++ tag.put(ITEM_TAG, input.nbt().get(SNBT_CODEC)); + } catch (final CommandSyntaxException ex) { + throw new IOException(ex); + } @@ -464,11 +483,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @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()); ++ final CompoundTag tag = new CompoundTag(); ++ tag.putString(ENTITY_ID, input.id().toString()); ++ tag.putString(ENTITY_TYPE, input.type().asString()); + if (input.name() != null) { -+ tag.setString(ENTITY_NAME, componentCodec.encode(input.name())); ++ tag.putString(ENTITY_NAME, componentCodec.encode(input.name())); + } + return Component.text(SNBT_CODEC.encode(tag)); + } @@ -503,16 +522,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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.ChatFormatting; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.TagParser; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.world.BossEvent; +import net.minecraft.world.item.ItemStack; +import org.bukkit.ChatColor; +import org.checkerframework.checker.nullness.qual.NonNull; @@ -523,7 +540,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 @NonNull String translated = net.minecraft.locale.Language.getInstance().getOrDefault(translatable.key()); + + final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); + final List args = translatable.args(); @@ -570,18 +587,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE) + .downsampleColors() + .build(); -+ private static final Codec NBT_CODEC = new Codec() { ++ private static final Codec NBT_CODEC = new Codec() { + @Override -+ public @NonNull NBTTagCompound decode(final @NonNull String encoded) throws IOException { ++ public @NonNull CompoundTag decode(final @NonNull String encoded) throws IOException { + try { -+ return MojangsonParser.parse(encoded); ++ return TagParser.parseTag(encoded); + } catch (final CommandSyntaxException e) { + throw new IOException(e); + } + } + + @Override -+ public @NonNull String encode(final @NonNull NBTTagCompound decoded) { ++ public @NonNull String encode(final @NonNull CompoundTag decoded) { + return decoded.toString(); + } + }; @@ -592,26 +609,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // Key + -+ public static MinecraftKey asVanilla(final Key key) { -+ return new MinecraftKey(key.namespace(), key.value()); ++ public static ResourceLocation asVanilla(final Key key) { ++ return new ResourceLocation(key.namespace(), key.value()); + } + -+ public static MinecraftKey asVanillaNullable(final Key key) { ++ public static ResourceLocation asVanillaNullable(final Key key) { + if (key == null) { + return null; + } -+ return new MinecraftKey(key.namespace(), key.value()); ++ return new ResourceLocation(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 Component asAdventure(final net.minecraft.network.chat.Component component) { ++ return component == null ? Component.empty() : GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(component), Component.class); + } + -+ public static ArrayList asAdventure(final List vanillas) { ++ public static ArrayList asAdventure(final List vanillas) { + final ArrayList adventures = new ArrayList<>(vanillas.size()); -+ for (final IChatBaseComponent vanilla : vanillas) { ++ for (final net.minecraft.network.chat.Component vanilla : vanillas) { + adventures.add(asAdventure(vanilla)); + } + return adventures; @@ -633,13 +650,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return jsons; + } + -+ public static IChatBaseComponent asVanilla(final Component component) { ++ public static net.minecraft.network.chat.Component asVanilla(final Component component) { + if (true) return new AdventureComponent(component); -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(GSON.serializer().toJsonTree(component)); ++ return net.minecraft.network.chat.Component.Serializer.fromJson(GSON.serializer().toJsonTree(component)); + } + -+ public static List asVanilla(final List adventures) { -+ final List vanillas = new ArrayList<>(adventures.size()); ++ public static List asVanilla(final List adventures) { ++ final List vanillas = new ArrayList<>(adventures.size()); + for (final Component adventure : adventures) { + vanillas.add(asVanilla(adventure)); + } @@ -658,11 +675,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ); + } + -+ public static String asJsonString(final IChatBaseComponent component, final Locale locale) { ++ public static String asJsonString(final net.minecraft.network.chat.Component component, final Locale locale) { + if (component instanceof AdventureComponent) { + return asJsonString(((AdventureComponent) component).wrapped, locale); + } -+ return IChatBaseComponent.ChatSerializer.componentToJson(component); ++ return net.minecraft.network.chat.Component.Serializer.toJson(component); + } + + // thank you for being worse than wet socks, Bukkit @@ -672,69 +689,69 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // BossBar + -+ public static BossBattle.BarColor asVanilla(final BossBar.Color color) { ++ public static BossEvent.BossBarColor asVanilla(final BossBar.Color color) { + if (color == BossBar.Color.PINK) { -+ return BossBattle.BarColor.PINK; ++ return BossEvent.BossBarColor.PINK; + } else if (color == BossBar.Color.BLUE) { -+ return BossBattle.BarColor.BLUE; ++ return BossEvent.BossBarColor.BLUE; + } else if (color == BossBar.Color.RED) { -+ return BossBattle.BarColor.RED; ++ return BossEvent.BossBarColor.RED; + } else if (color == BossBar.Color.GREEN) { -+ return BossBattle.BarColor.GREEN; ++ return BossEvent.BossBarColor.GREEN; + } else if (color == BossBar.Color.YELLOW) { -+ return BossBattle.BarColor.YELLOW; ++ return BossEvent.BossBarColor.YELLOW; + } else if (color == BossBar.Color.PURPLE) { -+ return BossBattle.BarColor.PURPLE; ++ return BossEvent.BossBarColor.PURPLE; + } else if (color == BossBar.Color.WHITE) { -+ return BossBattle.BarColor.WHITE; ++ return BossEvent.BossBarColor.WHITE; + } + throw new IllegalArgumentException(color.name()); + } + -+ public static BossBar.Color asAdventure(final BossBattle.BarColor color) { -+ if(color == BossBattle.BarColor.PINK) { ++ public static BossBar.Color asAdventure(final BossEvent.BossBarColor color) { ++ if(color == BossEvent.BossBarColor.PINK) { + return BossBar.Color.PINK; -+ } else if(color == BossBattle.BarColor.BLUE) { ++ } else if(color == BossEvent.BossBarColor.BLUE) { + return BossBar.Color.BLUE; -+ } else if(color == BossBattle.BarColor.RED) { ++ } else if(color == BossEvent.BossBarColor.RED) { + return BossBar.Color.RED; -+ } else if(color == BossBattle.BarColor.GREEN) { ++ } else if(color == BossEvent.BossBarColor.GREEN) { + return BossBar.Color.GREEN; -+ } else if(color == BossBattle.BarColor.YELLOW) { ++ } else if(color == BossEvent.BossBarColor.YELLOW) { + return BossBar.Color.YELLOW; -+ } else if(color == BossBattle.BarColor.PURPLE) { ++ } else if(color == BossEvent.BossBarColor.PURPLE) { + return BossBar.Color.PURPLE; -+ } else if(color == BossBattle.BarColor.WHITE) { ++ } else if(color == BossEvent.BossBarColor.WHITE) { + return BossBar.Color.WHITE; + } + throw new IllegalArgumentException(color.name()); + } + -+ public static BossBattle.BarStyle asVanilla(final BossBar.Overlay overlay) { ++ public static BossEvent.BossBarOverlay asVanilla(final BossBar.Overlay overlay) { + if (overlay == BossBar.Overlay.PROGRESS) { -+ return BossBattle.BarStyle.PROGRESS; ++ return BossEvent.BossBarOverlay.PROGRESS; + } else if (overlay == BossBar.Overlay.NOTCHED_6) { -+ return BossBattle.BarStyle.NOTCHED_6; ++ return BossEvent.BossBarOverlay.NOTCHED_6; + } else if (overlay == BossBar.Overlay.NOTCHED_10) { -+ return BossBattle.BarStyle.NOTCHED_10; ++ return BossEvent.BossBarOverlay.NOTCHED_10; + } else if (overlay == BossBar.Overlay.NOTCHED_12) { -+ return BossBattle.BarStyle.NOTCHED_12; ++ return BossEvent.BossBarOverlay.NOTCHED_12; + } else if (overlay == BossBar.Overlay.NOTCHED_20) { -+ return BossBattle.BarStyle.NOTCHED_20; ++ return BossEvent.BossBarOverlay.NOTCHED_20; + } + throw new IllegalArgumentException(overlay.name()); + } + -+ public static BossBar.Overlay asAdventure(final BossBattle.BarStyle overlay) { -+ if (overlay == BossBattle.BarStyle.PROGRESS) { ++ public static BossBar.Overlay asAdventure(final BossEvent.BossBarOverlay overlay) { ++ if (overlay == BossEvent.BossBarOverlay.PROGRESS) { + return BossBar.Overlay.PROGRESS; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_6) { ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_6) { + return BossBar.Overlay.NOTCHED_6; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_10) { ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_10) { + return BossBar.Overlay.NOTCHED_10; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_12) { ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_12) { + return BossBar.Overlay.NOTCHED_12; -+ } else if (overlay == BossBattle.BarStyle.NOTCHED_20) { ++ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_20) { + return BossBar.Overlay.NOTCHED_20; + } + throw new IllegalArgumentException(overlay.name()); @@ -752,45 +769,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + 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(); ++ final CompoundTag tag = item.getOrCreateTag(); ++ tag.putString("title", asJsonString(book.title(), locale)); ++ tag.putString("author", asJsonString(book.author(), locale)); ++ final ListTag pages = new ListTag(); + for (final Component page : book.pages()) { -+ pages.add(NBTTagString.create(asJsonString(page, locale))); ++ pages.add(StringTag.valueOf(asJsonString(page, locale))); + } -+ tag.set("pages", pages); ++ tag.put("pages", pages); + return item; + } + + // Sounds + -+ public static SoundCategory asVanilla(final Sound.Source source) { ++ public static SoundSource asVanilla(final Sound.Source source) { + if (source == Sound.Source.MASTER) { -+ return SoundCategory.MASTER; ++ return SoundSource.MASTER; + } else if (source == Sound.Source.MUSIC) { -+ return SoundCategory.MUSIC; ++ return SoundSource.MUSIC; + } else if (source == Sound.Source.RECORD) { -+ return SoundCategory.RECORDS; ++ return SoundSource.RECORDS; + } else if (source == Sound.Source.WEATHER) { -+ return SoundCategory.WEATHER; ++ return SoundSource.WEATHER; + } else if (source == Sound.Source.BLOCK) { -+ return SoundCategory.BLOCKS; ++ return SoundSource.BLOCKS; + } else if (source == Sound.Source.HOSTILE) { -+ return SoundCategory.HOSTILE; ++ return SoundSource.HOSTILE; + } else if (source == Sound.Source.NEUTRAL) { -+ return SoundCategory.NEUTRAL; ++ return SoundSource.NEUTRAL; + } else if (source == Sound.Source.PLAYER) { -+ return SoundCategory.PLAYERS; ++ return SoundSource.PLAYERS; + } else if (source == Sound.Source.AMBIENT) { -+ return SoundCategory.AMBIENT; ++ return SoundSource.AMBIENT; + } else if (source == Sound.Source.VOICE) { -+ return SoundCategory.VOICE; ++ return SoundSource.VOICE; + } + throw new IllegalArgumentException(source.name()); + } + -+ public static @Nullable SoundCategory asVanillaNullable(final Sound.@Nullable Source source) { ++ public static @Nullable SoundSource asVanillaNullable(final Sound.@Nullable Source source) { + if (source == null) { + return null; + } @@ -799,7 +816,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // NBT + -+ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable NBTTagCompound tag) { ++ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable CompoundTag tag) { + if (tag == null) { + return null; + } @@ -812,15 +829,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // Colors + -+ public static @NonNull TextColor asAdventure(EnumChatFormat minecraftColor) { -+ if (minecraftColor.e() == null) { ++ public static @NonNull TextColor asAdventure(ChatFormatting minecraftColor) { ++ if (minecraftColor.getColor() == null) { + throw new IllegalArgumentException("Not a valid color"); + } -+ return TextColor.color(minecraftColor.e()); ++ return TextColor.color(minecraftColor.getColor()); + } + -+ public static @Nullable EnumChatFormat asVanilla(TextColor color) { -+ return EnumChatFormat.getByHexValue(color.value()); ++ public static @Nullable ChatFormatting asVanilla(TextColor color) { ++ return ChatFormatting.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 @@ -833,41 +850,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import java.util.Set; +import java.util.function.Consumer; ++import java.util.function.Function; ++ +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; -+import net.minecraft.network.protocol.game.PacketPlayOutBoss; ++import net.minecraft.network.protocol.game.ClientboundBossEventPacket; ++import net.minecraft.world.BossEvent; +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class VanillaBossBarListener implements BossBar.Listener { -+ private final Consumer action; ++ private final Consumer> action; + -+ public VanillaBossBarListener(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); ++ this.action.accept(ClientboundBossEventPacket::createUpdateNamePacket); + } + + @Override + public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PCT); ++ this.action.accept(ClientboundBossEventPacket::createUpdateProgressPacket); + } + + @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); ++ this.action.accept(ClientboundBossEventPacket::createUpdateStylePacket); + } + + @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); ++ this.action.accept(ClientboundBossEventPacket::createUpdateStylePacket); + } + + @Override + public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set flagsAdded, final @NonNull Set flagsRemoved) { -+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PROPERTIES); ++ this.action.accept(ClientboundBossEventPacket::createUpdatePropertiesPacket); + } +} diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java @@ -880,20 +900,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.ComponentSerializer; -+import net.minecraft.network.chat.IChatBaseComponent; + -+final class WrapperAwareSerializer implements ComponentSerializer { ++final class WrapperAwareSerializer implements ComponentSerializer { + @Override -+ public Component deserialize(final IChatBaseComponent input) { ++ public Component deserialize(final net.minecraft.network.chat.Component input) { + if (input instanceof AdventureComponent) { + return ((AdventureComponent) input).wrapped; + } -+ return PaperAdventure.GSON.serializer().fromJson(IChatBaseComponent.ChatSerializer.toJsonTree(input), Component.class); ++ return PaperAdventure.GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(input), Component.class); + } + + @Override -+ public IChatBaseComponent serialize(final Component component) { -+ return IChatBaseComponent.ChatSerializer.fromJsonTree(PaperAdventure.GSON.serializer().toJsonTree(component)); ++ public net.minecraft.network.chat.Component serialize(final Component component) { ++ return net.minecraft.network.chat.Component.Serializer.fromJson(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 @@ -906,23 +925,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.adventure.VanillaBossBarListener; -+import net.minecraft.server.level.BossBattleServer; ++import net.minecraft.server.level.ServerBossEvent; +import org.bukkit.craftbukkit.entity.CraftPlayer; + +public abstract class HackyBossBarPlatformBridge { -+ public BossBattleServer vanilla$bar; ++ public ServerBossEvent 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( ++ this.vanilla$bar = new ServerBossEvent( + 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.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::broadcast); + $this.addListener(this.vanilla$listener); + } + this.vanilla$bar.addPlayer(player.getHandle()); @@ -938,26 +957,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } +} -diff --git a/src/main/java/net/minecraft/EnumChatFormat.java b/src/main/java/net/minecraft/EnumChatFormat.java +diff --git a/src/main/java/net/minecraft/ChatFormatting.java b/src/main/java/net/minecraft/ChatFormatting.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)); +--- a/src/main/java/net/minecraft/ChatFormatting.java ++++ b/src/main/java/net/minecraft/ChatFormatting.java +@@ -0,0 +0,0 @@ public enum ChatFormatting { + return name == null ? null : FORMATTING_BY_NAME.get(cleanName(name)); } + // Paper start -+ @Nullable public static EnumChatFormat getByHexValue(int i) { -+ for (EnumChatFormat value : values()) { -+ if (value.getHexValue() != null && value.getHexValue() == i) { ++ @Nullable public static ChatFormatting getByHexValue(int i) { ++ for (ChatFormatting value : values()) { ++ if (value.getColor() != null && value.getColor() == i) { + return value; + } + } @@ -967,65 +978,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 + public static ChatFormatting getById(int colorIndex) { + if (colorIndex < 0) { +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.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; +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -0,0 +0,0 @@ import io.netty.handler.codec.EncoderException; import io.netty.util.ByteProcessor; + import it.unimi.dsi.fastutil.ints.IntArrayList; + import it.unimi.dsi.fastutil.ints.IntList; +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; +@@ -0,0 +0,0 @@ public class FriendlyByteBuf extends ByteBuf { + private static final int MAX_VARLONG_SIZE = 10; + private static final int DEFAULT_NBT_QUOTA = 2097152; + private final ByteBuf source; + public java.util.Locale adventure$locale; // Paper + public static final short MAX_STRING_LENGTH = 32767; + public static final int MAX_COMPONENT_STRING_LENGTH = 262144; - public PacketDataSerializer(ByteBuf bytebuf) { - this.a = bytebuf; -@@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - return IChatBaseComponent.ChatSerializer.a(this.e(262144)); +@@ -0,0 +0,0 @@ public class FriendlyByteBuf extends ByteBuf { + return Component.Serializer.fromJson(this.readUtf(262144)); } + // Paper start -+ public PacketDataSerializer writeComponent(final net.kyori.adventure.text.Component component) { ++ public FriendlyByteBuf 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); + public FriendlyByteBuf writeComponent(Component text) { +- return this.writeUtf(Component.Serializer.toJson(text), 262144); + //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment -+ return this.writeUtf(PaperAdventure.asJsonString(ichatbasecomponent, this.adventure$locale), 262144); // Paper ++ return this.writeUtf(PaperAdventure.asJsonString(text, 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); - + public > T readEnum(Class enumClass) { 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 @@ -1036,277 +1027,248 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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; + import net.minecraft.network.protocol.PacketFlow; @@ -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 + FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf); + friendlyByteBuf.writeVarInt(integer); ++ friendlyByteBuf.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 + try { + int i = friendlyByteBuf.writerIndex(); +diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.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 +--- a/src/main/java/net/minecraft/network/chat/Component.java ++++ b/src/main/java/net/minecraft/network/chat/Component.java @@ -0,0 +0,0 @@ package net.minecraft.network.chat; + import com.google.common.collect.Lists; +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 { GsonBuilder gsonbuilder = new GsonBuilder(); gsonbuilder.disableHtmlEscaping(); + gsonbuilder.registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()); // Paper - gsonbuilder.registerTypeHierarchyAdapter(IChatBaseComponent.class, new IChatBaseComponent.ChatSerializer()); - gsonbuilder.registerTypeHierarchyAdapter(ChatModifier.class, new ChatModifier.ChatModifierSerializer()); - gsonbuilder.registerTypeAdapterFactory(new ChatTypeAdapterFactory()); -@@ -0,0 +0,0 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { } - public JsonElement serialize(IChatBaseComponent ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { + public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) { + if (ichatbasecomponent instanceof AdventureComponent) return jsonserializationcontext.serialize(ichatbasecomponent); // Paper JsonObject jsonobject = new JsonObject(); - if (!ichatbasecomponent.getChatModifier().g()) { -@@ -0,0 +0,0 @@ public interface IChatBaseComponent extends Message, IChatFormatted, Iterable { + public class ClientboundChatPacket implements Packet { - private IChatBaseComponent a; + private final Component message; + 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 { + private final ChatType type; + private final UUID sender; +@@ -0,0 +0,0 @@ public class ClientboundChatPacket implements Packet { @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { + public void write(FriendlyByteBuf buf) { + // Paper start + if (this.adventure$message != null) { -+ packetdataserializer.writeComponent(this.adventure$message); ++ buf.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 + if (this.components != null) { + buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components)); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.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 { + private final Component text; ++ public net.kyori.adventure.text.Component adventure$text; // Paper + + public ClientboundSetActionBarTextPacket(Component message) { + this.text = message; +@@ -0,0 +0,0 @@ public class ClientboundSetActionBarTextPacket implements Packet { + private final Component text; ++ public net.kyori.adventure.text.Component adventure$text; // Paper + + public ClientboundSetSubtitleTextPacket(Component subtitle) { + this.text = subtitle; +@@ -0,0 +0,0 @@ public class ClientboundSetSubtitleTextPacket implements Packet { + private final Component text; ++ public net.kyori.adventure.text.Component adventure$text; // Paper + + public ClientboundSetTitleTextPacket(Component title) { + this.text = title; +@@ -0,0 +0,0 @@ public class ClientboundSetTitleTextPacket implements Packet { + public final Component header; + public final Component footer; + // Paper start + public net.kyori.adventure.text.Component adventure$header; + public net.kyori.adventure.text.Component adventure$footer; + // Paper end - public PacketPlayOutPlayerListHeaderFooter() {} - -@@ -0,0 +0,0 @@ public class PacketPlayOutPlayerListHeaderFooter implements Packet { - - private PacketPlayOutTitle.EnumTitleAction a; - private IChatBaseComponent b; -+ public net.kyori.adventure.text.Component adventure$text; // Paper - private int c; - private int d; - private int e; -@@ -0,0 +0,0 @@ public class PacketPlayOutTitle implements Packet { - public void b(PacketDataSerializer packetdataserializer) throws IOException { - packetdataserializer.a((Enum) this.a); - if (this.a == PacketPlayOutTitle.EnumTitleAction.TITLE || this.a == PacketPlayOutTitle.EnumTitleAction.SUBTITLE || this.a == PacketPlayOutTitle.EnumTitleAction.ACTIONBAR) { -+ // Paper start -+ if (this.adventure$text != null) { -+ packetdataserializer.writeComponent(this.adventure$text); -+ } else -+ // Paper end - packetdataserializer.a(this.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.world.item.enchantment.EnchantmentManager; - import net.minecraft.world.level.block.BlockChest; - import net.minecraft.world.level.dimension.DimensionManager; +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ import net.minecraft.world.scores.Score; import net.minecraft.world.scores.Scoreboard; + import net.minecraft.world.scores.Team; + import net.minecraft.world.scores.criteria.ObjectiveCriteria; +import io.papermc.paper.adventure.PaperAdventure; // Paper import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { // CraftBukkit start public String displayName; + public net.kyori.adventure.text.Component adventure$displayName; // Paper - public IChatBaseComponent listName; + public Component listName; public org.bukkit.Location compassTarget; public int newExp = 0; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { // CraftBukkit start - this.displayName = this.getName(); -+ this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getName()); // Paper - this.canPickUpLoot = true; + this.displayName = this.getScoreboardName(); ++ this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper + this.bukkitPickUpLoot = true; this.maxHealthCache = this.getMaxHealth(); } -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { - IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); + Component defaultMessage = this.getCombatTracker().getDeathMessage(); - String deathmessage = defaultMessage.getString(); - org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory); + org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure // SPIGOT-943 - only call if they have an inventory open - if (this.activeContainer != this.defaultContainer) { - this.closeInventory(); + if (this.containerMenu != this.inventoryMenu) { + this.closeContainer(); } - String deathMessage = event.getDeathMessage(); + net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure - if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override? -- IChatBaseComponent ichatbasecomponent; +- Component 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 ++ Component ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure - this.playerConnection.a((Packet) (new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent)), (future) -> { + this.connection.send((Packet) (new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), 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 { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { } public String locale = "en_us"; // CraftBukkit - add, lowercase + public java.util.Locale adventure$locale = java.util.Locale.US; // Paper - public void a(PacketPlayInSettings packetplayinsettings) { + public void updateOptions(ServerboundClientInformationPacket packet) { // CraftBukkit start - if (getMainHand() != packetplayinsettings.getMainHand()) { -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { + if (getMainArm() != packet.getMainHand()) { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { this.server.server.getPluginManager().callEvent(event); } - this.locale = packetplayinsettings.locale; + this.locale = packet.language; + // 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); ++ this.connection.connection.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale); + // Paper end - this.clientViewDistance = packetplayinsettings.viewDistance; + this.clientViewDistance = packet.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 + this.chatVisibility = packet.getChatVisibility(); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -1314,16 +1276,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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()); + import java.util.concurrent.atomic.AtomicInteger; + import net.minecraft.world.inventory.AbstractContainerMenu; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + return this.server.isSingleplayerOwner(this.player.getGameProfile()); } - // CraftBukkit start - @Deprecated -- public void disconnect(IChatBaseComponent ichatbasecomponent) { -- disconnect(CraftChatMessage.fromComponent(ichatbasecomponent)); +- public void disconnect(Component reason) { +- this.disconnect(CraftChatMessage.fromComponent(reason)); + public void disconnect(String s) { + // Paper start + this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s)); @@ -1331,7 +1293,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - // CraftBukkit end - public void disconnect(String s) { -+ public void disconnect(final IChatBaseComponent reason) { ++ public void disconnect(final Component reason) { + this.disconnect(PaperAdventure.asAdventure(reason)); + } + @@ -1341,85 +1303,140 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.processedDisconnect) { return; } -- String leaveMessage = EnumChatFormat.YELLOW + this.player.getName() + " left the game."; +- String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " 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 +- PlayerKickEvent event = new PlayerKickEvent(this.cserver.getPlayer(this.player), s, leaveMessage); ++ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), reason, leaveMessage); // Paper - Adventure - if (this.server.getServer().isRunning()) { - this.server.getPluginManager().callEvent(event); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { + if (this.cserver.getServer().isRunning()) { + this.cserver.getPluginManager().callEvent(event); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser 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 +- final Component ichatbasecomponent = CraftChatMessage.fromString(s, true)[0]; ++ final Component 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.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser */ - this.player.p(); -- String quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); + this.player.disconnect(); +- String quitMessage = this.server.getPlayerList().disconnect(this.player); - if ((quitMessage != null) && (quitMessage.length() > 0)) { -- this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); +- this.server.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); + // Paper start - Adventure -+ net.kyori.adventure.text.Component quitMessage = this.minecraftServer.getPlayerList().disconnect(this.player); ++ net.kyori.adventure.text.Component quitMessage = this.server.getPlayerList().disconnect(this.player); + if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { -+ this.minecraftServer.getPlayerList().sendMessage(PaperAdventure.asVanilla(quitMessage)); ++ this.server.getPlayerList().broadcastMessage(PaperAdventure.asVanilla(quitMessage), ChatType.SYSTEM, Util.NIL_UUID); + // Paper end } // CraftBukkit end - ITextFilter itextfilter = this.player.Q(); -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { + this.player.getTextFilter().leave(); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { + } else if (this.player.getChatVisibility() == ChatVisiblity.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); ++ final ChatProcessor cp = new ChatProcessor(this.server, this.player, s, async); + cp.process(); -+ // Paper end ++ // 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 { + Player player = this.getCraftPlayer(); + AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(this.server)); + this.cserver.getPluginManager().callEvent(event); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser 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 + Player player = this.cserver.getPlayer(this.player); + int x = packetplayinupdatesign.getPos().getX(); + int y = packetplayinupdatesign.getPos().getY(); + int z = packetplayinupdatesign.getPos().getZ(); +- String[] lines = new String[4]; + 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))); +- TextFilter.FilteredText itextfilter_a = (TextFilter.FilteredText) list.get(i); +- + if (this.player.isTextFilteringEnabled()) { +- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(itextfilter_a.getFiltered())).getString()); ++ lines.add(net.kyori.adventure.text.Component.text(list.get(i).getFiltered())); + } else { +- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(itextfilter_a.getRaw())).getString()); ++ lines.add(net.kyori.adventure.text.Component.text(list.get(i).getRaw())); + } } -- 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); + SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.cserver.getPlayer(this.player), lines); + this.cserver.getPluginManager().callEvent(event); if (!event.isCancelled()) { -- System.arraycopy(org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()), 0, tileentitysign.lines, 0, 4); +- Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines()); +- for (int i = 0; i < components.length; i++) { +- tileentitysign.setMessage(i, components[i]); + for (int i = 0; i < 4; i++) { -+ tileentitysign.a(i, PaperAdventure.asVanilla(event.line(i))); -+ } ++ tileentitysign.setMessage(i, PaperAdventure.asVanilla(event.line(i))); + } + // Paper end tileentitysign.isEditable = false; - } + } // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ import net.minecraft.world.entity.player.Player; + import org.apache.commons.lang3.Validate; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++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 ServerLoginPacketListenerImpl implements ServerLoginPacketListener + 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 ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable); + if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) { +- ServerLoginPacketListenerImpl.this.disconnect(event.getKickMessage()); ++ ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure + return; + } + } else { + if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { +- ServerLoginPacketListenerImpl.this.disconnect(asyncEvent.getKickMessage()); ++ ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure + return; + } + } +diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + CraftIconCache icon = server.server.getServerIcon(); + + ServerListPingEvent() { +- super(((InetSocketAddress) ServerStatusPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(), ServerStatusPacketListenerImpl.this.server.getMotd(), ServerStatusPacketListenerImpl.this.server.getPlayerList().getMaxPlayers()); ++ super(((InetSocketAddress) ServerStatusPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(), ServerStatusPacketListenerImpl.this.server.server.getMotd(), ServerStatusPacketListenerImpl.this.server.getPlayerList().getMaxPlayers()); // Paper - Adventure + } + + @Override 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 @@ -1438,26 +1455,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start +import io.papermc.paper.adventure.PaperAdventure; // Paper import com.google.common.base.Predicate; - import com.google.common.collect.Iterables; - + import java.util.stream.Collectors; + import net.minecraft.server.dedicated.DedicatedServer; @@ -0,0 +0,0 @@ public abstract class PlayerList { } // CraftBukkit start - chatmessage.a(EnumChatFormat.YELLOW); + chatmessage.withStyle(ChatFormatting.YELLOW); - String joinMessage = CraftChatMessage.fromComponent(chatmessage); -+ IChatBaseComponent joinMessage = chatmessage; // Paper - Adventure ++ Component joinMessage = chatmessage; // Paper - Adventure - playerconnection.a(entityplayer.locX(), entityplayer.locY(), entityplayer.locZ(), entityplayer.yaw, entityplayer.pitch); - this.players.add(entityplayer); + playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot()); + this.players.add(player); @@ -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); +- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(this.cserver.getPlayer(player), joinMessage); ++ PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(this.cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + this.cserver.getPluginManager().callEvent(playerJoinEvent); - if (!entityplayer.playerConnection.networkManager.isConnected()) { + if (!player.connection.connection.isConnected()) { return; } @@ -1465,12 +1482,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); +- for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) { +- this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID)); - } + 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 ++ this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure } // CraftBukkit end @@ -1478,22 +1495,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } -- public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - return string -+ public net.kyori.adventure.text.Component disconnect(EntityPlayer entityplayer) { // Paper - return Component - WorldServer worldserver = entityplayer.getWorldServer(); +- public String disconnect(ServerPlayer entityplayer) { // CraftBukkit - return string ++ public net.kyori.adventure.text.Component disconnect(ServerPlayer entityplayer) { // Paper - return Component + ServerLevel worldserver = entityplayer.getLevel(); - entityplayer.a(StatisticList.LEAVE_GAME); + entityplayer.awardStat(Stats.LEAVE_GAME); @@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.closeInventory(); + entityplayer.closeContainer(); } -- 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); +- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.getScoreboardName() + " left the game"); ++ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.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.getScoreboardName()))); + this.cserver.getPluginManager().callEvent(playerQuitEvent); entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); @@ -0,0 +0,0 @@ public abstract class PlayerList { - cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); + this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity()); // CraftBukkit end - return playerQuitEvent.getQuitMessage(); // CraftBukkit @@ -1507,12 +1524,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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"); + } else if (!this.isWhiteListed(gameprofile)) { + chatmessage = new TranslatableComponent("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); + } else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) { + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); @@ -0,0 +0,0 @@ public abstract class PlayerList { } @@ -1521,14 +1538,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - 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)) { + // return this.players.size() >= this.maxPlayers && !this.d(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null; + if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(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); + this.cserver.getPluginManager().callEvent(event); if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { - loginlistener.disconnect(event.getKickMessage()); + loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure @@ -1536,137 +1553,37 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } return entity; @@ -0,0 +0,0 @@ public abstract class PlayerList { - public void shutdown() { + public void removeAll() { // 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 + for (ServerPlayer player : this.players) { +- player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message ++ player.connection.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 +diff --git a/src/main/java/net/minecraft/world/BossEvent.java b/src/main/java/net/minecraft/world/BossEvent.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/BossBattle.java -+++ b/src/main/java/net/minecraft/world/BossBattle.java +--- a/src/main/java/net/minecraft/world/BossEvent.java ++++ b/src/main/java/net/minecraft/world/BossEvent.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; + import net.minecraft.ChatFormatting; + import net.minecraft.network.chat.Component; +@@ -0,0 +0,0 @@ public abstract class BossEvent { + protected boolean darkenScreen; + protected boolean playBossMusic; + protected boolean createWorldFog; + 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 + public BossEvent(UUID uuid, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay style) { + this.id = uuid; +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.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 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java @@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -1674,16 +1591,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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) { + import org.bukkit.Bukkit; +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { - 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 + for (org.bukkit.map.MapCursor cursor : render.cursors) { + if (cursor.isVisible()) { +- icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); ++ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure + } } - } - + collection = icons; 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 @@ -1694,14 +1611,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override + @Deprecated // Paper start public int broadcastMessage(String message) { -- return broadcast(message, BROADCAST_CHANNEL_USERS); -+ return this.broadcast(message, BROADCAST_CHANNEL_USERS); + return this.broadcast(message, BROADCAST_CHANNEL_USERS); + // Paper end } - public Player getPlayer(final EntityPlayer entity) { + public Player getPlayer(final ServerPlayer entity) { @@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return configuration.getInt("settings.spawn-radius", -1); + return this.configuration.getInt("settings.spawn-radius", -1); } + // Paper start @@ -1714,7 +1630,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + @Deprecated // Paper public String getShutdownMessage() { - return configuration.getString("settings.shutdown-message"); + return this.configuration.getString("settings.shutdown-message"); } @@ -0,0 +0,0 @@ public final class CraftServer implements Server { } @@ -1735,7 +1651,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public int broadcast(net.kyori.adventure.text.Component message, String permission) { + // Paper end Set recipients = new HashSet<>(); - for (Permissible permissible : getPluginManager().getPermissionSubscriptions(permission)) { + for (Permissible permissible : this.getPluginManager().getPermissionSubscriptions(permission)) { if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { @@ -0,0 +0,0 @@ public final class CraftServer implements Server { } @@ -1743,7 +1659,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); + BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure - getPluginManager().callEvent(broadcastMessageEvent); + this.getPluginManager().callEvent(broadcastMessageEvent); if (broadcastMessageEvent.isCancelled()) { return 0; @@ -1799,18 +1715,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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) + return Thread.currentThread().equals(console.serverThread) || this.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())); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.TextComponent(console.getMotd())); + } + // Paper end @Override public String getMotd() { - return console.getMotd(); + return this.console.getMotd(); @@ -0,0 +0,0 @@ public final class CraftServer implements Server { return null; } @@ -1848,15 +1764,15 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/m 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; +@@ -0,0 +0,0 @@ public class CraftBeacon extends CraftBlockEntityState implem + this.getSnapshot().secondaryPower = (effect != null) ? MobEffect.byId(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; ++ final BeaconBlockEntity be = this.getSnapshot(); ++ return be.name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.name) : null; + } + + @Override @@ -1867,13 +1783,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public String getCustomName() { - TileEntityBeacon beacon = this.getSnapshot(); + BeaconBlockEntity 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); +@@ -0,0 +0,0 @@ public abstract class CraftContainer extends + this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); } + // Paper start @@ -1896,14 +1812,14 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.jav 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 { + public class CraftSign extends CraftBlockEntityState implements Sign { // Lazily initialized only if requested: - private String[] originalLines = null; @@ -1932,26 +1848,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end public CraftSign(final Block block) { - super(block, TileEntitySign.class); -@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockEntityState implements + super(block, SignBlockEntity.class); +@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockEntityState implements super(material, te); } + // Paper start @Override - public String[] getLines() { -- if (lines == null) { +- if (this.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]; +- SignBlockEntity sign = this.getSnapshot(); +- this.lines = new String[sign.messages.length]; +- System.arraycopy(CraftSign.revertComponents(sign.messages), 0, lines, 0, lines.length); +- this.originalLines = new String[lines.length]; - System.arraycopy(lines, 0, originalLines, 0, originalLines.length); +- } + public java.util.List lines() { + this.loadLines(); -+ return this.lines; -+ } -+ + return this.lines; + } + + @Override + public net.kyori.adventure.text.Component line(int index) { + this.loadLines(); @@ -1967,12 +1884,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); ++ SignBlockEntity sign = this.getSnapshot(); ++ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.messages)); + originalLines = new java.util.ArrayList<>(lines); + } + // Paper end @@ -1980,30 +1895,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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]; +- return this.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.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 +@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockEntityState implements super.applyTo(sign); - if (lines != null) { + if (this.lines != null) { - for (int i = 0; i < lines.length; i++) { -- String line = (lines[i] == null) ? "" : lines[i]; -- if (line.equals(originalLines[i])) { +- String line = (this.lines[i] == null) ? "" : this.lines[i]; +- if (line.equals(this.originalLines[i])) { + // Paper start + for (int i = 0; i < this.lines.size(); ++i) { + net.kyori.adventure.text.Component component = this.lines.get(i); @@ -2011,28 +1926,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); +- sign.setMessage(i, CraftChatMessage.fromString(line)[0]); ++ sign.messages[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]; ++ public static Component[] sanitizeLines(java.util.List lines) { ++ Component[] components = new Component[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(""); ++ components[i] = new TextComponent(""); + } + } + return components; + } + // Paper end - public static IChatBaseComponent[] sanitizeLines(String[] lines) { - IChatBaseComponent[] components = new IChatBaseComponent[4]; + public static Component[] sanitizeLines(String[] lines) { + Component[] components = new Component[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 @@ -2040,7 +1955,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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(); + return this.conversationTracker.isConversing(); } + + // Paper start @@ -2056,29 +1971,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + return !this.target.isCompatibleWith(ench.target); } + // Paper start + @Override + public net.kyori.adventure.text.Component displayName(int level) { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getFullname(level)); + } + // Paper end public net.minecraft.world.item.enchantment.Enchantment getHandle() { - return target; + return this.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(); + return this.getHandle().getVehicle().getBukkitEntity(); } + // Paper start + @Override + public net.kyori.adventure.text.Component customName() { -+ final IChatBaseComponent name = this.getHandle().getCustomName(); ++ final Component name = this.getHandle().getCustomName(); + return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null; + } + @@ -2104,26 +2019,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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.connection.send(new ClientboundOpenScreenPacket(container.containerId, 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); ++ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.initMenu(container); } @@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { // Now open the window - Containers windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); + MenuType windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); - String title = inventory.getTitle(); -- player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); +- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, 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); ++ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.initMenu(container); } 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 @@ -2134,22 +2049,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public String getDisplayName() { + if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper - return getHandle().displayName; + return this.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; + this.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) { ++ for (ServerPlayer player : server.getHandle().players) { + if (player.getBukkitEntity().canSee(this)) { -+ player.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_DISPLAY_NAME, getHandle())); ++ player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, getHandle())); + } + } + } @@ -2168,40 +2083,40 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end @Override public String getPlayerListName() { - return getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(getHandle().listName); + return this.getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(this.getHandle().listName); @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } } -- private IChatBaseComponent playerListHeader; -- private IChatBaseComponent playerListFooter; +- private Component playerListHeader; +- private Component 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 +- return (this.playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader); ++ return (this.playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader); } @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 +- return (this.playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter); ++ return (this.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(); + this.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(); + this.updatePlayerListHeaderFooter(); } @Override @@ -2210,29 +2125,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - 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(); + this.updatePlayerListHeaderFooter(); + } + + private void updatePlayerListHeaderFooter() { + if (this.getHandle().connection == null) return; + +- ClientboundTabListPacket packet = new ClientboundTabListPacket((this.playerListHeader == null) ? new TextComponent("") : this.playerListHeader, (this.playerListFooter == null) ? new TextComponent("") : this.playerListFooter); ++ ClientboundTabListPacket packet = new ClientboundTabListPacket((this.playerListHeader == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader), (this.playerListFooter == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter)); + this.getHandle().connection.send(packet); } @@ -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); + this.getHandle().connection.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; ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; + if (connection != null) { + connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); + } @@ -2241,9 +2153,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public void setCompassTarget(Location loc) { - if (getHandle().playerConnection == null) return; + if (this.getHandle().connection == null) return; @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - getHandle().playerConnection.sendPacket(packet); + this.getHandle().connection.send(packet); } + // Paper start @@ -2253,7 +2165,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + @Override + public void sendSignChange(Location loc, List lines, DyeColor dyeColor) { -+ if (getHandle().playerConnection == null) { ++ if (getHandle().connection == null) { + return; + } + if (lines == null) { @@ -2264,40 +2176,42 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (lines.size() < 4) { + throw new IllegalArgumentException("Must have at least 4 lines"); + } -+ IChatBaseComponent[] components = CraftSign.sanitizeLines(lines); ++ Component[] 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); ++ private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor) { ++ SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState()); ++ sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); ++ System.arraycopy(components, 0, sign.messages, 0, sign.messages.length); + -+ getHandle().playerConnection.sendPacket(sign.getUpdatePacket()); ++ getHandle().connection.send(sign.getUpdatePacket()); + } + // Paper end @Override public void sendSignChange(Location loc, String[] lines) { - sendSignChange(loc, lines, DyeColor.BLACK); + this.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); + Component[] components = CraftSign.sanitizeLines(lines); +- SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState()); +- sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); +- for (int i = 0; i < components.length; i++) { +- sign.setMessage(i, components[i]); +- } ++ /*SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState()); ++ 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.getHandle().connection.send(sign.getUpdatePacket()); ++ this.getHandle().connection.send(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; + return (this.getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : this.getHandle().clientViewDistance; } + // Paper start @@ -2308,7 +2222,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end @Override public int getPing() { - return getHandle().ping; + return this.getHandle().latency; @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { getInventory().setItemInMainHand(hand); } @@ -2327,16 +2241,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @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()); ++ final ClientboundChatPacket packet = new ClientboundChatPacket(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatType.CHAT : net.minecraft.network.chat.ChatType.SYSTEM, identity.uuid()); + packet.adventure$message = message; -+ this.getHandle().playerConnection.sendPacket(packet); ++ this.getHandle().connection.send(packet); + } + + @Override + public void sendActionBar(final net.kyori.adventure.text.Component message) { -+ final PacketPlayOutTitle packet = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.ACTIONBAR, null); ++ final net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket packet = new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket((net.minecraft.network.chat.Component) null); + packet.adventure$text = message; -+ this.getHandle().playerConnection.sendPacket(packet); ++ this.getHandle().connection.send(packet); + } + + @Override @@ -2359,27 +2273,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private void adventure$sendPlayerListHeaderAndFooter() { -+ final PlayerConnection connection = this.getHandle().playerConnection; ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; + if (connection == null) return; -+ final PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); ++ final ClientboundTabListPacket packet = new ClientboundTabListPacket(null, null); + 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); ++ connection.send(packet); + } + + @Override + public void showTitle(final net.kyori.adventure.title.Title title) { -+ final PlayerConnection connection = this.getHandle().playerConnection; ++ final ServerGamePacketListenerImpl connection = this.getHandle().connection; + 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()))); ++ connection.send(new ClientboundSetTitlesAnimationPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut()))); + } -+ final PacketPlayOutTitle sp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.SUBTITLE, null); ++ final ClientboundSetSubtitleTextPacket sp = new ClientboundSetSubtitleTextPacket((net.minecraft.network.chat.Component) null); + sp.adventure$text = title.subtitle(); -+ connection.sendPacket(sp); -+ final PacketPlayOutTitle tp = new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.TITLE, null); ++ connection.send(sp); ++ final ClientboundSetTitleTextPacket tp = new ClientboundSetTitleTextPacket((net.minecraft.network.chat.Component) null); + tp.adventure$text = title.title(); -+ connection.sendPacket(tp); ++ connection.send(tp); + } + + private static int ticks(final java.time.Duration duration) { @@ -2391,7 +2305,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public void clearTitle() { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutTitle(PacketPlayOutTitle.EnumTitleAction.CLEAR, null)); ++ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundClearTitlesPacket(false)); + } + + // resetTitle implemented above @@ -2408,24 +2322,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public void playSound(final net.kyori.adventure.sound.Sound sound) { -+ final Vec3D pos = this.getHandle().getPositionVector(); ++ final Vec3 pos = this.getHandle().position(); + 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); ++ final ResourceLocation name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); ++ final java.util.Optional event = net.minecraft.core.Registry.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())); ++ this.getHandle().connection.send(new ClientboundSoundPacket(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())); ++ this.getHandle().connection.send(new ClientboundCustomSoundPacket(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3(x, y, z), sound.volume(), sound.pitch())); ++ } ++ } ++ ++ @Override ++ public void playSound(final net.kyori.adventure.sound.Sound sound, final net.kyori.adventure.sound.Sound.Emitter emitter) { ++ final Entity entity; ++ if (emitter == net.kyori.adventure.sound.Sound.Emitter.self()) { ++ entity = this.getHandle(); ++ } else if (emitter instanceof org.bukkit.entity.Entity) { ++ entity = ((CraftEntity) emitter).getHandle(); ++ } else { ++ throw new IllegalArgumentException("Sound emitter must be an Entity or self(), but was: " + emitter); ++ } ++ ++ final ResourceLocation name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name()); ++ final java.util.Optional event = net.minecraft.core.Registry.SOUND_EVENT.getOptional(name); ++ if (event.isPresent()) { ++ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSoundEntityPacket(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), entity, sound.volume(), sound.pitch())); ++ } else { ++ this.getHandle().connection.send(new ClientboundCustomSoundPacket(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), entity.position(), sound.volume(), sound.pitch())); + } + } + + @Override + public void stopSound(final net.kyori.adventure.sound.SoundStop stop) { -+ this.getHandle().playerConnection.sendPacket(new PacketPlayOutStopSound( ++ this.getHandle().connection.send(new ClientboundStopSoundPacket( + io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()), + io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source()) + )); @@ -2435,13 +2369,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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())); ++ final ServerPlayer player = this.getHandle(); ++ final ServerGamePacketListenerImpl connection = player.connection; ++ final net.minecraft.world.entity.player.Inventory inventory = player.getInventory(); ++ final int slot = inventory.items.size() + inventory.selected; ++ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, item)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); + } + // Paper end + @@ -2456,8 +2390,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +- public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List drops, String deathMessage, boolean keepInventory) { ++ public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer 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 @@ -2477,26 +2411,7 @@ diff --git a/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 { +@@ -0,0 +0,0 @@ public class CraftContainer extends AbstractContainerMenu { return inventory.getType(); } @@ -2510,37 +2425,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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/CraftContainer.javaED5zI7 b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.javaED5zI7 +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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 @@ -2591,7 +2478,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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.items = NonNullList.withSize(size, ItemStack.EMPTY); this.title = title; + this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title); this.viewers = new ArrayList(); @@ -2602,7 +2489,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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.items = NonNullList.withSize(size, ItemStack.EMPTY); + this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title); + this.adventure$title = title; + this.viewers = new ArrayList(); @@ -2612,8 +2499,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + @Override - public int getSize() { - return items.size(); + public int getContainerSize() { + return this.items.size(); @@ -0,0 +0,0 @@ public class CraftInventoryCustom extends CraftInventory { return null; } @@ -2625,14 +2512,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + public String getTitle() { - return title; + return this.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()); + return CraftItemStack.asCraftMirror(this.container.getSlot(slot).getItem()); } + // Paper start @@ -2644,7 +2531,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public String getTitle() { - return CraftChatMessage.fromComponent(container.getTitle()); + return CraftChatMessage.fromComponent(this.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 @@ -2657,13 +2544,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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(); ++ final net.minecraft.nbt.CompoundTag 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()); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName()); + } + // Paper end } @@ -2678,7 +2565,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Deprecated // Paper - Adventure public CraftMerchantCustom(String title) { super(new MinecraftMerchant(title)); - getMerchant().craftMerchant = this; + this.getMerchant().craftMerchant = this; } + // Paper start + public CraftMerchantCustom(net.kyori.adventure.text.Component title) { @@ -2690,13 +2577,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public String toString() { @@ -0,0 +0,0 @@ public class CraftMerchantCustom extends CraftMerchant { - private World tradingWorld; + private Level tradingWorld; protected CraftMerchant craftMerchant; + @Deprecated // Paper - Adventure public MinecraftMerchant(String title) { Validate.notNull(title, "Title cannot be null"); - this.title = new ChatComponentText(title); + this.title = new TextComponent(title); } + // Paper start + public MinecraftMerchant(net.kyori.adventure.text.Component title) { @@ -2730,6 +2617,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Spigot start import static org.spigotmc.ValidateUtils.*; ++ + import java.util.AbstractList; + import net.md_5.bungee.api.chat.BaseComponent; + import net.md_5.bungee.chat.ComponentSerializer; @@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { this.generation = (generation == null) ? null : generation.ordinal(); } @@ -2871,7 +2762,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end @Override public String getPage(final int page) { - Validate.isTrue(isValidPage(page), "Invalid page number"); + Validate.isTrue(this.isValidPage(page), "Invalid page number"); @@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { } @@ -2880,7 +2771,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { super.serialize(builder); - if (hasTitle()) { + if (this.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 @@ -2891,7 +2782,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 -import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.ImmutableMap; // Paper import java.util.Map; - import net.minecraft.nbt.NBTTagCompound; + import net.minecraft.nbt.CompoundTag; import org.bukkit.Material; @@ -0,0 +0,0 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta { } @@ -2907,7 +2798,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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()); + return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers()); } + // Paper start @@ -2943,7 +2834,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public boolean hasRepairCost() { - return repairCost > 0; + return this.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 @@ -2980,7 +2871,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + return this.converterMap.get(type).createInventory(holder, type); } + // Paper start @@ -2995,10 +2886,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - return converterMap.get(type).createInventory(holder, type, title); + return this.converterMap.get(type).createInventory(holder, type, title); } @@ -0,0 +0,0 @@ public final class CraftInventoryCreator { - return DEFAULT_CONVERTER.createInventory(holder, size); + return this.DEFAULT_CONVERTER.createInventory(holder, size); } + // Paper start @@ -3008,7 +2899,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + public Inventory createInventory(InventoryHolder holder, int size, String title) { - return DEFAULT_CONVERTER.createInventory(holder, size, title); + return this.DEFAULT_CONVERTER.createInventory(holder, size, title); } @@ -0,0 +0,0 @@ public final class CraftInventoryCreator { @@ -3026,15 +2917,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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()); + return this.getInventory(this.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)); ++ Container te = getTileEntity(); ++ if (te instanceof RandomizableContainerBlockEntity) { ++ ((RandomizableContainerBlockEntity) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); + } + + return getInventory(te); @@ -3043,7 +2934,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { - IInventory te = getTileEntity(); + Container te = this.getTileEntity(); @@ -0,0 +0,0 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat return furnace; } @@ -3051,26 +2942,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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)); ++ Container tileEntity = getTileEntity(); ++ ((AbstractFurnaceBlockEntity) 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(); + Container tileEntity = this.getTileEntity(); @@ -0,0 +0,0 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat - return new TileEntityBrewingStand(); + return new BrewingStandBlockEntity(BlockPos.ZERO, Blocks.BREWING_STAND.defaultBlockState()); } + // 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)); ++ Container tileEntity = getTileEntity(); ++ if (tileEntity instanceof BrewingStandBlockEntity) { ++ ((BrewingStandBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); + } + return getInventory(tileEntity); + } @@ -3084,7 +2975,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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(); + return this.objective.getName(); } + // Paper start @@ -3104,14 +2995,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end @Override public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + CraftScoreboard scoreboard = this.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); + return this.registerNewObjective(name, criteria, name); } + // Paper start + @Override @@ -3130,7 +3021,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); ++ net.minecraft.world.scores.Objective objective = board.addObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); + return new CraftObjective(this, objective); + } + // Paper end @@ -3149,8 +3040,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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)); + net.minecraft.world.scores.Objective objective = this.board.addObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); - return new CraftObjective(this, objective); ++ ++ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); ++ 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 } @@ -3162,7 +3056,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java @@ -0,0 +0,0 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { - return team.getName(); + return this.team.getName(); } + // Paper start + @Override @@ -3179,30 +3073,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public net.kyori.adventure.text.Component prefix() throws IllegalStateException { + CraftScoreboard scoreboard = checkState(); -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPrefix()); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerPrefix()); + } + @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)); ++ team.setPlayerPrefix(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()); ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerSuffix()); + } + @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)); ++ team.setPlayerSuffix(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 (team.getColor().getColor() == 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().getColor()); + 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; + } @@ -3222,7 +3116,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java @@ -0,0 +0,0 @@ public final class CraftChatMessage { - public static String fromComponent(IChatBaseComponent component) { + public static String fromComponent(Component 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(); @@ -3263,22 +3157,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + - public static IBlockData getBlock(MaterialData material) { - return getBlock(material.getItemType(), material.getData()); + public static BlockState getBlock(MaterialData material) { + return CraftMagicNumbers.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(); + return this.reference = this.makeReference(); } - abstract Set makeReference(); + protected abstract Set makeReference(); // Paper - protected public boolean isLazy() { - return reference == null; + return this.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 @@ -3292,11 +3186,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (reference != null) { throw new IllegalStateException("Reference already created!"); } + List players = this.server.getPlayerList().players; + // Paper start + return makePlayerSet(this.server); + } + public static HashSet makePlayerSet(final MinecraftServer server) { + // Paper end - List players = server.getPlayerList().players; ++ List players = server.getPlayerList().players; HashSet reference = new HashSet(players.size()); - for (EntityPlayer player : players) { + for (ServerPlayer player : players) { + reference.add(player.getBukkitEntity()); diff --git a/patches/server/All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server/All-chunks-are-slime-spawn-chunks-toggle.patch new file mode 100644 index 0000000000..5d628f686a --- /dev/null +++ b/patches/server/All-chunks-are-slime-spawn-chunks-toggle.patch @@ -0,0 +1,33 @@ +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/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + } + + ChunkPos chunkcoordintpair = new ChunkPos(pos); +- boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot ++ boolean flag = world.getMinecraftWorld().paperConfig.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) world).getSeed(), world.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper + + if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { + return checkMobSpawnRules(type, world, spawnReason, pos, random); diff --git a/Spigot-Server-Patches/Allow-Reloading-of-Command-Aliases.patch b/patches/server/Allow-Reloading-of-Command-Aliases.patch similarity index 100% rename from Spigot-Server-Patches/Allow-Reloading-of-Command-Aliases.patch rename to patches/server/Allow-Reloading-of-Command-Aliases.patch diff --git a/Spigot-Server-Patches/Allow-Reloading-of-Custom-Permissions.patch b/patches/server/Allow-Reloading-of-Custom-Permissions.patch similarity index 100% rename from Spigot-Server-Patches/Allow-Reloading-of-Custom-Permissions.patch rename to patches/server/Allow-Reloading-of-Custom-Permissions.patch diff --git a/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch b/patches/server/Allow-Saving-of-Oversized-Chunks.patch similarity index 59% rename from Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch rename to patches/server/Allow-Saving-of-Oversized-Chunks.patch index 03a45e81d4..a0dbbc59cb 100644 --- a/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch +++ b/patches/server/Allow-Saving-of-Oversized-Chunks.patch @@ -3,6 +3,8 @@ From: Aikar Date: Fri, 15 Feb 2019 01:08:19 -0500 Subject: [PATCH] Allow Saving of Oversized Chunks +Note 1.17 update: With 1.17, Entities are no longer stored in chunk slices, so this needs updating!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + 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. @@ -30,26 +32,6 @@ This fix also maintains compatability if someone switches server jars to one wit 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 @@ -61,31 +43,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.Util; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtIo; + import net.minecraft.world.level.ChunkPos; 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 + protected final RegionBitmap usedSectors; + public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper ++ public final File regionFile; // Paper - public RegionFile(File file, File file1, boolean flag) throws IOException { - this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag); + public RegionFile(File file, File directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); @@ -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 + public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException { + this.header = ByteBuffer.allocateDirect(8192); ++ this.regionFile = file.toFile(); // Paper + initOversizedState(); // Paper - this.freeSectors = new RegionFileBitSet(); - this.f = regionfilecompression; - if (!Files.isDirectory(path1, new LinkOption[0])) { + this.usedSectors = new RegionBitmap(); + this.version = outputChunkStreamVersion; + if (!Files.isDirectory(directory, new LinkOption[0])) { @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - void run() throws IOException; + } + // Paper start @@ -141,40 +123,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private File getOversizedMetaFile() { -+ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); ++ return new File(this.regionFile.getParentFile(), this.regionFile.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"); ++ return new File(this.regionFile.getParentFile(), this.regionFile.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); + } + -+ synchronized NBTTagCompound getOversizedData(int x, int z) throws IOException { ++ synchronized CompoundTag 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); ++ return NbtIo.read((java.io.DataInput) out); + } + + } + // Paper end - class ChunkBuffer extends ByteArrayOutputStream { + private 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 + private final ChunkPos pos; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.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; +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -0,0 +0,0 @@ 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.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtIo; ++import net.minecraft.nbt.Tag; 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 { + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { } } @@ -199,21 +180,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + -+ private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException { ++ private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos 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); ++ try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) { ++ CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); ++ CompoundTag chunk = NbtIo.read((DataInput) datainputstream); + if (oversizedData == null) { + return chunk; + } -+ NBTTagCompound oversizedLevel = oversizedData.getCompound("Level"); -+ NBTTagCompound level = chunk.getCompound("Level"); ++ CompoundTag oversizedLevel = oversizedData.getCompound("Level"); ++ CompoundTag level = chunk.getCompound("Level"); + + mergeChunkList(level, oversizedLevel, "Entities"); + mergeChunkList(level, oversizedLevel, "TileEntities"); + -+ chunk.set("Level", level); ++ chunk.put("Level", level); + + return chunk; + } catch (Throwable throwable) { @@ -223,17 +204,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private static void mergeChunkList(NBTTagCompound level, NBTTagCompound oversizedLevel, String key) { -+ NBTTagList levelList = level.getList(key, 10); -+ NBTTagList oversizedList = oversizedLevel.getList(key, 10); ++ private static void mergeChunkList(CompoundTag level, CompoundTag oversizedLevel, String key) { ++ ListTag levelList = level.getList(key, 10); ++ ListTag oversizedList = oversizedLevel.getList(key, 10); + + if (!oversizedList.isEmpty()) { + levelList.addAll(oversizedList); -+ level.set(key, levelList); ++ level.put(key, levelList); + } + } + -+ private static int getNBTSize(NBTBase nbtBase) { ++ private static int getNBTSize(Tag nbtBase) { + DataOutputStream test = new DataOutputStream(new org.apache.commons.io.output.NullOutputStream()); + try { + nbtBase.write(test); @@ -247,26 +228,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper End + @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { + public CompoundTag read(ChunkPos pos) 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); +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + try { // Paper + DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); + + // Paper start -+ if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { -+ printOversizedLog("Loading Oversized Chunk!", regionfile.file, chunkcoordintpair.x, chunkcoordintpair.z); -+ return readOversizedChunk(regionfile, chunkcoordintpair); ++ if (regionfile.isOversized(pos.x, pos.z)) { ++ printOversizedLog("Loading Oversized Chunk!", regionfile.regionFile, pos.x, pos.z); ++ return readOversizedChunk(regionfile, pos); + } + // Paper end - Throwable throwable = null; + CompoundTag nbttagcompound; + label43: + { +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { - 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; + try { + NbtIo.write(nbt, (DataOutput) dataoutputstream); ++ regionfile.setOversized(pos.x, pos.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 throwable) { + if (dataoutputstream != null) { + try { diff --git a/Spigot-Server-Patches/Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/Allow-adding-items-to-BlockDropItemEvent.patch similarity index 87% rename from Spigot-Server-Patches/Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/server/Allow-adding-items-to-BlockDropItemEvent.patch index 151563104d..4367155fda 100644 --- a/Spigot-Server-Patches/Allow-adding-items-to-BlockDropItemEvent.patch +++ b/patches/server/Allow-adding-items-to-BlockDropItemEvent.patch @@ -11,11 +11,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftEventFactory { } - public static void handleBlockDropItemEvent(Block block, BlockState state, EntityPlayer player, List items) { + public static void handleBlockDropItemEvent(Block block, BlockState state, ServerPlayer 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) { ++ for (ItemEntity item : items) { + list.add((Item) item.getBukkitEntity()); + } + BlockDropItemEvent event = new BlockDropItemEvent(block, state, player.getBukkitEntity(), list); @@ -23,13 +23,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { -- for (EntityItem item : items) { -- item.world.addEntity(item); +- for (ItemEntity item : items) { +- item.level.addFreshEntity(item); + // Paper start + for (Item bukkit : list) { + if (!bukkit.isValid()) { + Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); -+ item.world.addEntity(item); ++ item.level.addFreshEntity(item); + } + } + } else { diff --git a/Spigot-Server-Patches/Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server/Allow-chests-to-be-placed-with-NBT-data.patch similarity index 72% rename from Spigot-Server-Patches/Allow-chests-to-be-placed-with-NBT-data.patch rename to patches/server/Allow-chests-to-be-placed-with-NBT-data.patch index f0dfa2fde8..0043f8dedc 100644 --- a/Spigot-Server-Patches/Allow-chests-to-be-placed-with-NBT-data.patch +++ b/patches/server/Allow-chests-to-be-placed-with-NBT-data.patch @@ -9,21 +9,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 + enuminteractionresult = InteractionResult.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 +diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.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 +--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -0,0 +0,0 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement // CraftBukkit start @Override - public boolean isFilteredNBT() { + public boolean onlyOpCanSetNbt() { - return true; + return false; // Paper } diff --git a/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch new file mode 100644 index 0000000000..820c8124d3 --- /dev/null +++ b/patches/server/Allow-delegation-to-vanilla-chunk-gen.patch @@ -0,0 +1,69 @@ +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/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.ServerLevel nmsWorld = ((CraftWorld) world).getHandle(); ++ net.minecraft.world.level.chunk.ProtoChunk protoChunk = new net.minecraft.world.level.chunk.ProtoChunk(new net.minecraft.world.level.ChunkPos(x, z), null, nmsWorld); ++ List list = new ArrayList<>(); ++ list.add(protoChunk); ++ net.minecraft.server.level.WorldGenRegion genRegion = new net.minecraft.server.level.WorldGenRegion(nmsWorld, list, net.minecraft.world.level.chunk.ChunkStatus.EMPTY, -1); ++ // call vanilla generator, one feature after another. Order here is important! ++ net.minecraft.world.level.chunk.ChunkGenerator chunkGenerator = nmsWorld.getChunkSource().generator; ++ if (chunkGenerator instanceof org.bukkit.craftbukkit.generator.CustomChunkGenerator) { ++ chunkGenerator = ((org.bukkit.craftbukkit.generator.CustomChunkGenerator) chunkGenerator).delegate; ++ } ++ chunkGenerator.createBiomes(nmsWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), protoChunk); ++ chunkGenerator.fillFromNoise((runnable) -> {}, nmsWorld.structureFeatureManager(), protoChunk); ++ chunkGenerator.buildSurfaceAndBedrock(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 minHeight; + private final int maxHeight; +- private final LevelChunkSection[] sections; ++ private LevelChunkSection[] 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 this.sections; + } + ++ // Paper start ++ public void setRawChunkData(LevelChunkSection[] sections) { ++ this.sections = sections; ++ } ++ // Paper end ++ + Set getTiles() { + return this.tiles; + } diff --git a/Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch b/patches/server/Allow-disabling-armour-stand-ticking.patch similarity index 56% rename from Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch rename to patches/server/Allow-disabling-armour-stand-ticking.patch index fd6e3e16c7..dde5613bf1 100644 --- a/Spigot-Server-Patches/Allow-disabling-armour-stand-ticking.patch +++ b/patches/server/Allow-disabling-armour-stand-ticking.patch @@ -19,13 +19,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.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; +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + public Rotations leftLegPose; + public Rotations rightLegPose; public boolean canMove = true; // Paper + // Paper start - Allow ArmorStands not to tick + public boolean canTick = true; @@ -34,42 +34,42 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private boolean noTickEquipmentDirty = false; + // Paper end - public EntityArmorStand(EntityTypes entitytypes, World world) { - super(entitytypes, world); + public ArmorStand(EntityType type, Level world) { + super(type, 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.handItems = NonNullList.withSize(2, ItemStack.EMPTY); + this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY); + this.headPose = ArmorStand.DEFAULT_HEAD_POSE; +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + this.armorItems.set(enumitemslot.getIndex(), itemstack); } + this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled } @Override -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { } - nbttagcompound.set("Pose", this.B()); -+ if (this.canTickSetByAPI) nbttagcompound.setBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting + nbt.put("Pose", this.writePose()); ++ if (this.canTickSetByAPI) nbt.putBoolean("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(); +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + this.setNoBasePlate(nbt.getBoolean("NoBasePlate")); + this.setMarker(nbt.getBoolean("Marker")); + this.noPhysics = !this.hasPhysics(); + // Paper start - persist no tick -+ if (nbttagcompound.hasKey("Paper.CanTickOverride")) { -+ this.canTick = nbttagcompound.getBoolean("Paper.CanTickOverride"); ++ if (nbt.contains("Paper.CanTickOverride")) { ++ this.canTick = nbt.getBoolean("Paper.CanTickOverride"); + this.canTickSetByAPI = true; + } + // Paper end - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Pose"); + CompoundTag nbttagcompound1 = nbt.getCompound("Pose"); - this.g(nbttagcompound1); -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { + this.readPose(nbttagcompound1); +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { @Override public void tick() { @@ -82,7 +82,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + if (this.noTickEquipmentDirty) { + this.noTickEquipmentDirty = false; -+ this.updateEquipment(); ++ this.detectEquipmentUpdates(); + } + + return; @@ -96,53 +96,54 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public void updatePose() { + // Paper end - Vector3f vector3f = (Vector3f) this.datawatcher.get(EntityArmorStand.c); + Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE); 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); +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + public void setHeadPose(Rotations angle) { + this.headPose = angle; + this.entityData.set(ArmorStand.DATA_HEAD_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setBodyPose(Vector3f vector3f) { - this.bodyPose = vector3f; - this.datawatcher.set(EntityArmorStand.d, vector3f); + public void setBodyPose(Rotations angle) { + this.bodyPose = angle; + this.entityData.set(ArmorStand.DATA_BODY_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setLeftArmPose(Vector3f vector3f) { - this.leftArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.e, vector3f); + public void setLeftArmPose(Rotations angle) { + this.leftArmPose = angle; + this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setRightArmPose(Vector3f vector3f) { - this.rightArmPose = vector3f; - this.datawatcher.set(EntityArmorStand.f, vector3f); + public void setRightArmPose(Rotations angle) { + this.rightArmPose = angle; + this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking } - public void setLeftLegPose(Vector3f vector3f) { + public void setLeftLegPose(Rotations angle) { + this.leftLegPose = angle; + this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.leftLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.g, vector3f); -+ } - public void setRightLegPose(Vector3f vector3f) { + public void setRightLegPose(Rotations angle) { + this.rightLegPose = angle; + this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, angle); + this.noTickPoseDirty = true; // Paper - Allow updates when not ticking - this.rightLegPose = vector3f; - this.datawatcher.set(EntityArmorStand.bh, vector3f); } + + public Rotations getHeadPose() { 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)); + public void setCanMove(boolean move) { + getHandle().canMove = move; } + + @Override diff --git a/Spigot-Server-Patches/Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/Allow-disabling-mob-spawner-spawn-egg-transformation.patch similarity index 58% rename from Spigot-Server-Patches/Allow-disabling-mob-spawner-spawn-egg-transformation.patch rename to patches/server/Allow-disabling-mob-spawner-spawn-egg-transformation.patch index b9ed7a75bb..91db7a8951 100644 --- a/Spigot-Server-Patches/Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ b/patches/server/Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -9,25 +9,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +diff --git a/src/main/java/net/minecraft/world/item/SpawnEggItem.java b/src/main/java/net/minecraft/world/item/SpawnEggItem.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); +--- a/src/main/java/net/minecraft/world/item/SpawnEggItem.java ++++ b/src/main/java/net/minecraft/world/item/SpawnEggItem.java +@@ -0,0 +0,0 @@ public class SpawnEggItem extends Item { + Direction enumdirection = context.getClickedFace(); + BlockState iblockdata = world.getBlockState(blockposition); -- if (iblockdata.a(Blocks.SPAWNER)) { -+ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.a(Blocks.SPAWNER)) { // Paper - TileEntity tileentity = world.getTileEntity(blockposition); +- if (iblockdata.is(Blocks.SPAWNER)) { ++ if (!world.paperConfig.disableMobSpawnerSpawnEggTransformation && iblockdata.is(Blocks.SPAWNER)) { // Paper + BlockEntity tileentity = world.getBlockEntity(blockposition); - if (tileentity instanceof TileEntityMobSpawner) { + if (tileentity instanceof SpawnerBlockEntity) { diff --git a/Spigot-Server-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch b/patches/server/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch similarity index 90% rename from Spigot-Server-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch rename to patches/server/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch index 6ce190411e..ee0a8f0493 100644 --- a/Spigot-Server-Patches/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch +++ b/patches/server/Allow-for-Component-suggestion-tooltips-in-AsyncTabC.patch @@ -5,18 +5,18 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // 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(), + String buffer = packet.getCommand(); +- event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), completions, ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), buffer, true, null); event.callEvent(); - completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); @@ -24,12 +24,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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 { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser }); } } 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()); +- com.mojang.brigadier.suggestion.SuggestionsBuilder builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); ++ com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); - builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); - completions.forEach(builder::suggest); @@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); 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); + com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), 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 diff --git a/Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch b/patches/server/Allow-for-toggling-of-spawn-chunks.patch similarity index 82% rename from Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch rename to patches/server/Allow-for-toggling-of-spawn-chunks.patch index 40ada8ba8a..1aa084f151 100644 --- a/Spigot-Server-Patches/Allow-for-toggling-of-spawn-chunks.patch +++ b/patches/server/Allow-for-toggling-of-spawn-chunks.patch @@ -19,11 +19,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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 { +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { }); // CraftBukkit end timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings diff --git a/Spigot-Server-Patches/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch b/patches/server/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch similarity index 56% rename from Spigot-Server-Patches/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch rename to patches/server/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch index 2fee86152b..3e1e2807fa 100644 --- a/Spigot-Server-Patches/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch +++ b/patches/server/Allow-multiple-callbacks-to-schedule-for-Callback-Ex.patch @@ -13,46 +13,39 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 { +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final CallbackExecutor callbackExecutor = new CallbackExecutor(); public static final class CallbackExecutor implements java.util.concurrent.Executor, Runnable { -- private Runnable queued; +- private final java.util.Queue queue = new java.util.ArrayDeque<>(); + // 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<>(); ++ private java.util.Queue queue = new java.util.ArrayDeque<>(); // Paper - remove final @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); ++ if (this.queue == null) { ++ this.queue = new java.util.ArrayDeque<>(); ++ } + this.queue.add(runnable); } @Override public void run() { -- Runnable task = queued; -+ if (queued == null) { ++ if (this.queue == null) { + return; + } -+ java.util.ArrayDeque queue = queued; - queued = null; -- if (task != null) { -+ Runnable task; -+ while ((task = queue.pollFirst()) != null) { ++ java.util.Queue queue = this.queue; ++ this.queue = null; ++ // Paper end + Runnable task; +- while ((task = this.queue.poll()) != null) { ++ while ((task = queue.poll()) != null) { // Paper task.run(); } } -+ // Paper end - }; - // CraftBukkit end - diff --git a/patches/server/Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server/Allow-nerfed-mobs-to-jump-and-take-water-damage.patch new file mode 100644 index 0000000000..3599ea2fda --- /dev/null +++ b/patches/server/Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -0,0 +1,75 @@ +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 Nameable, EntityAccess, CommandSource, n + return this.isInWater() || this.isInRain(); + } + ++ @Deprecated public final boolean isInWaterOrRainOrBubble() { return isInWaterRainOrBubble(); } // Paper - OBFHELPER + public boolean isInWaterRainOrBubble() { + return this.isInWater() || this.isInRain() || this.isInBubbleColumn(); + } +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; + public GoalSelector goalSelector; ++ @Nullable public net.minecraft.world.entity.ai.goal.FloatGoal goalFloat; // Paper + public GoalSelector targetSelector; + private LivingEntity target; + private final Sensing sensing; +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + @Override + protected final void serverAiStep() { + ++this.noActionTime; +- 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.canUse()) goalFloat.tick(); ++ this.getJumpControl().tick(); ++ } ++ if ((this instanceof net.minecraft.world.entity.monster.Blaze || this instanceof net.minecraft.world.entity.monster.EnderMan) && isInWaterRainOrBubble()) { ++ hurt(DamageSource.DROWN, 1.0F); ++ } ++ return; ++ } ++ // Paper end + this.level.getProfiler().push("sensing"); + this.sensing.tick(); + this.level.getProfiler().pop(); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/FloatGoal.java +@@ -0,0 +0,0 @@ public class FloatGoal extends Goal { + + public FloatGoal(Mob mob) { + this.mob = mob; ++ if (mob.getCommandSenderWorld().paperConfig.nerfedMobsShouldJump) mob.goalFloat = this; // Paper + this.setFlags(EnumSet.of(Goal.Flag.JUMP)); + mob.getNavigation().setCanFloat(true); + } diff --git a/Spigot-Server-Patches/Allow-overriding-the-java-version-check.patch b/patches/server/Allow-overriding-the-java-version-check.patch similarity index 90% rename from Spigot-Server-Patches/Allow-overriding-the-java-version-check.patch rename to patches/server/Allow-overriding-the-java-version-check.patch index 9ee5f8b776..ef64daab09 100644 --- a/Spigot-Server-Patches/Allow-overriding-the-java-version-check.patch +++ b/patches/server/Allow-overriding-the-java-version-check.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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; diff --git a/Spigot-Server-Patches/Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server/Allow-spawning-Item-entities-with-World.spawnEntity.patch similarity index 70% rename from Spigot-Server-Patches/Allow-spawning-Item-entities-with-World.spawnEntity.patch rename to patches/server/Allow-spawning-Item-entities-with-World.spawnEntity.patch index 859a04e3df..fd77740787 100644 --- a/Spigot-Server-Patches/Allow-spawning-Item-entities-with-World.spawnEntity.patch +++ b/patches/server/Allow-spawning-Item-entities-with-World.spawnEntity.patch @@ -13,12 +13,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + entity = new net.minecraft.world.entity.vehicle.Boat(this.world, x, y, z); + entity.moveTo(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))); ++ entity = new ItemEntity(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Item.byBlock(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))); + entity = new FallingBlockEntity(this.world, x, y, z, this.world.getBlockState(new BlockPos(x, y, z))); } else if (Projectile.class.isAssignableFrom(clazz)) { diff --git a/Spigot-Server-Patches/Allow-specifying-a-custom-authentication-servers-dow.patch b/patches/server/Allow-specifying-a-custom-authentication-servers-dow.patch similarity index 60% rename from Spigot-Server-Patches/Allow-specifying-a-custom-authentication-servers-dow.patch rename to patches/server/Allow-specifying-a-custom-authentication-servers-dow.patch index 75e8645bd5..35a1658591 100644 --- a/Spigot-Server-Patches/Allow-specifying-a-custom-authentication-servers-dow.patch +++ b/patches/server/Allow-specifying-a-custom-authentication-servers-dow.patch @@ -26,18 +26,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.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; +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + ServerLoginPacketListenerImpl.this.gameProfile = ServerLoginPacketListenerImpl.this.createFakeProfile(gameprofile); + ServerLoginPacketListenerImpl.this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; } else { + // Paper start + if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { -+ LoginListener.this.disconnect(new ChatComponentText(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); ++ ServerLoginPacketListenerImpl.this.disconnect(new TextComponent(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"); + ServerLoginPacketListenerImpl.this.disconnect(new TranslatableComponent("multiplayer.disconnect.authservers_down")); + ServerLoginPacketListenerImpl.LOGGER.error("Couldn't verify username because servers are unavailable"); } diff --git a/patches/server/Allow-using-signs-inside-spawn-protection.patch b/patches/server/Allow-using-signs-inside-spawn-protection.patch new file mode 100644 index 0000000000..b47c9531e7 --- /dev/null +++ b/patches/server/Allow-using-signs-inside-spawn-protection.patch @@ -0,0 +1,34 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + int i = this.player.level.getMaxBuildHeight(); + + if (blockposition.getY() < i) { +- if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { ++ if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && (worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition) || (worldserver.paperConfig.allowUsingSignsInsideSpawnProtection && worldserver.getBlockState(blockposition).getBlock() instanceof net.minecraft.world.level.block.SignBlock))) { // Paper + // CraftBukkit start - Check if we can actually do something over this large a distance + // Paper - move check up + this.player.stopUsingItem(); // SPIGOT-4706 diff --git a/Spigot-Server-Patches/Always-tick-falling-blocks.patch b/patches/server/Always-tick-falling-blocks.patch similarity index 55% rename from Spigot-Server-Patches/Always-tick-falling-blocks.patch rename to patches/server/Always-tick-falling-blocks.patch index d1254a90b5..f34fbb3d88 100644 --- a/Spigot-Server-Patches/Always-tick-falling-blocks.patch +++ b/patches/server/Always-tick-falling-blocks.patch @@ -9,10 +9,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 ) + || entity instanceof AbstractHurtingProjectile + || entity instanceof LightningBolt + || entity instanceof PrimedTnt ++ || entity instanceof net.minecraft.world.entity.item.FallingBlockEntity // Paper - Always tick falling blocks + || entity instanceof EndCrystal + || entity instanceof FireworkRocketEntity + || entity instanceof ThrownTrident ) diff --git a/patches/server/Anti-Xray.patch b/patches/server/Anti-Xray.patch new file mode 100644 index 0000000000..bc7242244d --- /dev/null +++ b/patches/server/Anti-Xray.patch @@ -0,0 +1,1509 @@ +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 lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); + } ++ ++ public boolean antiXray; ++ public EngineMode engineMode; ++ public int maxBlockHeight; ++ 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; ++ maxBlockHeight = getInt("anti-xray.max-block-height", 64); ++ 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("copper_ore", "deepslate_copper_ore", "gold_ore", "deepslate_gold_ore", "iron_ore", "deepslate_iron_ore", ++ "coal_ore", "deepslate_coal_ore", "lapis_ore", "deepslate_lapis_ore", "mossy_cobblestone", "obsidian", "chest", "diamond_ore", "deepslate_diamond_ore", ++ "redstone_ore", "deepslate_redstone_ore", "clay", "emerald_ore", "deepslate_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 " + ((maxBlockHeight >> 4) << 4) + " 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.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++ ++public class ChunkPacketBlockController { ++ ++ public static final ChunkPacketBlockController NO_OPERATION_INSTANCE = new ChunkPacketBlockController(); ++ ++ protected ChunkPacketBlockController() { ++ ++ } ++ ++ public BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection chunkSection, boolean initializeBlocks) { ++ return null; ++ } ++ ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk) { ++ return false; ++ } ++ ++ public ChunkPacketInfo getChunkPacketInfo(ClientboundLevelChunkPacket chunkPacket, LevelChunk chunk) { ++ return null; ++ } ++ ++ public void modifyBlocks(ClientboundLevelChunkPacket chunkPacket, ChunkPacketInfo chunkPacketInfo) { ++ chunkPacket.setReady(true); ++ } ++ ++ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { ++ ++ } ++ ++ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction 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.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.core.Registry; ++import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ServerPlayerGameMode; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.EmptyLevelChunk; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++import net.minecraft.world.level.chunk.Palette; ++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 worldSectionHeight; ++ private final int maxChunkSectionIndex; ++ private final int updateRadius; ++ private final boolean usePermission; ++ private final BlockState[] predefinedBlockData; ++ private final BlockState[] predefinedBlockDataFull; ++ private final BlockState[] predefinedBlockDataStone; ++ private final BlockState[] predefinedBlockDataNetherrack; ++ private final BlockState[] predefinedBlockDataEndStone; ++ private final int[] predefinedBlockDataBitsGlobal; ++ private final int[] predefinedBlockDataBitsStoneGlobal; ++ private final int[] predefinedBlockDataBitsNetherrackGlobal; ++ private final int[] predefinedBlockDataBitsEndStoneGlobal; ++ private final boolean[] solidGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; ++ private final boolean[] obfuscateGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()]; ++ private final LevelChunkSection[] emptyNearbyChunkSections = {LevelChunk.EMPTY_SECTION, LevelChunk.EMPTY_SECTION, LevelChunk.EMPTY_SECTION, LevelChunk.EMPTY_SECTION}; ++ private final int maxBlockYUpdatePosition; ++ ++ public ChunkPacketBlockControllerAntiXray(Level world, Executor executor) { ++ PaperWorldConfig paperWorldConfig = world.paperConfig; ++ engineMode = paperWorldConfig.engineMode; ++ ++ int minSection = world.getMinSection(); ++ worldSectionHeight = world.getSectionsCount(); ++ maxChunkSectionIndex = (paperWorldConfig.maxBlockHeight >> 4) - minSection; ++ updateRadius = paperWorldConfig.updateRadius; ++ usePermission = paperWorldConfig.usePermission; ++ ++ this.executor = executor; ++ ++ List toObfuscate; ++ ++ if (engineMode == EngineMode.HIDE) { ++ toObfuscate = paperWorldConfig.hiddenBlocks; ++ predefinedBlockData = null; ++ predefinedBlockDataFull = null; ++ predefinedBlockDataStone = new BlockState[] {Blocks.STONE.defaultBlockState()}; ++ predefinedBlockDataNetherrack = new BlockState[] {Blocks.NETHERRACK.defaultBlockState()}; ++ predefinedBlockDataEndStone = new BlockState[] {Blocks.END_STONE.defaultBlockState()}; ++ predefinedBlockDataBitsGlobal = null; ++ predefinedBlockDataBitsStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(Blocks.STONE.defaultBlockState())}; ++ predefinedBlockDataBitsNetherrackGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(Blocks.NETHERRACK.defaultBlockState())}; ++ predefinedBlockDataBitsEndStoneGlobal = new int[] {LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(Blocks.END_STONE.defaultBlockState())}; ++ } else { ++ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); ++ List predefinedBlockDataList = new LinkedList(); ++ ++ for (String id : paperWorldConfig.hiddenBlocks) { ++ Block block = Registry.BLOCK.getOptional(new ResourceLocation(id)).orElse(null); ++ ++ if (block != null && !(block instanceof net.minecraft.world.level.block.EntityBlock)) { ++ toObfuscate.add(id); ++ predefinedBlockDataList.add(block.defaultBlockState()); ++ } ++ } ++ ++ // 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<>(predefinedBlockDataList); ++ // Therefore addAll(Collection c) is used, which guarantees this order in the doc ++ predefinedBlockData = predefinedBlockDataSet.isEmpty() ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataSet.toArray(new BlockState[0]); ++ predefinedBlockDataFull = predefinedBlockDataSet.isEmpty() ? new BlockState[] {Blocks.DIAMOND_ORE.defaultBlockState()} : predefinedBlockDataList.toArray(new BlockState[0]); ++ predefinedBlockDataStone = null; ++ predefinedBlockDataNetherrack = null; ++ predefinedBlockDataEndStone = null; ++ predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length]; ++ ++ for (int i = 0; i < predefinedBlockDataFull.length; i++) { ++ predefinedBlockDataBitsGlobal[i] = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(predefinedBlockDataFull[i]); ++ } ++ ++ predefinedBlockDataBitsStoneGlobal = null; ++ predefinedBlockDataBitsNetherrackGlobal = null; ++ predefinedBlockDataBitsEndStoneGlobal = null; ++ } ++ ++ for (String id : toObfuscate) { ++ Block block = Registry.BLOCK.getOptional(new ResourceLocation(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.defaultBlockState().isAir()) { ++ // Replace all block states of a specified block ++ for (BlockState blockData : block.getStateDefinition().getPossibleStates()) { ++ obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(blockData)] = true; ++ } ++ } ++ } ++ ++ EmptyLevelChunk emptyChunk = new EmptyLevelChunk(world, new ChunkPos(0, 0)); ++ BlockPos zeroPos = new BlockPos(0, 0, 0); ++ ++ for (int i = 0; i < solidGlobal.length; i++) { ++ BlockState blockData = LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.valueFor(i); ++ ++ if (blockData != null) { ++ solidGlobal[i] = blockData.isRedstoneConductor(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.defaultBlockState(); ++ // 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 BlockState[] getPredefinedBlockData(Level world, ChunkAccess chunk, LevelChunkSection 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.bottomBlockY() >> 4 <= maxChunkSectionIndex) { ++ if (engineMode == EngineMode.HIDE) { ++ return switch (world.getWorld().getEnvironment()) { ++ case NETHER -> predefinedBlockDataNetherrack; ++ case THE_END -> predefinedBlockDataEndStone; ++ default -> predefinedBlockDataStone; ++ }; ++ } ++ return predefinedBlockData; ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public boolean shouldModify(ServerPlayer entityPlayer, LevelChunk chunk) { ++ return !usePermission || !entityPlayer.getBukkitEntity().hasPermission("paper.antixray.bypass"); ++ } ++ ++ @Override ++ public ChunkPacketInfoAntiXray getChunkPacketInfo(ClientboundLevelChunkPacket chunkPacket, LevelChunk chunk) { ++ // 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. ++ return new ChunkPacketInfoAntiXray(chunkPacket, chunk, this); ++ } ++ ++ @Override ++ public void modifyBlocks(ClientboundLevelChunkPacket chunkPacket, ChunkPacketInfo chunkPacketInfo) { ++ if (chunkPacketInfo == null) { ++ chunkPacket.setReady(true); ++ return; ++ } ++ ++ if (!Bukkit.isPrimaryThread()) { ++ // plugins? ++ MinecraftServer.getServer().scheduleOnMain(() -> { ++ this.modifyBlocks(chunkPacket, chunkPacketInfo); ++ }); ++ return; ++ } ++ ++ LevelChunk chunk = chunkPacketInfo.getChunk(); ++ int x = chunk.getPos().x; ++ int z = chunk.getPos().z; ++ ServerLevel world = chunk.level; ++ ((ChunkPacketInfoAntiXray) chunkPacketInfo).setNearbyChunks( ++ (LevelChunk) world.getChunkIfLoadedImmediately(x - 1, z), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x + 1, z), ++ (LevelChunk) world.getChunkIfLoadedImmediately(x, z - 1), ++ (LevelChunk) 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.BLOCK_STATE_REGISTRY.size()]); ++ private static final ThreadLocal obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.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 = ChunkPacketBlockControllerAntiXray.solid.get(); ++ boolean[] obfuscate = ChunkPacketBlockControllerAntiXray.obfuscate.get(); ++ boolean[][] current = ChunkPacketBlockControllerAntiXray.current.get(); ++ boolean[][] next = ChunkPacketBlockControllerAntiXray.next.get(); ++ boolean[][] nextNext = ChunkPacketBlockControllerAntiXray.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(); ++ LevelChunkSection[] nearbyChunkSections = new LevelChunkSection[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) == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { ++ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().level.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().level.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; ++ } else { ++ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead ++ BlockState[] 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).idFor(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 ++ LevelChunkSection belowChunkSection = null; ++ boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex - 1]) == LevelChunk.EMPTY_SECTION; ++ ++ for (int z = 0; z < 16; z++) { ++ for (int x = 0; x < 16; x++) { ++ current[z][x] = true; ++ next[z][x] = skipFirstLayer || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(belowChunkSection.getBlockState(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 ? LevelChunk.EMPTY_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? LevelChunk.EMPTY_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? LevelChunk.EMPTY_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex]; ++ nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? LevelChunk.EMPTY_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 ++ LevelChunkSection aboveChunkSection; ++ ++ if (chunkSectionIndex != worldSectionHeight && (aboveChunkSection = chunkPacketInfoAntiXray.getChunk().getSections()[chunkSectionIndex + 1]) != LevelChunk.EMPTY_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[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(aboveChunkSection.getBlockState(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.getChunkPacket().setReady(true); ++ } ++ ++ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, LevelChunkSection[] 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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[2].getBlockState(0, y, 15))] || nearbyChunkSections[0] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[0].getBlockState(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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[2].getBlockState(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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[2].getBlockState(15, y, 15))] || nearbyChunkSections[1] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[1].getBlockState(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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[0].getBlockState(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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[1].getBlockState(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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[3].getBlockState(0, y, 0))] || nearbyChunkSections[0] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[0].getBlockState(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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[3].getBlockState(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] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[3].getBlockState(15, y, 0))] || nearbyChunkSections[1] == LevelChunk.EMPTY_SECTION || !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(nearbyChunkSections[1].getBlockState(0, y, 15))] || current[15][15]) { ++ dataBitsWriter.skip(); ++ } else { ++ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]); ++ } ++ } ++ ++ if (!obfuscate[dataBits]) { ++ next[15][15] = true; ++ } ++ } ++ ++ private boolean[] readDataPalette(Palette dataPalette, boolean[] temp, boolean[] global) { ++ if (dataPalette == LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE) { ++ return global; ++ } ++ ++ BlockState blockData; ++ ++ for (int i = 0; (blockData = dataPalette.valueFor(i)) != null; i++) { ++ temp[i] = global[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(blockData)]; ++ } ++ ++ return temp; ++ } ++ ++ @Override ++ public void onBlockChange(Level world, BlockPos blockPosition, BlockState newBlockData, BlockState oldBlockData, int flag) { ++ if (oldBlockData != null && solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(oldBlockData)] && !solidGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(newBlockData)] && blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(world, blockPosition); ++ } ++ } ++ ++ @Override ++ public void onPlayerLeftClickBlock(ServerPlayerGameMode playerInteractManager, BlockPos blockPosition, Direction enumDirection) { ++ if (blockPosition.getY() <= maxBlockYUpdatePosition) { ++ updateNearbyBlocks(playerInteractManager.level, blockPosition); ++ } ++ } ++ ++ private void updateNearbyBlocks(Level world, BlockPos blockPosition) { ++ if (updateRadius >= 2) { ++ BlockPos temp = blockPosition.west(); ++ updateBlock(world, temp); ++ updateBlock(world, temp.west()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.east()); ++ updateBlock(world, temp.east()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.above()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.below()); ++ updateBlock(world, temp.below()); ++ updateBlock(world, temp.north()); ++ updateBlock(world, temp.south()); ++ updateBlock(world, temp = blockPosition.above()); ++ updateBlock(world, temp.above()); ++ 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.below()); ++ updateBlock(world, blockPosition.above()); ++ updateBlock(world, blockPosition.north()); ++ updateBlock(world, blockPosition.south()); ++ } else { ++ // Do nothing if updateRadius <= 0 (test mode) ++ } ++ } ++ ++ private void updateBlock(Level world, BlockPos blockPosition) { ++ BlockState blockData = world.getTypeIfLoaded(blockPosition); ++ ++ if (blockData != null && obfuscateGlobal[LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE.idFor(blockData)]) { ++ // world.notify(blockPosition, blockData, blockData, 3); ++ ((ServerLevel)world).getChunkSource().blockChanged(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.ClientboundLevelChunkPacket; ++import net.minecraft.world.level.chunk.LevelChunk; ++import net.minecraft.world.level.chunk.Palette; ++ ++public class ChunkPacketInfo { ++ ++ private final ClientboundLevelChunkPacket chunkPacket; ++ private final LevelChunk chunk; ++ private byte[] data; ++ private final int[] bitsPerObject; ++ private final Object[] dataPalettes; ++ private final int[] dataBitsIndexes; ++ private final Object[][] predefinedObjects; ++ ++ public ChunkPacketInfo(ClientboundLevelChunkPacket chunkPacket, LevelChunk chunk) { ++ this.chunkPacket = chunkPacket; ++ this.chunk = chunk; ++ ++ int sections = chunk.getSectionsCount(); ++ this.bitsPerObject = new int[sections]; ++ this.dataPalettes = new Object[sections]; ++ this.dataBitsIndexes = new int[sections]; ++ this.predefinedObjects = new Object[sections][]; ++ } ++ ++ public ClientboundLevelChunkPacket getChunkPacket() { ++ return chunkPacket; ++ } ++ ++ public LevelChunk getChunk() { ++ return chunk; ++ } ++ ++ 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 Palette getDataPalette(int chunkSectionIndex) { ++ return (Palette) dataPalettes[chunkSectionIndex]; ++ } ++ ++ public void setDataPalette(int chunkSectionIndex, Palette 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.ClientboundLevelChunkPacket; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.LevelChunk; ++ ++public final class ChunkPacketInfoAntiXray extends ChunkPacketInfo implements Runnable { ++ ++ private LevelChunk[] nearbyChunks; ++ private final ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray; ++ ++ public ChunkPacketInfoAntiXray(ClientboundLevelChunkPacket packetPlayOutMapChunk, LevelChunk chunk, ++ ChunkPacketBlockControllerAntiXray chunkPacketBlockControllerAntiXray) { ++ super(packetPlayOutMapChunk, chunk); ++ this.chunkPacketBlockControllerAntiXray = chunkPacketBlockControllerAntiXray; ++ } ++ ++ public LevelChunk[] getNearbyChunks() { ++ return nearbyChunks; ++ } ++ ++ public void setNearbyChunks(LevelChunk... 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/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo = modifyBlocks ? chunk.level.chunkPacketBlockController.getChunkPacketInfo(this, chunk) : null; ++ // Paper end + ChunkPos chunkPos = chunk.getPos(); + this.x = chunkPos.x; + this.z = chunkPos.z; +@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet chunkPacketInfo) { ++ // Paper end + BitSet bitSet = new BitSet(); + LevelChunkSection[] levelChunkSections = chunk.getSections(); + int i = 0; +@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { +- packets[0] = new ClientboundLevelChunkPacket(chunk); ++ packets[0] = new ClientboundLevelChunkPacket(chunk, chunk.level.chunkPacketBlockController.shouldModify(player, chunk)); // Paper - Ani-Xray - Bypass + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error +- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env); ++ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper - pass executor + this.pvpMode = minecraftserver.isPvpAllowed(); + this.convertable = convertable_conversionsession; + this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile()); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ import org.bukkit.event.player.PlayerInteractEvent; + public class ServerPlayerGameMode { + + private static final Logger LOGGER = LogManager.getLogger(); +- protected ServerLevel level; ++ public ServerLevel level; // Paper - protected->public + protected final ServerPlayer player; + private GameType gameModeForPlayer; + @Nullable +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + } + + } ++ ++ this.level.chunkPacketBlockController.onPlayerLeftClickBlock(this, pos, direction); // Paper - Anti-Xray + } + + public void destroyAndAck(BlockPos pos, ServerboundPlayerActionPacket.Action action, String reason) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + + public final com.destroystokyo.paper.PaperWorldConfig paperConfig; // Paper ++ public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + + public final co.aikar.timings.WorldTimingsHandler timings; // Paper + public static BlockPos lastPhysicsProblem; // Spigot +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return this.typeKey; + } + +- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType dimensionmanager, Supplier supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { ++ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType 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.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot + this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper + this.generator = gen; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.keepSpawnInMemory = this.paperConfig.keepSpawnInMemory; // Paper + this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); ++ this.chunkPacketBlockController = this.paperConfig.antiXray ? ++ new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) ++ : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + } + + // Paper start +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit end + + BlockState iblockdata1 = chunk.setType(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag ++ this.chunkPacketBlockController.onBlockChange(this, pos, state, iblockdata1, flags); // 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/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -0,0 +0,0 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + default LevelChunkSection getOrCreateSection(int yIndex) { + LevelChunkSection[] levelChunkSections = this.getSections(); + if (levelChunkSections[yIndex] == LevelChunk.EMPTY_SECTION) { +- levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex)); ++ levelChunkSections[yIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(yIndex), this, getServerLevel(), true); + } + + return levelChunkSections[yIndex]; + } + ++ // Paper start ++ default net.minecraft.server.level.ServerLevel getServerLevel() { ++ return null; ++ } ++ // Paper end ++ + Collection> getHeightmaps(); + + default void setHeightmap(Heightmap.Types type, long[] heightmap) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +@@ -0,0 +0,0 @@ public class EmptyLevelChunk extends LevelChunk { + private static final Biome[] EMPTY_BIOMES = new Biome[0]; + + public EmptyChunkBiomeContainer(Level world) { +- super(world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), world, EMPTY_BIOMES); ++ super(net.minecraft.server.MinecraftServer.getServer().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), world, EMPTY_BIOMES); // Paper - world isnt ready yet for anti xray use here, use server singleton for registry + } + + @Override +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + return null; + } + +- chunksection = new LevelChunkSection(SectionPos.blockToSectionCoord(i)); ++ chunksection = new LevelChunkSection(SectionPos.blockToSectionCoord(i), this, this.level, true); // Paper - Anti-Xray - Add parameters + this.sections[j] = chunksection; + } + +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + return "Level ticker for " + s + "@" + this.getPos(); + } + } ++ ++ // Paper start ++ @Override ++ public net.minecraft.server.level.ServerLevel getServerLevel() { ++ return level; ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -0,0 +0,0 @@ public class LevelChunkSection { + private short tickingFluidCount; + final PalettedContainer states; // Paper - package-private + +- public LevelChunkSection(int yOffset) { +- this(yOffset, (short)0, (short)0, (short)0); ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere ++ public LevelChunkSection(int yOffset, ChunkAccess chunk, net.minecraft.server.level.ServerLevel world, boolean initializeBlocks) { ++ // Paper end ++ this(yOffset, (short) 0, (short) 0, (short) 0, chunk, world, initializeBlocks); + } + +- public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { ++ // Paper start - Anti-Xray - Add parameters ++ @Deprecated public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount) { // Notice for updates: Please make sure this constructor isn't used anywhere ++ this(yOffset, nonEmptyBlockCount, randomTickableBlockCount, nonEmptyFluidCount, null, null, true); ++ } ++ public LevelChunkSection(int yOffset, short nonEmptyBlockCount, short randomTickableBlockCount, short nonEmptyFluidCount, ChunkAccess chunk, net.minecraft.server.level.ServerLevel world, boolean initializeBlocks) { ++ // Paper end + this.bottomBlockY = getBottomBlockY(yOffset); + this.nonEmptyBlockCount = nonEmptyBlockCount; + this.tickingBlockCount = randomTickableBlockCount; + this.tickingFluidCount = nonEmptyFluidCount; +- this.states = new PalettedContainer<>(GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); ++ this.states = new PalettedContainer<>(GLOBAL_BLOCKSTATE_PALETTE, Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), ++ world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data + } + + public static int getBottomBlockY(int chunkPos) { +@@ -0,0 +0,0 @@ public class LevelChunkSection { + this.states.read(buf); + } + +- public void write(FriendlyByteBuf buf) { ++ // Paper start ++ @Deprecated public void write(FriendlyByteBuf buf) { write(buf, null); } // Notice for updates: Please make sure this method isn't used anywhere ++ public void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo) { ++ // Paper end + buf.writeShort(this.nonEmptyBlockCount); +- this.states.write(buf); ++ this.states.write(buf, chunkPacketInfo, this.bottomBlockY); // Paper - Anti-Xray - Add chunk packet info + } + + public int getSerializedSize() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + private final Function reader; + private final Function writer; + private final T defaultValue; ++ private final T[] predefinedObjects; // Paper - Anti-Xray - Add predefined objects + protected BitStorage storage; + private Palette palette; + private int bits; +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + this.lock.release(); + } + +- public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { ++ // Paper start - Anti-Xray - Add predefined objects ++ @Deprecated public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement) { // Notice for updates: Please make sure this constructor isn't used anywhere ++ this(fallbackPalette, idList, elementDeserializer, elementSerializer, defaultElement, null, true); ++ } ++ public PalettedContainer(Palette fallbackPalette, IdMapper idList, Function elementDeserializer, Function elementSerializer, T defaultElement, T[] predefinedObjects, boolean initialize) { ++ // Paper end + this.globalPalette = fallbackPalette; + this.registry = idList; + this.reader = elementDeserializer; + this.writer = elementSerializer; + this.defaultValue = defaultElement; + this.setBits(4); ++ // Paper start - Anti-Xray - Add predefined objects ++ this.predefinedObjects = predefinedObjects; ++ ++ if (initialize) { ++ if (predefinedObjects == null) { ++ // Default ++ this.setBits(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.setBits((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.palette != this.globalPalette) { ++ for (T predefinedObject : this.predefinedObjects) { ++ this.palette.idFor(predefinedObject); ++ } ++ } ++ } ++ // Paper end ++ + private static int getIndex(int x, int y, int z) { + return y << 8 | z << 4 | x; + } +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + Palette palette = this.palette; + this.setBits(newSize); + ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + for(int i = 0; i < bitStorage.getSize(); ++i) { + T object = palette.valueFor(bitStorage.get(i)); + if (object != null) { +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + + } + +- public void write(FriendlyByteBuf buf) { ++ // Paper start - Anti-Xray - Add chunk packet info ++ @Deprecated public void write(FriendlyByteBuf buf) { ++ write(buf, null, 0); ++ } ++ public void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int bottomBlockY) { ++ // Paper end + try { + this.acquire(); + buf.writeByte(this.bits); + this.palette.write(buf); ++ // Paper start - Anti-Xray - Add chunk packet info ++ if (chunkPacketInfo != null) { ++ // Bottom block to 0 based chunk section index ++ int section = (bottomBlockY >> 4) - chunkPacketInfo.getChunk().getMinSection(); ++ chunkPacketInfo.setBitsPerObject(section, this.bits); ++ chunkPacketInfo.setDataPalette(section, this.palette); ++ chunkPacketInfo.setDataBitsIndex(section, buf.writerIndex() + FriendlyByteBuf.getVarIntSize(this.storage.getRaw().length)); ++ chunkPacketInfo.setPredefinedObjects(section, this.predefinedObjects); ++ } ++ // Paper end + buf.writeLongArray(this.storage.getRaw()); + } finally { + this.release(); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + public void read(ListTag paletteNbt, long[] data) { + try { + this.acquire(); +- int i = Math.max(4, Mth.ceillog2(paletteNbt.size())); +- if (i != this.bits) { ++ // 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, Mth.ceillog2(paletteNbt.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects ++ if (true || i != this.bits) { // Paper - Anti-Xray - Not initialized yet + this.setBits(i); + } + + this.palette.read(paletteNbt); ++ this.addPredefinedObjects(); // Paper - Anti-Xray - Add predefined objects + int j = data.length * 64 / 4096; + if (this.palette == this.globalPalette) { + Palette palette = new HashMapPalette<>(this.registry, i, this.dummyPaletteResize, this.reader, this.writer); +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 ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks = new Object2ObjectArrayMap<>(); + private volatile boolean isLightCorrect; +- final net.minecraft.world.level.Level level; // Paper - Add level ++ final net.minecraft.server.level.ServerLevel level; // Paper - Add level + + // Paper start - add level + @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); } +@@ -0,0 +0,0 @@ public class ProtoChunk implements ChunkAccess { + this.postProcessing = new ShortList[world.getSectionsCount()]; + } + ++ // Paper start ++ @Override ++ public net.minecraft.server.level.ServerLevel getServerLevel() { ++ return level; ++ } ++ // Paper end ++ + // Paper start - If loaded util + @Override + public FluidState getFluidIfLoaded(BlockPos blockposition) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { + byte b0 = nbttagcompound2.getByte("Y"); + + if (nbttagcompound2.contains("Palette", 9) && nbttagcompound2.contains("BlockStates", 12)) { +- LevelChunkSection chunksection = new LevelChunkSection(b0); ++ LevelChunkSection chunksection = new LevelChunkSection(b0, null, world, false); // Paper - Anti-Xray - Add parameters + + chunksection.getStates().read(nbttagcompound2.getList("Palette", 10), nbttagcompound2.getLongArray("BlockStates")); + chunksection.recalcBlockCounts(); +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 ServerLevel worldServer; + private final int x; + private final int z; +- private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0).getStates(); ++ private static final PalettedContainer emptyBlockIDs = new LevelChunkSection(0, null, null, true).getStates(); // Paper - Anti-Xray - Add parameters + private static final byte[] emptyLight = new byte[2048]; + + public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { +@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { + CompoundTag data = new CompoundTag(); + cs[i].getStates().write(data, "Palette", "BlockStates"); + +- PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState()); // TODO: snapshot whole ChunkSection ++ PalettedContainer blockids = new PalettedContainer<>(LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE, net.minecraft.world.level.block.Block.BLOCK_STATE_REGISTRY, NbtUtils::readBlockState, NbtUtils::writeBlockState, Blocks.AIR.defaultBlockState(), 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.read(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 LevelChunkSection[] sections; + private Set tiles; ++ private World world; // Paper - Anti-Xray - Add world + + public CraftChunkData(World world) { + this(world.getMinHeight(), world.getMaxHeight()); ++ this.world = world; // Paper - Anti-Xray - Add world + } + + /* pp for tests */ CraftChunkData(int minHeight, int maxHeight) { +@@ -0,0 +0,0 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData { + int offset = (y - this.minHeight) >> 4; + LevelChunkSection section = this.sections[offset]; + if (create && section == null) { +- this.sections[offset] = section = new LevelChunkSection(offset + (this.minHeight >> 4)); ++ this.sections[offset] = section = new LevelChunkSection(offset + (this.minHeight >> 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/patches/server/AnvilDamageEvent.patch similarity index 57% rename from Spigot-Server-Patches/AnvilDamageEvent.patch rename to patches/server/AnvilDamageEvent.patch index 3e0d4b69e2..403d8b8b9d 100644 --- a/Spigot-Server-Patches/AnvilDamageEvent.patch +++ b/patches/server/AnvilDamageEvent.patch @@ -4,15 +4,14 @@ 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 +diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.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 { +--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java +@@ -0,0 +0,0 @@ public class AnvilMenu extends ItemCombinerMenu { + if (!player.getAbilities().instabuild && iblockdata.is((Tag) BlockTags.ANVIL) && player.getRandom().nextFloat() < 0.12F) { + BlockState iblockdata1 = AnvilBlock.damage(iblockdata); - 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()) { @@ -20,9 +19,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } 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)); ++ iblockdata1 = ((org.bukkit.craftbukkit.block.data.CraftBlockData) event.getDamageState().getMaterial().createBlockData()).getState().setValue(AnvilBlock.FACING, iblockdata.getValue(AnvilBlock.FACING)); + } + // Paper end if (iblockdata1 == null) { - world.a(blockposition, false); - world.triggerEffect(1029, blockposition, 0); + world.removeBlock(blockposition, false); + world.levelEvent(1029, blockposition, 0); diff --git a/patches/server/Async-command-map-building.patch b/patches/server/Async-command-map-building.patch new file mode 100644 index 0000000000..292c80fe03 --- /dev/null +++ b/patches/server/Async-command-map-building.patch @@ -0,0 +1,72 @@ +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/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -0,0 +0,0 @@ import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundCommandsPacket; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.commands.AdvancementCommands; + import net.minecraft.server.commands.AttributeCommand; + import net.minecraft.server.commands.BanIpCommands; +@@ -0,0 +0,0 @@ public class Commands { + 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(player); ++ }); ++ } ++ ++ private void sendAsync(ServerPlayer entityplayer) { ++ // Paper end - Async command map building + Map, CommandNode> map = Maps.newIdentityHashMap(); // Use identity to prevent aliasing issues + RootCommandNode vanillaRoot = new RootCommandNode(); + +- RootCommandNode vanilla = player.server.vanillaCommandDispatcher.getDispatcher().getRoot(); ++ RootCommandNode vanilla = entityplayer.server.vanillaCommandDispatcher.getDispatcher().getRoot(); + map.put(vanilla, vanillaRoot); +- this.fillUsableCommands(vanilla, vanillaRoot, player.createCommandSourceStack(), (Map) map); ++ this.fillUsableCommands(vanilla, vanillaRoot, entityplayer.createCommandSourceStack(), (Map) map); + + // Now build the global commands in a second pass + RootCommandNode rootcommandnode = new RootCommandNode(); + + map.put(this.dispatcher.getRoot(), rootcommandnode); +- this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, player.createCommandSourceStack(), (Map) map); ++ this.fillUsableCommands(this.dispatcher.getRoot(), rootcommandnode, entityplayer.createCommandSourceStack(), (Map) map); + + Collection bukkit = new LinkedHashSet<>(); + for (CommandNode node : rootcommandnode.getChildren()) { + bukkit.add(node.getName()); + } ++ // Paper start - Async command map building ++ MinecraftServer.getServer().execute(() -> { ++ runSync(entityplayer, bukkit, rootcommandnode); ++ }); ++ } + +- PlayerCommandSendEvent event = new PlayerCommandSendEvent(player.getBukkitEntity(), new LinkedHashSet<>(bukkit)); ++ private void runSync(ServerPlayer 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); + + // Remove labels that were removed during the event +@@ -0,0 +0,0 @@ public class Commands { + } + } + // CraftBukkit end +- player.connection.send(new ClientboundCommandsPacket(rootcommandnode)); ++ entityplayer.connection.send(new ClientboundCommandsPacket(rootcommandnode)); + } + + private void fillUsableCommands(CommandNode tree, CommandNode result, CommandSourceStack source, Map, CommandNode> resultNodes) { diff --git a/Spigot-Server-Patches/AsyncTabCompleteEvent.patch b/patches/server/AsyncTabCompleteEvent.patch similarity index 71% rename from Spigot-Server-Patches/AsyncTabCompleteEvent.patch rename to patches/server/AsyncTabCompleteEvent.patch index 17de52ce5d..d6f8071a7c 100644 --- a/Spigot-Server-Patches/AsyncTabCompleteEvent.patch +++ b/patches/server/AsyncTabCompleteEvent.patch @@ -13,33 +13,33 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override - public void a(PacketPlayInTabComplete packetplayintabcomplete) { -- PlayerConnectionUtils.ensureMainThread(packetplayintabcomplete, this, this.player.getWorldServer()); + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + // 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 + if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { +- this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0])); ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper return; } // CraftBukkit end -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser stringreader.skip(); } -- ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); +- ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + // 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, ++ String buffer = packet.getCommand(); ++ event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), completions, + buffer, true, null); + event.callEvent(); + completions = event.isCancelled() ? com.google.common.collect.ImmutableList.of() : event.getCompletions(); @@ -47,25 +47,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!event.isHandled()) { + if (!event.isCancelled()) { -- this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { - if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); +- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); - }); -+ this.minecraftServer.scheduleOnMain(() -> { // Paper - This needs to be on main -+ ParseResults parseresults = this.minecraftServer.getCommandDispatcher().a().parse(stringreader, this.player.getCommandListener()); ++ this.server.scheduleOnMain(() -> { // Paper - This needs to be on main ++ ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + -+ this.minecraftServer.getCommandDispatcher().a().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { ++ this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { + if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -+ this.networkManager.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), suggestions)); ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); + }); + }); + } + } 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 builder = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); + + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); + completions.forEach(builder::suggest); -+ player.playerConnection.sendPacket(new PacketPlayOutTabComplete(packetplayintabcomplete.b(), builder.buildFuture().join())); ++ player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), builder.buildFuture().join())); + } + // Paper end - async tab completion } @@ -76,12 +76,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + offers = this.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); ++ TabCompleteEvent tabEvent = new TabCompleteEvent(player, message, offers, message.startsWith("/") || forceCommand, pos != null ? net.minecraft.server.MCUtil.toLocation(((CraftWorld) player.getWorld()).getHandle(), new BlockPos(pos)) : null); // Paper + this.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 diff --git a/Spigot-Server-Patches/Asynchronous-chunk-IO-and-loading.patch b/patches/server/Asynchronous-chunk-IO-and-loading.patch similarity index 59% rename from Spigot-Server-Patches/Asynchronous-chunk-IO-and-loading.patch rename to patches/server/Asynchronous-chunk-IO-and-loading.patch index 06c10d22ec..70a05f3f46 100644 --- a/Spigot-Server-Patches/Asynchronous-chunk-IO-and-loading.patch +++ b/patches/server/Asynchronous-chunk-IO-and-loading.patch @@ -132,15 +132,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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() + " - "; + public WorldTimingsHandler(Level server) { + String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; @@ -0,0 +0,0 @@ public class WorldTimingsHandler { @@ -151,7 +150,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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"); @@ -159,37 +157,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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; + public static Timing getTickList(ServerLevel worldserver, String 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 @@ -202,8 +170,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); + } + tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit); } + + public static boolean asyncChunks = false; @@ -332,10 +300,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.io; + -+import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.WorldServer; -+import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.chunk.storage.RegionFile; +import org.apache.logging.log4j.Logger; + @@ -364,13 +332,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + *

+ * + * @see Holder#INSTANCE -+ * @see #scheduleSave(WorldServer, int, int, NBTTagCompound, NBTTagCompound, int) -+ * @see #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean) ++ * @see #scheduleSave(ServerLevel, int, int, CompoundTag, CompoundTag, int) ++ * @see #loadChunkDataAsync(ServerLevel, 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 CompoundTag FAILURE_VALUE = new CompoundTag(); + + public static final class Holder { + @@ -420,7 +388,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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) { ++ public void bumpPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { + if (!PrioritizedTaskQueue.validPriority(priority)) { + throw new IllegalArgumentException("Invalid priority: " + priority); + } @@ -438,7 +406,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ public NBTTagCompound getPendingWrite(final WorldServer world, final int chunkX, final int chunkZ, final boolean poiData) { ++ public CompoundTag getPendingWrite(final ServerLevel 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))); @@ -463,7 +431,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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) { ++ public void setPriority(final ServerLevel world, final int chunkX, final int chunkZ, final int priority) { + if (!PrioritizedTaskQueue.validPriority(priority)) { + throw new IllegalArgumentException("Invalid priority: " + priority); + } @@ -502,8 +470,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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, ++ public void scheduleSave(final ServerLevel world, final int chunkX, final int chunkZ, ++ final CompoundTag poiData, final CompoundTag chunkData, + final int priority) throws IllegalArgumentException { + if (!PrioritizedTaskQueue.validPriority(priority)) { + throw new IllegalArgumentException("Invalid priority: " + priority); @@ -519,8 +487,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private void scheduleWrite(final ChunkDataController dataController, final WorldServer world, -+ final int chunkX, final int chunkZ, final NBTTagCompound data, final int priority, final long writeCounter) { ++ private void scheduleWrite(final ChunkDataController dataController, final ServerLevel world, ++ final int chunkX, final int chunkZ, final CompoundTag 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 @@ -560,14 +528,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * Same as {@link #loadChunkDataAsync(ServerLevel, 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, ++ public CompletableFuture loadChunkDataAsyncFuture(final ServerLevel world, final int chunkX, final int chunkZ, + final int priority, final boolean readPoiData, final boolean readChunkData, + final boolean intendingToBlock) { + final CompletableFuture future = new CompletableFuture<>(); @@ -602,7 +570,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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, ++ public void loadChunkDataAsync(final ServerLevel world, final int chunkX, final int chunkZ, + final int priority, final Consumer onComplete, + final boolean readPoiData, final boolean readChunkData, + final boolean intendingToBlock) { @@ -618,7 +586,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final boolean[] requireCompletion = new boolean[] { readPoiData, readChunkData }; + + if (readPoiData) { -+ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final NBTTagCompound poiData) -> { ++ this.scheduleRead(world.poiDataController, world, chunkX, chunkZ, (final CompoundTag poiData) -> { + complete.poiData = poiData; + + final boolean finished; @@ -637,7 +605,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + if (readChunkData) { -+ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final NBTTagCompound chunkData) -> { ++ this.scheduleRead(world.chunkDataController, world, chunkX, chunkZ, (final CompoundTag chunkData) -> { + complete.chunkData = chunkData; + + final boolean finished; @@ -658,15 +626,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + // 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, ++ private void scheduleRead(final ChunkDataController dataController, final ServerLevel 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))); ++ return Boolean.valueOf(file.hasChunk(new ChunkPos(chunkX, chunkZ))); + }; + + dataController.tasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkDataTask running) -> { @@ -707,11 +675,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + /** -+ * Same as {@link #loadChunkDataAsync(WorldServer, int, int, int, Consumer, boolean, boolean, boolean)}, except this function returns ++ * Same as {@link #loadChunkDataAsync(ServerLevel, 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, ++ public ChunkData loadChunkData(final ServerLevel 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(); + } @@ -750,12 +718,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public static final class ChunkData { + -+ public NBTTagCompound poiData; -+ public NBTTagCompound chunkData; ++ public CompoundTag poiData; ++ public CompoundTag chunkData; + + public ChunkData() {} + -+ public ChunkData(final NBTTagCompound poiData, final NBTTagCompound chunkData) { ++ public ChunkData(final CompoundTag poiData, final CompoundTag chunkData) { + this.poiData = poiData; + this.chunkData = chunkData; + } @@ -766,19 +734,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 void writeData(final int x, final int z, final CompoundTag compound) throws IOException; ++ public abstract CompoundTag 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 CompoundTag data; + } + + public static final class InProgressRead { -+ public final CompletableFuture readFuture = new CompletableFuture<>(); ++ public final CompletableFuture readFuture = new CompletableFuture<>(); + } + } + @@ -787,12 +755,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public ChunkDataController.InProgressWrite inProgressWrite; + public ChunkDataController.InProgressRead inProgressRead; + -+ private final WorldServer world; ++ private final ServerLevel 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) { ++ public ChunkDataTask(final int priority, final ServerLevel world, final int x, final int z, final ChunkDataController taskController) { + super(priority); + this.world = world; + this.x = x; @@ -835,7 +803,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void run() { + ChunkDataController.InProgressRead read = this.inProgressRead; + if (read != null) { -+ NBTTagCompound compound = PaperFileIOThread.FAILURE_VALUE; ++ CompoundTag compound = PaperFileIOThread.FAILURE_VALUE; + try { + compound = this.taskController.readData(this.x, this.z); + } catch (final Throwable thr) { @@ -884,7 +852,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +*/ + for (;;) { + final long writeCounter; -+ final NBTTagCompound data; ++ final CompoundTag data; + + //noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (write) { @@ -1477,34 +1445,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; + +public final class ChunkLoadTask extends ChunkTask { + + public boolean cancelled; + -+ Consumer onComplete; ++ Consumer onComplete; + public PaperFileIOThread.ChunkData chunkData; + + private boolean hasCompleted; + -+ public ChunkLoadTask(final WorldServer world, final int chunkX, final int chunkZ, final int priority, ++ public ChunkLoadTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, + final ChunkTaskManager taskManager, -+ final Consumer onComplete) { ++ 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); ++ private static ChunkSerializer.InProgressChunkHolder createEmptyHolder() { ++ return new ChunkSerializer.InProgressChunkHolder(null, EMPTY_QUEUE); + } + + @Override @@ -1556,18 +1523,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ final ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(this.chunkX, this.chunkZ); ++ final ChunkPos chunkPos = new ChunkPos(this.chunkX, this.chunkZ); + -+ final PlayerChunkMap chunkManager = this.world.getChunkProvider().playerChunkMap; ++ final ChunkMap chunkManager = this.world.getChunkSource().chunkMap; + + try (Timing ignored = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { -+ final ChunkRegionLoader.InProgressChunkHolder chunkHolder; ++ final ChunkSerializer.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 ++ chunkManager.overworldDataStorage, 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()); @@ -1578,15 +1545,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + 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, ++ chunkHolder = ChunkSerializer.loadChunk(this.world, ++ chunkManager.structureManager, chunkManager.getVillagePlace(), chunkPos, + chunkData.chunkData, true); + } catch (final Throwable ex) { + PaperFileIOThread.LOGGER.error("Could not de-serialize chunk data for task: " + this.toString(), ex); @@ -1598,7 +1558,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private void complete(final ChunkRegionLoader.InProgressChunkHolder holder) { ++ private void complete(final ChunkSerializer.InProgressChunkHolder holder) { + this.hasCompleted = true; + holder.poiData = this.chunkData == null ? null : this.chunkData.poiData; + @@ -1633,22 +1593,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +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; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; + +public final class ChunkSaveTask extends ChunkTask { + -+ public final ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ public final IChunkAccess chunk; -+ public final CompletableFuture onComplete = new CompletableFuture<>(); ++ public final ChunkSerializer.AsyncSaveData asyncSaveData; ++ public final ChunkAccess 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) { ++ public ChunkSaveTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, ++ final ChunkTaskManager taskManager, final ChunkSerializer.AsyncSaveData asyncSaveData, ++ final ChunkAccess chunk) { + super(world, chunkX, chunkZ, priority, taskManager); + this.chunk = chunk; + this.asyncSaveData = asyncSaveData; @@ -1658,10 +1618,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public void run() { + // can be executed asynchronously or synchronously -+ final NBTTagCompound compound; ++ final CompoundTag compound; + + try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTimingIfSync()) { -+ compound = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ compound = ChunkSerializer.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); @@ -1670,10 +1630,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // when waiting for chunks + ChunkTaskManager.queueChunkWaitTask(() -> { + try (Timing ignored = this.world.timings.chunkUnloadDataSave.startTiming()) { -+ NBTTagCompound data = PaperFileIOThread.FAILURE_VALUE; ++ CompoundTag data = PaperFileIOThread.FAILURE_VALUE; + + try { -+ data = ChunkRegionLoader.saveChunk(this.world, this.chunk, this.asyncSaveData); ++ data = ChunkSerializer.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); @@ -1718,7 +1678,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return super.updatePriority(priority); + } + -+ private void complete(final NBTTagCompound compound) { ++ private void complete(final CompoundTag compound) { + try { + this.onComplete.complete(compound); + } catch (final Throwable thr) { @@ -1745,16 +1705,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import com.destroystokyo.paper.io.PaperFileIOThread; +import com.destroystokyo.paper.io.PrioritizedTaskQueue; -+import net.minecraft.server.level.WorldServer; ++import net.minecraft.server.level.ServerLevel; + +abstract class ChunkTask extends PrioritizedTaskQueue.PrioritizedTask implements Runnable { + -+ public final WorldServer world; ++ public final ServerLevel 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, ++ public ChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, final int priority, + final ChunkTaskManager taskManager) { + super(priority); + this.world = world; @@ -1793,15 +1753,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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.nbt.CompoundTag; +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.server.level.ChunkHolder; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.util.thread.BlockableEventLoop; ++import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; -+import net.minecraft.world.level.chunk.IChunkAccess; -+import net.minecraft.world.level.chunk.storage.ChunkRegionLoader; ++import net.minecraft.world.level.chunk.storage.ChunkSerializer; +import org.apache.commons.lang.StringUtils; +import org.apache.logging.log4j.Level; +import org.bukkit.Bukkit; @@ -1818,7 +1778,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +public final class ChunkTaskManager { + + private final QueueExecutorThread[] workers; -+ private final WorldServer world; ++ private final ServerLevel world; + + private final PrioritizedTaskQueue queue; + private final boolean perWorldQueue; @@ -1841,9 +1801,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public final int chunkX; + public final int chunkZ; -+ public final WorldServer world; ++ public final ServerLevel world; + -+ public ChunkInfo(final int chunkX, final int chunkZ, final WorldServer world) { ++ public ChunkInfo(final int chunkX, final int chunkZ, final ServerLevel world) { + this.chunkX = chunkX; + this.chunkZ = chunkZ; + this.world = world; @@ -1855,7 +1815,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ public static void pushChunkWait(final WorldServer world, final int chunkX, final int chunkZ) { ++ public static void pushChunkWait(final ServerLevel world, final int chunkX, final int chunkZ) { + synchronized (WAITING_CHUNKS) { + WAITING_CHUNKS.push(new ChunkInfo(chunkX, chunkZ, world)); + } @@ -1889,18 +1849,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ ChunkHolder chunkHolder = chunkInfo.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(key); + + dumpChunkInfo(new HashSet<>(), chunkHolder, chunkInfo.chunkX, chunkInfo.chunkZ); + } + } + } + -+ static void dumpChunkInfo(Set seenChunks, PlayerChunk chunkHolder, int x, int z) { ++ static void dumpChunkInfo(Set seenChunks, ChunkHolder 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) { ++ static void dumpChunkInfo(Set seenChunks, ChunkHolder chunkHolder, int x, int z, int indent, int maxDepth) { + if (seenChunks.contains(chunkHolder)) { + return; + } @@ -1912,11 +1872,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (chunkHolder == null) { + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder - null for (" + x +"," + z +")"); + } else { -+ IChunkAccess chunk = chunkHolder.getAvailableChunkNow(); ++ ChunkAccess chunk = chunkHolder.getLastAvailable(); + 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 Status - " + ((chunk == null) ? "null chunk" : chunk.getStatus().toString())); ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); + } + } @@ -1956,9 +1916,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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 ++ * @see ServerChunkCache#mainThreadProcessor + */ -+ public ChunkTaskManager(final WorldServer world, final int threads) { ++ public ChunkTaskManager(final ServerLevel world, final int threads) { + this.world = world; + this.workers = threads <= 0 ? null : new QueueExecutorThread[threads]; + this.queue = new PrioritizedTaskQueue<>(); @@ -1981,9 +1941,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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 ++ * @see ServerChunkCache#mainThreadProcessor + */ -+ public ChunkTaskManager(final WorldServer world) { ++ public ChunkTaskManager(final ServerLevel world) { + this.world = world; + this.workers = globalWorkers; + this.queue = globalQueue; @@ -2033,9 +1993,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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; ++ final Consumer onComplete, ++ final boolean intendingToBlock, final CompletableFuture dataFuture) { ++ final ServerLevel world = this.world; + + return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { + if (valueInMap != null) { @@ -2049,7 +2009,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + final ChunkLoadTask ret = new ChunkLoadTask(world, chunkX, chunkZ, priority, ChunkTaskManager.this, onComplete); + -+ dataFuture.thenAccept((final NBTTagCompound data) -> { ++ dataFuture.thenAccept((final CompoundTag data) -> { + final boolean failed = data == PaperFileIOThread.FAILURE_VALUE; + PaperFileIOThread.Holder.INSTANCE.loadChunkDataAsync(world, chunkX, chunkZ, priority, (final PaperFileIOThread.ChunkData chunkData) -> { + ret.chunkData = chunkData; @@ -2089,14 +2049,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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 onComplete The consumer to invoke with the {@link ChunkSerializer.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 Consumer onComplete, + final boolean intendingToBlock) { -+ final WorldServer world = this.world; ++ final ServerLevel world = this.world; + + return this.chunkLoadTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkLoadTask valueInMap) -> { + if (valueInMap != null) { @@ -2125,16 +2085,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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 asyncSaveData Async save data. See {@link ChunkSerializer#getAsyncSaveData(ServerLevel, ChunkAccess)} + * @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) { ++ final ChunkSerializer.AsyncSaveData asyncSaveData, ++ final ChunkAccess chunk) { + AsyncCatcher.catchOp("chunk save schedule"); + -+ final WorldServer world = this.world; ++ final ServerLevel world = this.world; + + return this.chunkSaveTasks.compute(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ)), (final Long keyInMap, final ChunkSaveTask valueInMap) -> { + if (valueInMap != null) { @@ -2155,7 +2115,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param chunkX Chunk's x coordinate + * @param chunkZ Chunk's z coordinate + */ -+ public CompletableFuture getChunkSaveFuture(final int chunkX, final int chunkZ) { ++ 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; @@ -2170,7 +2130,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @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) { ++ public ChunkAccess getChunkInSaveProgress(final int chunkX, final int chunkZ) { + final ChunkSaveTask chunkSaveTask = this.chunkSaveTasks.get(Long.valueOf(IOUtil.getCoordinateKey(chunkX, chunkZ))); + if (chunkSaveTask == null) { + return null; @@ -2186,11 +2146,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + if (this.workers == null) { + if (Bukkit.isPrimaryThread() || MinecraftServer.getServer().hasStopped()) { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); ++ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); + } else { + CompletableFuture wait = new CompletableFuture<>(); + MinecraftServer.getServer().scheduleOnMain(() -> { -+ ((IAsyncTaskHandler)this.world.getChunkProvider().serverThreadQueue).executeAll(); ++ ((BlockableEventLoop)this.world.getChunkSource().mainThreadProcessor).runAllTasks(); + }); + wait.join(); + } @@ -2300,16 +2260,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + +} -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayInTabComplete.java +diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.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); +--- a/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundCommandSuggestionPacket.java +@@ -0,0 +0,0 @@ public class ServerboundCommandSuggestionPacket implements Packet { - DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataConverterRegistry.a(), minecraftsessionservice, gameprofilerepository, usercache, WorldLoadListenerLogger::new); ++ Class.forName(net.minecraft.world.entity.npc.VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async + final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> { + DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataFixers.getDataFixer(), minecraftsessionservice, gameprofilerepository, usercache, LoggerChunkProgressListener::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 { +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + return chunkstatus; } - - 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; - } ++ 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); ++ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) { ++ CompletableFuture> future = this.getFutureIfPresentUnchecked(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); + return null; + } +@@ -0,0 +0,0 @@ public class ChunkHolder { + ChunkStatus chunkstatus = ChunkHolder.getStatus(this.oldTicketLevel); + ChunkStatus chunkstatus1 = ChunkHolder.getStatus(this.ticketLevel); + boolean flag = this.oldTicketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; +- boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; ++ boolean flag1 = this.ticketLevel <= ChunkMap.MAX_CHUNK_DISTANCE; // Paper - diff on change: (flag1 = new ticket level is in loadable range) + ChunkHolder.FullChunkStatus playerchunk_state = ChunkHolder.getFullChunkStatus(this.oldTicketLevel); + ChunkHolder.FullChunkStatus playerchunk_state1 = ChunkHolder.getFullChunkStatus(this.ticketLevel); // CraftBukkit start -@@ -0,0 +0,0 @@ public class PlayerChunk { +@@ -0,0 +0,0 @@ public class ChunkHolder { } }); + // Paper start + if (!flag1) { -+ playerchunkmap.world.asyncChunkTaskManager.cancelChunkLoad(this.location.x, this.location.z); ++ chunkStorage.level.asyncChunkTaskManager.cancelChunkLoad(this.pos.x, this.pos.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 + for (int i = flag1 ? chunkstatus1.getIndex() + 1 : 0; i <= chunkstatus.getIndex(); ++i) { + completablefuture = (CompletableFuture) this.futures.get(i); + if (completablefuture == null) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 { +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider 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(); + this.queueSorter.close(); ++ this.level.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line + this.poiManager.close(); } finally { super.close(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - this.b(() -> { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.processUnloads(() -> { return true; }); -- this.i(); -+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour +- this.flushWorker(); ++ this.level.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()); + ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); } else { - this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - 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(); + protected void tick(BooleanSupplier shouldKeepTicking) { + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); -+ try (Timing ignored = this.world.timings.poiUnload.startTiming()) { // Paper - gameprofilerfiller.enter("poi"); - this.m.a(booleansupplier); ++ try (Timing ignored = this.level.timings.poiUnload.startTiming()) { // Paper + gameprofilerfiller.push("poi"); + this.poiManager.tick(shouldKeepTicking); + } // Paper - gameprofilerfiller.exitEnter("chunk_unload"); - if (!this.world.isSavingDisabled()) { -+ try (Timing ignored = this.world.timings.chunkUnload.startTiming()) { // Paper - this.b(booleansupplier); + gameprofilerfiller.popPush("chunk_unload"); + if (!this.level.noSave()) { ++ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper + this.processUnloads(shouldKeepTicking); + }// Paper } - gameprofilerfiller.exit(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + gameprofilerfiller.pop(); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (playerchunk != null) { - this.pendingUnload.put(j, playerchunk); - this.updatingChunksModified = true; -+ this.a(j, playerchunk); // Paper - Move up - don't leak chunks + this.pendingUnloads.put(j, playerchunk); + this.modified = true; ++ this.scheduleUnload(j, playerchunk); // Paper - Move up - don't leak chunks // Spigot start - if (!booleansupplier.getAsBoolean() && this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { + if (!shouldKeepTicking.getAsBoolean() && this.toDrop.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { break; } // Spigot end -- this.a(j, playerchunk); +- this.scheduleUnload(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 { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } + // 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 ++ // This is also modeled after PlayerChunkMap#save(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()) { ++ private void asyncSave(ChunkAccess chunk) { ++ ChunkPos chunkPos = chunk.getPos(); ++ CompoundTag poiData; ++ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { + poiData = this.getVillagePlace().getData(chunk.getPos()); + } + -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z, ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z, + poiData, null, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY); + -+ if (!chunk.isNeedsSaving()) { ++ if (!chunk.isUnsaved()) { + return; + } + -+ ChunkStatus chunkstatus = chunk.getChunkStatus(); ++ ChunkStatus chunkstatus = chunk.getStatus(); + -+ // 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; -+ } ++ // Copied from PlayerChunkMap#save(IChunkAccess, boolean) ++ if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { ++ // Paper start - Optimize save by using status cache ++ if (chunkstatus == ChunkStatus.EMPTY && chunk.getAllStarts().values().stream().noneMatch(StructureStart::isValid)) { ++ return; + } + } + -+ ChunkRegionLoader.AsyncSaveData asyncSaveData; -+ try (Timing ignored = this.world.timings.chunkUnloadPrepareSave.startTiming()) { -+ asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk); ++ ChunkSerializer.AsyncSaveData asyncSaveData; ++ try (Timing ignored = this.level.timings.chunkUnloadPrepareSave.startTiming()) { ++ asyncSaveData = ChunkSerializer.getAsyncSaveData(this.level, chunk); + } + -+ this.world.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, ++ this.level.asyncChunkTaskManager.scheduleChunkSave(chunkPos.x, chunkPos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.LOW_PRIORITY, + asyncSaveData, chunk); + -+ chunk.setLastSaved(this.world.getTime()); -+ chunk.setNeedsSaving(false); ++ chunk.setUnsaved(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); + private void scheduleUnload(long pos, ChunkHolder holder) { + CompletableFuture completablefuture = holder.getChunkToSave(); + Consumer consumer = (ichunkaccess) -> { // CraftBukkit - decompile error +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ((LevelChunk) 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 - +- this.save(ichunkaccess); ++ // Paper start - async chunk saving + try { -+ this.asyncSave(ichunkaccess); // Paper - async chunk saving ++ this.asyncSave(ichunkaccess); ++ } catch (ThreadDeath ex) { ++ throw ex; // bye + } catch (Throwable ex) { + LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex); -+ this.saveChunk(ichunkaccess); ++ this.save(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 { ++ // Paper end - async chunk saving + if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { + LevelChunk chunk = (LevelChunk) ichunkaccess; + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { + private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { - 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); ++ final java.util.function.BiFunction> syncLoadComplete = (chunkHolder, ioThrowable) -> { + try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper + this.level.getProfiler().incrementCounter("chunkLoad"); +- CompoundTag nbttagcompound; // Paper +- try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings +- nbttagcompound = this.readChunk(pos); - } // 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); ++ ++ this.getVillagePlace().loadInData(pos, chunkHolder.poiData); + chunkHolder.tasks.forEach(Runnable::run); + // Paper end +- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings +- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); ++ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async + - 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 -+ +- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound); + 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.markPosition(pos, protochunk.getStatus().getChunkType()); + return Either.left(protochunk); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.g(chunkcoordintpair); - return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter -- }, this.executor); + this.markPositionReplaceable(pos); + return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); +- }, this.mainThreadExecutor); + // Paper start - Async chunk io + }; -+ CompletableFuture> ret = new CompletableFuture<>(); ++ CompletableFuture> ret = new CompletableFuture<>(); + -+ Consumer chunkHolderConsumer = (ChunkRegionLoader.InProgressChunkHolder holder) -> { ++ Consumer chunkHolderConsumer = (ChunkSerializer.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 { @@ -2846,78 +2533,75 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + }; + -+ CompletableFuture chunkSaveFuture = this.world.asyncChunkTaskManager.getChunkSaveFuture(chunkcoordintpair.x, chunkcoordintpair.z); ++ CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); + if (chunkSaveFuture != null) { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.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.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); + } else { -+ this.world.asyncChunkTaskManager.scheduleChunkLoad(chunkcoordintpair.x, chunkcoordintpair.z, ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.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 { + private void markPositionReplaceable(ChunkPos chunkcoordintpair) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - 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()) { + public boolean save(ChunkAccess chunk) { ++ try (co.aikar.timings.Timing ignored = this.level.timings.chunkSave.startTiming()) { // Paper + this.poiManager.flush(chunk.getPos()); + if (!chunk.isUnsaved()) { return false; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - ChunkStatus chunkstatus = ichunkaccess.getChunkStatus(); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkStatus chunkstatus = chunk.getStatus(); - if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { -+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper - if (this.h(chunkcoordintpair)) { + if (chunkstatus.getChunkType() != ChunkStatus.ChunkType.LEVELCHUNK) { +- if (this.isExistingChunkFull(chunkcoordintpair)) { ++ if (false && this.isExistingChunkFull(chunkcoordintpair)) { // Paper 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 + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - 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); + this.level.getProfiler().incrementCounter("chunkSave"); +- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); ++ CompoundTag nbttagcompound; ++ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper ++ nbttagcompound = ChunkSerializer.write(this.level, chunk); + } // Paper -+ -- this.a(chunkcoordintpair, nbttagcompound); +- this.write(chunkcoordintpair, nbttagcompound); ++ + // Paper start - async chunk io -+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkcoordintpair.x, chunkcoordintpair.z, ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, + null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); + // Paper end - async chunk io - this.a(chunkcoordintpair, chunkstatus.getType()); + this.markPosition(chunkcoordintpair, chunkstatus.getChunkType()); return true; } catch (Exception exception) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return false; } } + } // Paper } - private boolean h(ChunkCoordIntPair chunkcoordintpair) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } + // Paper start - Asynchronous chunk io + @Nullable + @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { ++ public CompoundTag read(ChunkPos 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(), ++ CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.level, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), + false, true, true).join().chunkData; + + if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { @@ -2929,10 +2613,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { ++ public void write(ChunkPos chunkcoordintpair, CompoundTag 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, ++ this.level, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound, + com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread()); + return; + } @@ -2941,178 +2625,222 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 { + private CompoundTag readChunk(ChunkPos pos) throws IOException { + CompoundTag nbttagcompound = this.read(pos); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // 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 ++ @Deprecated public PoiManager getVillagePlace() { return this.getPoiManager(); } // Paper - OBFHELPER + protected PoiManager getPoiManager() { + return this.poiManager; } - - 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 { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + return ret; } // 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 start - async chunk io ++ public ChunkAccess getChunkAtImmediately(int x, int z) { ++ ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); ++ if (holder == null) { ++ return null; + } -+ // 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); -+ } ++ return holder.getLastAvailable(); + } + - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start - return isOutsideOfRange(chunkcoordintpair, false); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { ++ private long asyncLoadSeqCounter; ++ ++ public CompletableFuture> getChunkAtAsynchronously(int x, int z, boolean gen, boolean isUrgent) { ++ if (Thread.currentThread() != this.mainThread) { ++ CompletableFuture> future = new CompletableFuture>(); ++ this.mainThreadProcessor.execute(() -> { ++ this.getChunkAtAsynchronously(x, z, gen, isUrgent).whenComplete((chunk, ex) -> { ++ if (ex != null) { ++ future.completeExceptionally(ex); ++ } else { ++ future.complete(chunk); ++ } ++ }); ++ }); ++ return future; ++ } ++ ++ long k = ChunkPos.asLong(x, z); ++ ChunkPos chunkPos = new ChunkPos(x, z); ++ ++ ChunkAccess ichunkaccess; ++ ++ // try cache ++ for (int l = 0; l < 4; ++l) { ++ if (k == this.lastChunkPos[l] && ChunkStatus.FULL == this.lastChunkStatus[l]) { ++ ichunkaccess = this.lastChunk[l]; ++ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime ++ ++ // move to first in cache ++ ++ for (int i1 = 3; i1 > 0; --i1) { ++ this.lastChunkPos[i1] = this.lastChunkPos[i1 - 1]; ++ this.lastChunkStatus[i1] = this.lastChunkStatus[i1 - 1]; ++ this.lastChunk[i1] = this.lastChunk[i1 - 1]; ++ } ++ ++ this.lastChunkPos[0] = k; ++ this.lastChunkStatus[0] = ChunkStatus.FULL; ++ this.lastChunk[0] = ichunkaccess; ++ ++ return CompletableFuture.completedFuture(Either.left(ichunkaccess)); ++ } ++ } ++ } ++ ++ if (gen) { ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ } ++ ++ ChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions ++ if (current != null) { ++ if (!(current instanceof net.minecraft.world.level.chunk.ImposterProtoChunk) && !(current instanceof LevelChunk)) { ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ // 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); ++ } ++ ++ // 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) -> { ++ ChunkAccess chunk = either.left().orElse(null); ++ if (!(chunk instanceof net.minecraft.world.level.chunk.ImposterProtoChunk) && !(chunk instanceof LevelChunk)) { ++ // the chunk on disk was not a full status chunk ++ return CompletableFuture.completedFuture(ChunkHolder.UNLOADED_CHUNK); ++ } ++ // bring to full status if required ++ return this.bringToFullStatusAsync(x, z, chunkPos, isUrgent); ++ }); ++ } ++ ++ private CompletableFuture> bringToFullStatusAsync(int x, int z, ChunkPos chunkPos, boolean isUrgent) { ++ return this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, isUrgent); ++ } ++ ++ private CompletableFuture> bringToStatusAsync(int x, int z, ChunkPos chunkPos, ChunkStatus status, boolean isUrgent) { ++ CompletableFuture> future = this.getChunkFutureMainThread(x, z, status, true, isUrgent); ++ Long identifier = Long.valueOf(this.asyncLoadSeqCounter++); ++ int ticketLevel = net.minecraft.server.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.mainThreadProcessor); ++ } ++ ++ public void addTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { ++ this.distanceManager.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } ++ ++ public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { ++ this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); ++ } ++ // Paper end - async chunk io + @Nullable + @Override + public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { ++ final int x1 = x; final int z1 = z; // Paper - conflict on variable change + if (Thread.currentThread() != this.mainThread) { + return (ChunkAccess) CompletableFuture.supplyAsync(() -> { + return this.getChunk(x, z, leastStatus, create); +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + } + + gameprofilerfiller.incrementCounter("getChunkCacheMiss"); +- CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); ++ CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper + ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor; + + Objects.requireNonNull(completablefuture); + if (!completablefuture.isDone()) { // Paper ++ // Paper start - async chunk io/loading ++ this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); ++ // Paper end + this.level.timings.syncChunkLoad.startTiming(); // Paper + chunkproviderserver_a.managedBlock(completablefuture::isDone); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.level.timings.syncChunkLoad.stopTiming(); // Paper + } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { } -+ 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 + 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 + ChunkPos chunkcoordintpair = new ChunkPos(i, j); + long k = chunkcoordintpair.toLong(); + int l = 33 + ChunkStatus.getDistance(chunkstatus); +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task + public boolean pollTask() { + try { ++ boolean execChunkTask = com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask(); // Paper + if (ServerChunkCache.this.runDistanceManagerUpdates()) { + return true; + } else { + ServerChunkCache.this.lightEngine.tryScheduleUpdate(); +- return super.pollTask(); ++ return super.pollTask() || execChunkTask; // Paper + } + } finally { + chunkMap.callbackExecutor.run(); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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); +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return this.chunkSource.getChunk(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); ++ public void writeData(int x, int z, net.minecraft.nbt.CompoundTag compound) throws java.io.IOException { ++ ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().write(new ChunkPos(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)); ++ public net.minecraft.nbt.CompoundTag readData(int x, int z) throws java.io.IOException { ++ return ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().read(new ChunkPos(x, z)); + } + + @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace()) { -+ RegionFile file; ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { ++ net.minecraft.world.level.chunk.storage.RegionFile file; + + try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); ++ file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getFile(new ChunkPos(chunkX, chunkZ), false); + } catch (java.io.IOException ex) { + throw new RuntimeException(ex); + } @@ -3122,9 +2850,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @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)); ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap.getVillagePlace()) { ++ net.minecraft.world.level.chunk.storage.RegionFile file = ServerLevel.this.getChunkSource().chunkMap.getVillagePlace().getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); + return function.apply(file); + } + } @@ -3132,22 +2860,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + 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); ++ public void writeData(int x, int z, net.minecraft.nbt.CompoundTag compound) throws java.io.IOException { ++ ServerLevel.this.getChunkSource().chunkMap.write(new ChunkPos(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)); ++ public net.minecraft.nbt.CompoundTag readData(int x, int z) throws java.io.IOException { ++ return ServerLevel.this.getChunkSource().chunkMap.read(new ChunkPos(x, z)); + } + + @Override -+ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { -+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { -+ RegionFile file; ++ public T computeForRegionFile(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap) { ++ net.minecraft.world.level.chunk.storage.RegionFile file; + + try { -+ file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); ++ file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getFile(new ChunkPos(chunkX, chunkZ), false); + } catch (java.io.IOException ex) { + throw new RuntimeException(ex); + } @@ -3157,9 +2885,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @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)); ++ public T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function function) { ++ synchronized (ServerLevel.this.getChunkSource().chunkMap) { ++ net.minecraft.world.level.chunk.storage.RegionFile file = ServerLevel.this.getChunkSource().chunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkPos(chunkX, chunkZ)); + return function.apply(file); + } + } @@ -3168,126 +2896,93 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.sleepStatus = new SleepStatus(); + this.getCraftServer().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 +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/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 +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.ChunkPos; + + public class TicketType { + public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper ++ public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper + + private final String name; + private final Comparator comparator; +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper return; } + // Paper start -+ String str = packetplayintabcomplete.c(); int index = -1; ++ String str = packet.getCommand(); 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 ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper + return; + } + // Paper end // CraftBukkit end - StringReader stringreader = new StringReader(packetplayintabcomplete.c()); + StringReader stringreader = new StringReader(packet.getCommand()); -diff --git a/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java b/src/main/java/net/minecraft/util/thread/IAsyncTaskHandler.java +diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.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 static final int VILLAGE_SECTION_SIZE = 1; + private final PoiManager.DistanceTracker distanceTracker; + private final LongSet loadedChunks = new LongOpenHashSet(); ++ private final net.minecraft.server.level.ServerLevel world; // Paper + public PoiManager(File directory, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) { + super(directory, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world); ++ this.world = (net.minecraft.server.level.ServerLevel)world; // Paper + this.distanceTracker = new PoiManager.DistanceTracker(); } -- protected void executeAll() { -+ public void executeAll() { // Paper - protected -> 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 { +@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage { @Override - public void a(BooleanSupplier booleansupplier) { -- super.a(booleansupplier); + public void tick(BooleanSupplier shouldKeepTicking) { +- super.tick(shouldKeepTicking); + // 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(); ++ while (!this.dirty.isEmpty() && shouldKeepTicking.getAsBoolean()) { ++ ChunkPos chunkcoordintpair = SectionPos.of(this.dirty.firstLong()).chunk(); + -+ 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); ++ net.minecraft.nbt.CompoundTag 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(); + this.distanceTracker.runAllUpdates(); } -@@ -0,0 +0,0 @@ public class VillagePlace extends RegionFileSection { +@@ -0,0 +0,0 @@ public class PoiManager extends SectionStorage { } } + // Paper start - Asynchronous chunk io + @javax.annotation.Nullable + @Override -+ public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws java.io.IOException { ++ public net.minecraft.nbt.CompoundTag read(ChunkPos 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 ++ net.minecraft.nbt.CompoundTag 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; + @@ -3300,7 +2995,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws java.io.IOException { ++ public void write(ChunkPos chunkcoordintpair, net.minecraft.nbt.CompoundTag 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, @@ -3312,183 +3007,117 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 + HAS_SPACE(PoiRecord::hasSpace), + IS_OCCUPIED(PoiRecord::isOccupied), +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.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; +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -0,0 +0,0 @@ import java.util.Comparator; + import net.minecraft.core.BlockPos; - public class NextTickListEntry { - -- private static long d; + public class TickNextTickData { +- private static long counter; + 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 { + private final T type; + public final BlockPos pos; + public final long triggerTick; +@@ -0,0 +0,0 @@ public class TickNextTickData { } - 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 + public TickNextTickData(BlockPos pos, T t, long time, TickPriority priority) { +- this.c = (long)(counter++); ++ this.c = (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading + this.pos = pos.immutable(); + this.type = t; + this.triggerTick = time; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.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(); - } +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { -+ 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(); + public ChunkSerializer() {} + // Paper start + public static final class InProgressChunkHolder { + + public final ProtoChunk protoChunk; -+ public final ArrayDeque tasks; ++ public final java.util.ArrayDeque tasks; + -+ public NBTTagCompound poiData; ++ public CompoundTag poiData; + -+ public InProgressChunkHolder(final ProtoChunk protoChunk, final ArrayDeque tasks) { ++ public InProgressChunkHolder(final ProtoChunk protoChunk, final java.util.ArrayDeque tasks) { + this.protoChunk = protoChunk; + this.tasks = tasks; + } + } ++ // Paper end + - public static ProtoChunk loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -+ InProgressChunkHolder holder = loadChunk(worldserver, definedstructuremanager, villageplace, chunkcoordintpair, nbttagcompound, true); + public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt) { ++ // Paper start - add variant for async calls ++ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, nbt, 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<>(); ++ public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) { ++ java.util.ArrayDeque tasksToExecuteOnMain = new java.util.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(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); + CompoundTag nbttagcompound1 = nbt.getCompound("Level"); +@@ -0,0 +0,0 @@ public class ChunkSerializer { + LevelLightEngine 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); + lightengine.retainData(pos, 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; + for (int j = 0; j < nbttaglist.size(); ++j) { +@@ -0,0 +0,0 @@ public class ChunkSerializer { + achunksection[world.getSectionIndexFromSectionY(b0)] = chunksection; } -- villageplace.a(chunkcoordintpair, chunksection); + tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main -+ villageplace.a(chunkcoordintpair, chunksection); + poiStorage.checkConsistencyWithBlocks(pos, 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); + if (nbttagcompound2.contains("BlockLight", 7)) { +- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true); + // Paper start - delay this task since we're executing off-main -+ NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); ++ DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight")); + tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), blockLight, true); ++ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, 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); + if (flag1 && nbttagcompound2.contains("SkyLight", 7)) { +- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); + // Paper start - delay this task since we're executing off-main -+ NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); ++ DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight")); + tasksToExecuteOnMain.add(() -> { -+ lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true); ++ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair1, b0), skyLight, true); + }); + // Paper end - delay this task since we're executing off-main } } } -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { +@@ -0,0 +0,0 @@ public class ChunkSerializer { } - if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) { -- return new ProtoChunkExtension((Chunk) object); -+ return new InProgressChunkHolder(new ProtoChunkExtension((Chunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading + if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) { +- return new ImposterProtoChunk((LevelChunk) object); ++ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) 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))); +@@ -0,0 +0,0 @@ public class ChunkSerializer { + protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1))); } - return protochunk1; @@ -3498,37 +3127,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // 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 DataLayer[] blockLight; ++ public final DataLayer[] 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 ListTag blockTickList; // non-null if we had to go to the server's tick list ++ public final ListTag fluidTickList; // non-null if we had to go to the server's tick list ++ public final ListTag blockEntities; + + public final long worldTime; + -+ public AsyncSaveData(NibbleArray[] blockLight, NibbleArray[] skyLight, NBTTagList blockTickList, NBTTagList fluidTickList, -+ long worldTime) { ++ public AsyncSaveData(DataLayer[] blockLight, DataLayer[] skyLight, ++ ListTag blockTickList, ListTag fluidTickList, ListTag blockEntities, long worldTime) { + this.blockLight = blockLight; + this.skyLight = skyLight; + this.blockTickList = blockTickList; + this.fluidTickList = fluidTickList; ++ this.blockEntities = blockEntities; + this.worldTime = worldTime; - } - } - ++ } ++ } ++ + // must be called sync -+ public static AsyncSaveData getAsyncSaveData(WorldServer world, IChunkAccess chunk) { ++ public static AsyncSaveData getAsyncSaveData(ServerLevel world, ChunkAccess chunk) { + org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); -+ ChunkCoordIntPair chunkPos = chunk.getPos(); ++ ChunkPos chunkPos = chunk.getPos(); + -+ LightEngineThreaded lightenginethreaded = world.getChunkProvider().getLightEngine(); ++ ThreadedLevelLightEngine lightenginethreaded = world.getChunkSource().getLightEngine(); + -+ NibbleArray[] blockLight = new NibbleArray[17 - (-1)]; -+ NibbleArray[] skyLight = new NibbleArray[17 - (-1)]; ++ DataLayer[] blockLight = new DataLayer[lightenginethreaded.getMaxLightSection() - lightenginethreaded.getMinLightSection()]; ++ DataLayer[] skyLight = new DataLayer[lightenginethreaded.getMaxLightSection() - lightenginethreaded.getMinLightSection()]; + -+ 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)); ++ for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) { ++ DataLayer blockArray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkPos, i)); ++ DataLayer skyArray = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkPos, i)); + + // copy data for safety + if (blockArray != null) { @@ -3538,232 +3169,212 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + skyArray = skyArray.copy(); + } + -+ // apply offset of 1 for -1 starting index -+ blockLight[i + 1] = blockArray; -+ skyLight[i + 1] = skyArray; ++ blockLight[i - lightenginethreaded.getMinLightSection()] = blockArray; ++ skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray; + } + -+ TickList blockTickList = chunk.n(); ++ TickList blockTickList = chunk.getBlockTicks(); + -+ NBTTagList blockTickListSerialized; -+ if (blockTickList instanceof ProtoChunkTickList || blockTickList instanceof TickListChunk) { ++ ListTag blockTickListSerialized; ++ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) { + blockTickListSerialized = null; + } else { -+ blockTickListSerialized = world.getBlockTickList().a(chunkPos); ++ blockTickListSerialized = world.getBlockTicks().save(chunkPos); + } + -+ TickList fluidTickList = chunk.o(); ++ TickList fluidTickList = chunk.getLiquidTicks(); + -+ NBTTagList fluidTickListSerialized; -+ if (fluidTickList instanceof ProtoChunkTickList || fluidTickList instanceof TickListChunk) { ++ ListTag fluidTickListSerialized; ++ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) { + fluidTickListSerialized = null; + } else { -+ fluidTickListSerialized = world.getFluidTickList().a(chunkPos); ++ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos); + } + -+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, world.getTime()); -+ } ++ ListTag blockEntitiesSerialized = new ListTag(); ++ for (final BlockPos blockPos : chunk.getBlockEntitiesPos()) { ++ final CompoundTag blockEntityNbt = chunk.getBlockEntityNbtForSaving(blockPos); ++ if (blockEntityNbt != null) { ++ blockEntitiesSerialized.add(blockEntityNbt); ++ } + } + - public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess) { -+ return saveChunk(worldserver, ichunkaccess, null); ++ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime()); + } + + public static CompoundTag write(ServerLevel world, ChunkAccess chunk) { ++ return saveChunk(world, chunk, null); + } -+ public static NBTTagCompound saveChunk(WorldServer worldserver, IChunkAccess ichunkaccess, AsyncSaveData asyncsavedata) { ++ public static CompoundTag saveChunk(ServerLevel world, ChunkAccess chunk, 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)); + ChunkPos chunkcoordintpair = chunk.getPos(); + CompoundTag nbttagcompound = new CompoundTag(); + CompoundTag nbttagcompound1 = new CompoundTag(); +@@ -0,0 +0,0 @@ public class ChunkSerializer { + nbttagcompound.put("Level", nbttagcompound1); + nbttagcompound1.putInt("xPos", chunkcoordintpair.x); + nbttagcompound1.putInt("zPos", chunkcoordintpair.z); +- nbttagcompound1.putLong("LastUpdate", world.getGameTime()); ++ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading + nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); + nbttagcompound1.putString("Status", chunk.getStatus().getName()); + UpgradeData chunkconverter = chunk.getUpgradeData(); +@@ -0,0 +0,0 @@ public class ChunkSerializer { + LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { + return chunksection1 != null && SectionPos.blockToSectionCoord(chunksection1.bottomBlockY()) == finalI; // CraftBukkit - decompile errors + }).findFirst().orElse(LevelChunk.EMPTY_SECTION); +- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); +- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); - + // Paper start - async chunk save for unload -+ NibbleArray nibblearray; // block light -+ NibbleArray nibblearray1; // sky light ++ DataLayer nibblearray; // block light ++ DataLayer 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) ++ nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); /// Paper - diff on method change (see getAsyncSaveData) ++ nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(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 ++ nibblearray = asyncsavedata.blockLight[i - lightenginethreaded.getMinLightSection()]; ++ nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()]; + } + // 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 { + if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) { + CompoundTag nbttagcompound2 = new CompoundTag(); + +@@ -0,0 +0,0 @@ public class ChunkSerializer { + nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); } - nbttagcompound1.set("Entities", nbttaglist2); -- TickList ticklist = ichunkaccess.n(); -+ TickList ticklist = ichunkaccess.n(); // Paper - diff on method change (see getAsyncSaveData) +- ListTag nbttaglist1 = new ListTag(); +- Iterator iterator = chunk.getBlockEntitiesPos().iterator(); ++ // Paper start ++ ListTag nbttaglist1; ++ Iterator iterator; ++ if (asyncsavedata != null) { ++ nbttaglist1 = asyncsavedata.blockEntities; ++ iterator = java.util.Collections.emptyIterator(); ++ } else { ++ nbttaglist1 = new ListTag(); ++ iterator = chunk.getBlockEntitiesPos().iterator(); ++ } ++ // Paper end - if (ticklist instanceof ProtoChunkTickList) { - nbttagcompound1.set("ToBeTicked", ((ProtoChunkTickList) ticklist).b()); - } else if (ticklist instanceof TickListChunk) { - nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).b()); + CompoundTag nbttagcompound3; + +@@ -0,0 +0,0 @@ public class ChunkSerializer { + nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); + } else if (ticklist instanceof ChunkTickList) { + nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save()); + // Paper start - async chunk save for unload + } else if (asyncsavedata != null) { -+ nbttagcompound1.set("TileTicks", asyncsavedata.blockTickList); ++ nbttagcompound1.put("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) + nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair)); } - -- 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()); +@@ -0,0 +0,0 @@ public class ChunkSerializer { + nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save()); + } else if (ticklist1 instanceof ChunkTickList) { + nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save()); + // Paper start - async chunk save for unload + } else if (asyncsavedata != null) { -+ nbttagcompound1.set("LiquidTicks", asyncsavedata.fluidTickList); ++ nbttagcompound1.put("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.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair)); } - - 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.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; +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.DimensionDataStorage; - public class IChunkLoader implements AutoCloseable { + public class ChunkStorage implements AutoCloseable { -- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER -+ // Paper - OBFHELPER - nuke IOWorker - protected final DataFixer b; +- private final IOWorker worker; ++ // Paper - nuke IO worker + protected final DataFixer fixerUpper; @Nullable -- private PersistentStructureLegacy c; -+ private volatile PersistentStructureLegacy c; // Paper - async chunk loading -+ +- private LegacyStructureDataHandler legacyStructureHandler; ++ // Paper start - async chunk loading ++ private volatile LegacyStructureDataHandler legacyStructureHandler; + private final Object persistentDataLock = new Object(); // Paper -+ public final RegionFileCache regionFileCache; ++ public final RegionFileStorage regionFileCache; ++ // Paper end - async chunk loading - 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 + public ChunkStorage(File directory, DataFixer dataFixer, boolean dsync) { + this.fixerUpper = dataFixer; +- this.worker = new IOWorker(directory, dsync, "chunk"); ++ // Paper start - async chunk io ++ // remove IO worker ++ this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - nuke IOWorker ++ // Paper end - async chunk io } // CraftBukkit start - private boolean check(ChunkProviderServer cps, int x, int z) throws IOException { - ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); + private boolean check(ServerChunkCache cps, int x, int z) throws IOException { + ChunkPos pos = new ChunkPos(x, z); if (cps != null) { - com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread"); -- if (cps.isLoaded(x, z)) { +- if (cps.hasChunk(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 { +- CompoundTag nbt = this.read(pos); ++ // Paper start - prioritize ++ CompoundTag nbt = cps == null ? read(pos) : ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((ServerLevel)cps.getLevel(), x, z, ++ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData; ++ // Paper end + if (nbt != null) { + CompoundTag level = nbt.getCompound("Level"); + if (level.getBoolean("TerrainPopulated")) { +@@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { if (i < 1493) { - nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493); + nbttagcompound = NbtUtils.update(this.fixerUpper, 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()); + if (this.legacyStructureHandler == null) { + this.legacyStructureHandler = LegacyStructureDataHandler.getLegacyStructureHandler(resourcekey, (DimensionDataStorage) supplier.get()); } - nbttagcompound = this.c.a(nbttagcompound); + nbttagcompound = this.legacyStructureHandler.updateFromLegacy(nbttagcompound); + } // Paper - Async chunk loading } } -@@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable { +@@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { -- return this.a.a(chunkcoordintpair); -+ return this.regionFileCache.read(chunkcoordintpair); + public CompoundTag read(ChunkPos chunkPos) throws IOException { +- return this.worker.load(chunkPos); ++ return this.regionFileCache.read(chunkPos); // Paper - async chunk io } -- 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) { +- public void write(ChunkPos chunkPos, CompoundTag nbt) { +- this.worker.store(chunkPos, nbt); ++ // Paper start - async chunk io ++ public void write(ChunkPos chunkPos, CompoundTag nbt) throws IOException { ++ this.regionFileCache.write(chunkPos, nbt); ++ // Paper end - Async chunk loading + if (this.legacyStructureHandler != null) { + synchronized (this.persistentDataLock) { // Paper - Async chunk loading - this.c.a(chunkcoordintpair.pair()); -+ } // Paper - Async chunk loading} + this.legacyStructureHandler.removeIndex(chunkPos.toLong()); ++ } // Paper - Async chunk loading } -- -- } -- -- public void i() { -- this.a.a().join(); + + } + + public void flushWorker() { +- this.worker.synchronize().join(); ++ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.flush(); // Paper - nuke IO worker } public void close() throws IOException { -- this.a.close(); -+ this.regionFileCache.close(); +- this.worker.close(); ++ this.regionFileCache.close(); // Paper - nuke IO worker } } 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 @@ -3771,21 +3382,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 - + private final IntBuffer timestamps; + @VisibleForTesting + protected final RegionBitmap usedSectors; + 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]; + public RegionFile(File file, File directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - return (i + 4096 - 1) / 4096; + return (byteCount + 4096 - 1) / 4096; } -- public boolean b(ChunkCoordIntPair chunkcoordintpair) { -+ public synchronized boolean b(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronized - int i = this.getOffset(chunkcoordintpair); +- public boolean doesChunkExist(ChunkPos pos) { ++ public synchronized boolean doesChunkExist(ChunkPos pos) { // Paper - synchronized + int i = this.getOffset(pos); if (i == 0) { @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { @@ -3797,11 +3407,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + synchronized (this) { + try { + // Paper end - this.closed = true; // Paper try { - this.d(); + this.padToFullSector(); + } finally { @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - this.dataFile.close(); + this.file.close(); } } + } finally { // Paper start - Prevent regionfiles from being closed during use @@ -3811,38 +3421,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } -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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.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())); +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + this.sync = dsync; } - // 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 +- private RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit ++ // Paper start ++ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { ++ return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); ++ } ++ ++ public synchronized boolean chunkExists(ChunkPos pos) throws IOException { ++ RegionFile regionfile = getFile(pos, true); ++ ++ return regionfile != null ? regionfile.hasChunk(pos) : false; ++ } ++ ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit + return this.getFile(chunkcoordintpair, existingOnly, false); + } -+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { ++ public synchronized RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly, boolean lock) throws IOException { + // Paper end - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); - RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); + long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); if (regionfile != null) { + // Paper start @@ -3853,11 +3458,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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); + if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync); - this.cache.putAndMoveToFirst(i, regionfile1); + this.regionCache.putAndMoveToFirst(i, regionfile1); + // Paper start + if (lock) { + // must be in this synchronized block @@ -3867,21 +3472,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return regionfile1; } } -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { @Nullable - public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { + public CompoundTag read(ChunkPos pos) 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 +- RegionFile regionfile = this.getFile(pos, true); ++ RegionFile regionfile = this.getFile(pos, 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 { + DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); + + CompoundTag nbttagcompound; +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { } return nbttagcompound; @@ -3890,14 +3495,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // 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 + protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { +- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit ++ RegionFile regionfile = this.getFile(pos, 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 { + + if (nbt == null) { +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { MinecraftServer.LOGGER.error("Failed to save chunk", laste); } // Paper end @@ -3908,149 +3513,116 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - 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 { - } + ExceptionCollector exceptionsuppressor = new ExceptionCollector<>(); + ObjectIterator objectiterator = this.regionCache.values().iterator(); +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + exceptionsuppressor.throwIfPresent(); } -+ -+ // 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 + +- public void flush() throws IOException { ++ public synchronized void flush() throws IOException { // Paper - synchronize + ObjectIterator objectiterator = this.regionCache.values().iterator(); + + while (objectiterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.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; +--- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelHeightAccessor; 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 - +-public class SectionStorage implements AutoCloseable { ++public class SectionStorage extends RegionFileStorage 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; + private static final String SECTIONS_TAG = "Sections"; +- private final IOWorker worker; ++ // Paper - remove mojang I/O thread + private final Long2ObjectMap> storage = new Long2ObjectOpenHashMap<>(); + public final LongLinkedOpenHashSet dirty = new LongLinkedOpenHashSet(); + private final Function> codec; +@@ -0,0 +0,0 @@ public class SectionStorage implements AutoCloseable { + protected final LevelHeightAccessor levelHeightAccessor; - 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 + public SectionStorage(File directory, Function> codecFactory, Function factory, DataFixer dataFixer, DataFixTypes dataFixTypes, boolean dsync, LevelHeightAccessor world) { ++ super(directory, dsync); // Paper - nuke IOWorker + this.codec = codecFactory; + this.factory = factory; + this.fixerUpper = dataFixer; + this.type = dataFixTypes; + this.levelHeightAccessor = world; +- this.worker = new IOWorker(directory, dsync, directory.getName()); ++ // Paper - remove mojang I/O thread } - 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 { + protected void tick(BooleanSupplier shouldKeepTicking) { +@@ -0,0 +0,0 @@ public class SectionStorage 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)); + private void readColumn(ChunkPos chunkPos) { +- this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos)); ++ // Paper start - expose function to load in data ++ this.loadInData(chunkPos, this.tryRead(chunkPos)); + } -+ public void loadInData(ChunkCoordIntPair chunkPos, NBTTagCompound compound) { -+ this.a(chunkPos, DynamicOpsNBT.a, compound); -+ // Paper end ++ public void loadInData(ChunkPos chunkPos, CompoundTag compound) { ++ this.readColumn(chunkPos, NbtOps.INSTANCE, compound); ++ // Paper end - expose function to load in data } @Nullable - private NBTTagCompound c(ChunkCoordIntPair chunkcoordintpair) { + private CompoundTag tryRead(ChunkPos pos) { 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 this.worker.load(pos); ++ return this.read(pos); // Paper - nuke IOWorker + } catch (IOException var3) { + LOGGER.error("Error reading chunk {} data from disk", pos, var3); 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 +@@ -0,0 +0,0 @@ public class SectionStorage implements AutoCloseable { + Dynamic dynamic = this.writeColumn(chunkPos, NbtOps.INSTANCE); + Tag tag = dynamic.getValue(); + if (tag instanceof CompoundTag) { +- this.worker.store(chunkPos, (CompoundTag)tag); ++ try { this.write(chunkPos, (CompoundTag)tag); } catch (IOException ioexception) { SectionStorage.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker } else { - RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); + LOGGER.error("Expected compound tag, got {}", (Object)tag); } } + // 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(); ++ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) { ++ Dynamic dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); ++ Tag nbtbase = (Tag) dynamic.getValue(); + -+ if (nbtbase instanceof NBTTagCompound) { -+ return (NBTTagCompound)nbtbase; ++ if (nbtbase instanceof CompoundTag) { ++ return (CompoundTag)nbtbase; + } else { -+ RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase); ++ SectionStorage.LOGGER.error("Expected compound tag, got {}", nbtbase); + } + return null; + } + // Paper end -+ - private Dynamic a(ChunkCoordIntPair chunkcoordintpair, DynamicOps dynamicops) { + private Dynamic writeColumn(ChunkPos chunkPos, 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 +@@ -0,0 +0,0 @@ public class SectionStorage implements AutoCloseable { -- 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 + @Override + public void close() throws IOException { +- this.worker.close(); ++ //this.worker.close(); // Paper - nuke I/O worker ++ } + + // Paper start - get data function -+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) { ++ public CompoundTag getData(ChunkPos 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(); ++ // This is checking if the data needs to be written, then it builds it later in getDataInternal(ChunkCoordIntPair) ++ if (!this.dirty.isEmpty()) { ++ for (int i = this.levelHeightAccessor.getMinSection(); i < this.levelHeightAccessor.getMaxSection(); ++i) { ++ long j = SectionPos.of(chunkcoordintpair, i).asLong(); + -+ if (this.d.contains(j)) { ++ if (this.dirty.contains(j)) { + return this.getDataInternal(chunkcoordintpair); + } + } @@ -4063,53 +3635,21 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/jav 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()); + return (this.getHandle().dragonFight() == null) ? null : new CraftDragonBattle(this.getHandle().dragonFight()); } + // Paper start + @Override -+ public CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { ++ public java.util.concurrent.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); ++ net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); + if (immediate != null) { -+ return CompletableFuture.completedFuture(immediate.getBukkitChunk()); ++ return java.util.concurrent.CompletableFuture.completedFuture(immediate.getBukkitChunk()); + } + } else { -+ CompletableFuture future = new CompletableFuture(); -+ world.getMinecraftServer().execute(() -> { ++ java.util.concurrent.CompletableFuture future = new java.util.concurrent.CompletableFuture(); ++ world.getServer().execute(() -> { + getChunkAtAsync(x, z, gen, urgent).whenComplete((chunk, err) -> { + if (err != null) { + future.completeExceptionally(err); @@ -4121,9 +3661,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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()); ++ return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { ++ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); ++ return java.util.concurrent.CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, net.minecraft.server.MinecraftServer.getServer()); + } + // Paper end @@ -4134,39 +3674,29 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/ 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; +@@ -0,0 +0,0 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.TicketType; import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AreaEffectCloud; 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); + this.entity.setYHeadRot(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; ++ net.minecraft.server.level.ChunkMap playerChunkMap = ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().chunkMap; + 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()); ++ net.minecraft.world.level.ChunkPos pair = new net.minecraft.world.level.ChunkPos(chunk.getX(), chunk.getZ()); ++ ((CraftWorld) loc.getWorld()).getHandle().getChunkSource().addTicketAtLevel(TicketType.POST_TELEPORT, pair, 31, 0); ++ net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pair.toLong()); + if (updatingChunk != null) { -+ return updatingChunk.getEntityTickingFuture(); ++ return updatingChunk.getEntityTickingChunkFuture(); + } else { + return java.util.concurrent.CompletableFuture.completedFuture(com.mojang.datafixers.util.Either.left(((org.bukkit.craftbukkit.CraftChunk)chunk).getHandle())); + } @@ -4180,24 +3710,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public boolean teleport(Location location) { - return teleport(location, TeleportCause.PLUGIN); + return this.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 ); ++ com.destroystokyo.paper.io.chunk.ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper + WatchdogThread.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/patches/server/Attributes-API-for-item-defaults.patch similarity index 52% rename from Spigot-Server-Patches/Attributes-API-for-item-defaults.patch rename to patches/server/Attributes-API-for-item-defaults.patch index 00023654b1..cdb47e52a3 100644 --- a/Spigot-Server-Patches/Attributes-API-for-item-defaults.patch +++ b/patches/server/Attributes-API-for-item-defaults.patch @@ -4,39 +4,27 @@ 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)); + return CraftMagicNumbers.getItem(itemToBeRepaired.getType()).isValidRepairItem(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); ++ Item item = CraftMagicNumbers.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)); ++ item.getDefaultAttributeModifiers(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(equipmentSlot)).forEach((attributeBase, attributeModifier) -> { ++ attributeMapBuilder.put(org.bukkit.Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(net.minecraft.core.Registry.ATTRIBUTE.getKey(attributeBase))), org.bukkit.craftbukkit.attribute.CraftAttributeInstance.convert(attributeModifier)); + }); + return attributeMapBuilder.build(); + } + @Override public int getProtocolVersion() { - return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); + return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); diff --git a/patches/server/Auto-fix-bad-Y-levels-on-player-login.patch b/patches/server/Auto-fix-bad-Y-levels-on-player-login.patch new file mode 100644 index 0000000000..bc4c50ecb1 --- /dev/null +++ b/patches/server/Auto-fix-bad-Y-levels-on-player-login.patch @@ -0,0 +1,19 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + @Override + public void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); ++ if (this.getY() > 300) this.setPosRaw(getX(), 257, getZ()); // Paper - bring down to a saner Y level if out of world + if (nbt.contains("enteredNetherPosition", 10)) { + CompoundTag nbttagcompound1 = nbt.getCompound("enteredNetherPosition"); + diff --git a/patches/server/Avoid-blocking-on-Network-Manager-creation.patch b/patches/server/Avoid-blocking-on-Network-Manager-creation.patch new file mode 100644 index 0000000000..2f77b35d18 --- /dev/null +++ b/patches/server/Avoid-blocking-on-Network-Manager-creation.patch @@ -0,0 +1,45 @@ +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/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + public volatile boolean running; + private final List channels = Collections.synchronizedList(Lists.newArrayList()); + final List connections = 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 final void addPending() { ++ Connection manager = null; ++ while ((manager = pending.poll()) != null) { ++ connections.add(manager); ++ } ++ } ++ // Paper end + + public ServerConnectionListener(MinecraftServer server) { + this.server = server; +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); + Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); + +- ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error ++ // ServerConnectionListener.this.connections.add((Connection) object); // CraftBukkit - decompile error ++ pending.add((Connection) object); // Paper + channel.pipeline().addLast("packet_handler", (ChannelHandler) object); + ((Connection) object).setListener(new ServerHandshakePacketListenerImpl(ServerConnectionListener.this.server, (Connection) object)); + } +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + + synchronized (this.connections) { + // 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/patches/server/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch similarity index 57% rename from Spigot-Server-Patches/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch rename to patches/server/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch index 9db6147e86..cb8a4276c0 100644 --- a/Spigot-Server-Patches/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch +++ b/patches/server/Avoid-error-bubbling-up-when-item-stack-is-empty-in-.patch @@ -7,40 +7,40 @@ Subject: [PATCH] Avoid error bubbling up when item stack is empty in fishing 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.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 { +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -0,0 +0,0 @@ public class FishingHook extends Projectile { while (iterator.hasNext()) { ItemStack itemstack1 = (ItemStack) iterator.next(); -- EntityItem entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), 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; ++ ItemEntity entityitem = null; + if (!itemstack1.isEmpty()) { -+ entityitem = new EntityItem(this.world, this.locX(), this.locY(), this.locZ(), itemstack1); ++ entityitem = new ItemEntity(this.level, this.getX(), this.getY(), this.getZ(), 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); + this.level.getCraftServer().getPluginManager().callEvent(playerFishEvent); -@@ -0,0 +0,0 @@ public class EntityFishingHook extends IProjectile { - double d2 = entityhuman.locZ() - this.locZ(); +@@ -0,0 +0,0 @@ public class FishingHook extends Projectile { + double d2 = entityhuman.getZ() - this.getZ(); 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); +- entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); +- this.level.addFreshEntity(entityitem); + // 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); ++ entityitem.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); ++ this.level.addFreshEntity(entityitem); + } + // 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 + entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper diff --git a/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch b/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch new file mode 100644 index 0000000000..f6733c95da --- /dev/null +++ b/patches/server/Avoid-hopper-searches-if-there-are-no-items.patch @@ -0,0 +1,142 @@ +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/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + } + +- }); ++ }, predicate == net.minecraft.world.entity.EntitySelector.CONTAINER_ENTITY_SELECTOR); // Paper + return list; + } + +diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySection.java b/src/main/java/net/minecraft/world/level/entity/EntitySection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/entity/EntitySection.java ++++ b/src/main/java/net/minecraft/world/level/entity/EntitySection.java +@@ -0,0 +0,0 @@ public class EntitySection { + protected static final Logger LOGGER = LogManager.getLogger(); + private final ClassInstanceMultiMap storage; + private Visibility chunkStatus; ++ // Paper start - track number of items and minecarts ++ public int itemCount; ++ public int inventoryEntityCount; ++ // Paper end + + public EntitySection(Class entityClass, Visibility status) { + this.chunkStatus = status; +@@ -0,0 +0,0 @@ public class EntitySection { + } + + public void add(T obj) { ++ // Paper start ++ if (obj instanceof net.minecraft.world.entity.item.ItemEntity) { ++ this.itemCount++; ++ } else if (obj instanceof net.minecraft.world.Container) { ++ this.inventoryEntityCount++; ++ } ++ // Paper end + this.storage.add(obj); + } + + public boolean remove(T obj) { ++ // Paper start ++ if (obj instanceof net.minecraft.world.entity.item.ItemEntity) { ++ this.itemCount--; ++ } else if (obj instanceof net.minecraft.world.Container) { ++ this.inventoryEntityCount--; ++ } ++ // Paper end + return this.storage.remove(obj); + } + +@@ -0,0 +0,0 @@ public class EntitySection { + for(T object : this.storage.find(type.getBaseClass())) { + U object2 = (U)type.tryCast(object); + if (object2 != null && filter.test(object2)) { +- action.accept((T)object2); ++ action.accept(object2); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/entity/EntitySectionStorage.java +@@ -0,0 +0,0 @@ public class EntitySectionStorage { + + public LongSet getAllChunksWithExistingSections() { + LongSet longSet = new LongOpenHashSet(); +- this.sections.keySet().forEach((sectionPos) -> { ++ this.sections.keySet().forEach((java.util.function.LongConsumer) (sectionPos) -> { // Paper - decompile fix + longSet.add(getChunkKeyFromSectionKey(sectionPos)); + }); + return longSet; +@@ -0,0 +0,0 @@ public class EntitySectionStorage { + } + + public void getEntities(AABB box, Consumer action) { ++ // Paper start ++ this.getEntities(box, action, false); ++ } ++ public void getEntities(AABB box, Consumer action, boolean isContainerSearch) { ++ // Paper end + this.forEachAccessibleSection(box, (entitySection) -> { ++ if (isContainerSearch && entitySection.inventoryEntityCount <= 0) return; // Paper + entitySection.getEntities(createBoundingBoxCheck(box), action); + }); + } + + public void getEntities(EntityTypeTest filter, AABB box, Consumer action) { + this.forEachAccessibleSection(box, (entitySection) -> { ++ if (filter.getBaseClass() == net.minecraft.world.entity.item.ItemEntity.class && entitySection.itemCount <= 0) return; // Paper + entitySection.getEntities(filter, createBoundingBoxCheck(box), action); + }); + } +diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetter.java +@@ -0,0 +0,0 @@ public interface LevelEntityGetter { + void get(EntityTypeTest filter, Consumer action); + + void get(AABB box, Consumer action); ++ void get(AABB box, Consumer action, boolean isContainerSearch); // Paper + + void get(EntityTypeTest filter, AABB box, Consumer action); + } +diff --git a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java ++++ b/src/main/java/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java +@@ -0,0 +0,0 @@ public class LevelEntityGetterAdapter implements LevelEn + + @Override + public void get(AABB box, Consumer action) { +- this.sectionStorage.getEntities(box, action); ++ // Paper start ++ this.get(box, action, false); ++ } ++ @Override ++ public void get(AABB box, Consumer action, boolean isContainerSearch) { ++ this.sectionStorage.getEntities(box, action, isContainerSearch); ++ // Paper end + } + + @Override diff --git a/patches/server/Avoid-item-merge-if-stack-size-above-max-stack-size.patch b/patches/server/Avoid-item-merge-if-stack-size-above-max-stack-size.patch new file mode 100644 index 0000000000..ca70b3bf61 --- /dev/null +++ b/patches/server/Avoid-item-merge-if-stack-size-above-max-stack-size.patch @@ -0,0 +1,21 @@ +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/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { + + private void mergeWithNeighbours() { + if (this.isMergable()) { ++ // Paper start - avoid item merge if stack size above max stack size ++ ItemStack stack = getItem(); ++ if (stack.getCount() >= stack.getMaxStackSize()) return; ++ // Paper end + // Spigot start + double radius = level.spigotConfig.itemMerge; + List list = this.level.getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(radius, radius, radius), (entityitem) -> { diff --git a/Spigot-Server-Patches/Basic-PlayerProfile-API.patch b/patches/server/Basic-PlayerProfile-API.patch similarity index 87% rename from Spigot-Server-Patches/Basic-PlayerProfile-API.patch rename to patches/server/Basic-PlayerProfile-API.patch index f1242a28df..5020cc933d 100644 --- a/Spigot-Server-Patches/Basic-PlayerProfile-API.patch +++ b/patches/server/Basic-PlayerProfile-API.patch @@ -13,13 +13,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.profile; + ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.destroystokyo.paper.profile.ProfileProperty; +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 net.minecraft.server.players.GameProfileCache; +import org.apache.commons.lang3.Validate; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.spigotmc.SpigotConfig; @@ -39,7 +41,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private final PropertySet properties = new PropertySet(); + + public CraftPlayerProfile(CraftPlayer player) { -+ this.profile = player.getHandle().getProfile(); ++ this.profile = player.getHandle().getGameProfile(); + } + + public CraftPlayerProfile(UUID id, String name) { @@ -160,11 +162,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public boolean completeFromCache(boolean lookupUUID, boolean onlineMode) { + MinecraftServer server = MinecraftServer.getServer(); + String name = profile.getName(); -+ UserCache userCache = server.getUserCache(); ++ GameProfileCache userCache = server.getProfileCache(); + if (profile.getId() == null) { + final GameProfile profile; + if (onlineMode) { -+ profile = lookupUUID ? userCache.getProfile(name) : userCache.getProfileIfCached(name); ++ profile = lookupUUID ? userCache.get(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); @@ -177,7 +179,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + if ((profile.getName() == null || !hasTextures()) && profile.getId() != null) { -+ GameProfile profile = userCache.getProfile(this.profile.getId()); ++ GameProfile profile = userCache.get(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 @@ -200,12 +202,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + boolean isCompleteFromCache = this.completeFromCache(true, onlineMode); + if (onlineMode && (!isCompleteFromCache || textures && !hasTextures())) { -+ GameProfile result = server.getMinecraftSessionService().fillProfileProperties(profile, true); ++ GameProfile result = server.getSessionService().fillProfileProperties(profile, true); + if (result != null) { + copyProfileProperties(result, this.profile, true); + } + if (this.profile.isComplete()) { -+ server.getUserCache().saveProfile(this.profile); ++ server.getProfileCache().add(this.profile); + } + } + return profile.isComplete() && (!onlineMode || !textures || hasTextures()); @@ -434,15 +436,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 net.minecraft.core.BlockPos; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; import org.apache.commons.lang.exception.ExceptionUtils; +import com.mojang.authlib.GameProfile; import org.bukkit.Location; @@ -471,51 +472,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); +diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/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; +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -0,0 +0,0 @@ public class GameProfileCache { + } } + // Paper start + @Nullable public GameProfile getProfileIfCached(String name) { -+ UserCache.UserCacheEntry entry = this.nameCache.get(name.toLowerCase(Locale.ROOT)); ++ GameProfileCache.GameProfileInfo entry = this.profilesByName.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; - + public GameProfile get(UUID uuid) { + GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByUUID.get(uuid); 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 @@ -571,5 +546,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end this.profile = profile; - this.serializedProfile = (profile == null) ? null : GameProfileSerializer.serialize(new NBTTagCompound(), profile); + this.serializedProfile = (profile == null) ? null : NbtUtils.writeGameProfile(new CompoundTag(), profile); } diff --git a/Spigot-Server-Patches/Be-a-bit-more-informative-in-maxHealth-exception.patch b/patches/server/Be-a-bit-more-informative-in-maxHealth-exception.patch similarity index 72% rename from Spigot-Server-Patches/Be-a-bit-more-informative-in-maxHealth-exception.patch rename to patches/server/Be-a-bit-more-informative-in-maxHealth-exception.patch index 9ad4d1b879..a4cf491aa2 100644 --- a/Spigot-Server-Patches/Be-a-bit-more-informative-in-maxHealth-exception.patch +++ b/patches/server/Be-a-bit-more-informative-in-maxHealth-exception.patch @@ -11,12 +11,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 + ")"); + if ((health < 0) || (health > this.getMaxHealth())) { +- throw new IllegalArgumentException("Health must be between 0 and " + this.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() + ')' : ')')); ++ + ". (attribute base value: " + this.getHandle().getAttribute(Attributes.MAX_HEALTH).getBaseValue() ++ + (this instanceof CraftPlayer ? ", player: " + this.getName() + ')' : ')')); } - getHandle().setHealth((float) health); + this.getHandle().setHealth((float) health); diff --git a/patches/server/Beacon-API-custom-effect-ranges.patch b/patches/server/Beacon-API-custom-effect-ranges.patch new file mode 100644 index 0000000000..3d86153ed8 --- /dev/null +++ b/patches/server/Beacon-API-custom-effect-ranges.patch @@ -0,0 +1,94 @@ +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/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), 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 BeaconBlockEntity(BlockPos pos, BlockState state) { + super(BlockEntityType.BEACON, pos, state); +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + + public static List getHumansInRange(Level world, BlockPos blockposition, int i) { ++ // Paper start ++ return BeaconBlockEntity.getHumansInRange(world, blockposition, i, null); ++ } ++ public static List getHumansInRange(Level world, BlockPos blockposition, int i, @Nullable BeaconBlockEntity blockEntity) { ++ // Paper end + { +- double d0 = (double) (i * 10 + 10); ++ double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10);// Paper - custom beacon ranges + + AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D); + List list = world.getEntitiesOfClass(Player.class, axisalignedbb); +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + + this.lockKey = LockCode.fromTag(nbt); ++ this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + } + + this.lockKey.addToTag(nbt); ++ nbt.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper + return nbt; + } + +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 implem + public void setLock(String key) { + this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key); + } ++ ++ // Paper start ++ @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(); ++ } ++ // Paper end + } diff --git a/patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch new file mode 100644 index 0000000000..0518240e02 --- /dev/null +++ b/patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -0,0 +1,34 @@ +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/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + public Bee(EntityType type, Level world) { + super(type, world); + this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60); +- this.moveControl = new FlyingMoveControl(this, 20, true); ++ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279 ++ class BeeFlyingMoveControl extends FlyingMoveControl { ++ public BeeFlyingMoveControl(final Mob entity, final int maxPitchChange, final boolean noGravity) { ++ super(entity, maxPitchChange, noGravity); ++ } ++ ++ @Override ++ public void tick() { ++ if (this.mob.getY() <= Bee.this.level.getMinBuildHeight()) { ++ this.mob.setNoGravity(false); ++ } ++ super.tick(); ++ } ++ } ++ this.moveControl = new BeeFlyingMoveControl(this, 20, true); ++ // Paper end + this.lookControl = new Bee.BeeLookControl(this); + this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F); + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); diff --git a/Spigot-Server-Patches/Block-Enderpearl-Travel-Exploit.patch b/patches/server/Block-Enderpearl-Travel-Exploit.patch similarity index 68% rename from Spigot-Server-Patches/Block-Enderpearl-Travel-Exploit.patch rename to patches/server/Block-Enderpearl-Travel-Exploit.patch index f252ae46ae..0f5cc3bc59 100644 --- a/Spigot-Server-Patches/Block-Enderpearl-Travel-Exploit.patch +++ b/patches/server/Block-Enderpearl-Travel-Exploit.patch @@ -26,15 +26,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.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 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -0,0 +0,0 @@ public abstract class Projectile extends Entity { + protected void readAdditionalSaveData(CompoundTag nbt) { + if (nbt.hasUUID("Owner")) { + this.ownerUUID = nbt.getUUID("Owner"); ++ if (this instanceof ThrownEnderpearl && this.level != null && this.level.paperConfig.disableEnderpearlExploit) { this.ownerUUID = null; } // Paper - Don't store shooter name for pearls to block enderpearl travel exploit } - this.d = nbttagcompound.getBoolean("LeftOwner"); + this.leftOwner = nbt.getBoolean("LeftOwner"); diff --git a/Spigot-Server-Patches/Block-Entity-remove-from-being-called-on-Players.patch b/patches/server/Block-Entity-remove-from-being-called-on-Players.patch similarity index 92% rename from Spigot-Server-Patches/Block-Entity-remove-from-being-called-on-Players.patch rename to patches/server/Block-Entity-remove-from-being-called-on-Players.patch index 129b2336d0..4ba8aa64de 100644 --- a/Spigot-Server-Patches/Block-Entity-remove-from-being-called-on-Players.patch +++ b/patches/server/Block-Entity-remove-from-being-called-on-Players.patch @@ -17,12 +17,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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(); + getHandle().resetAttackStrengthTicker(); } + + @Override + public void remove() { -+ if (this.getHandle().getClass().equals(EntityPlayer.class)) { // special case for NMS plugins inheriting ++ if (this.getHandle().getClass().equals(ServerPlayer.class)) { // special case for NMS plugins inheriting + throw new UnsupportedOperationException("Calling Entity#remove on players produces undefined (bad) behavior"); + } else { + super.remove(); diff --git a/Spigot-Server-Patches/Block-player-logins-during-server-shutdown.patch b/patches/server/Block-player-logins-during-server-shutdown.patch similarity index 51% rename from Spigot-Server-Patches/Block-player-logins-during-server-shutdown.patch rename to patches/server/Block-player-logins-during-server-shutdown.patch index 542217531f..89fa315f85 100644 --- a/Spigot-Server-Patches/Block-player-logins-during-server-shutdown.patch +++ b/patches/server/Block-player-logins-during-server-shutdown.patch @@ -4,11 +4,11 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener } public void tick() { @@ -18,6 +18,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + // Paper end - if (this.g == LoginListener.EnumProtocolState.READY_TO_ACCEPT) { - this.c(); - } else if (this.g == LoginListener.EnumProtocolState.DELAY_ACCEPT) { + if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { + this.handleAcceptedLogin(); + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { diff --git a/Spigot-Server-Patches/BlockDestroyEvent.patch b/patches/server/BlockDestroyEvent.patch similarity index 65% rename from Spigot-Server-Patches/BlockDestroyEvent.patch rename to patches/server/BlockDestroyEvent.patch index a7158f3a75..8fd9320d2d 100644 --- a/Spigot-Server-Patches/BlockDestroyEvent.patch +++ b/patches/server/BlockDestroyEvent.patch @@ -10,28 +10,28 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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; +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.Packet; - import net.minecraft.resources.MinecraftKey; import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; +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 { + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerLevel; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { return false; } else { - Fluid fluid = this.getFluid(blockposition); + FluidState fluid = this.getFluidState(pos); + // 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); ++ com.destroystokyo.paper.event.block.BlockDestroyEvent event = new com.destroystokyo.paper.event.block.BlockDestroyEvent(MCUtil.toBukkitBlock(this, pos), fluid.createLegacyBlock().createCraftBlockData(), drop); + if (!event.callEvent()) { + return false; + } @@ -39,8 +39,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end -- if (!(iblockdata.getBlock() instanceof BlockFireAbstract)) { -+ if (playEffect && !(iblockdata.getBlock() instanceof BlockFireAbstract)) { // Paper - this.triggerEffect(2001, blockposition, Block.getCombinedId(iblockdata)); +- if (!(iblockdata.getBlock() instanceof BaseFireBlock)) { ++ if (playEffect && !(iblockdata.getBlock() instanceof BaseFireBlock)) { // Paper + this.levelEvent(2001, pos, Block.getId(iblockdata)); } diff --git a/Spigot-Server-Patches/Book-Size-Limits.patch b/patches/server/Book-Size-Limits.patch similarity index 63% rename from Spigot-Server-Patches/Book-Size-Limits.patch rename to patches/server/Book-Size-Limits.patch index 0a4db2d6bf..b0fc41a32f 100644 --- a/Spigot-Server-Patches/Book-Size-Limits.patch +++ b/patches/server/Book-Size-Limits.patch @@ -10,32 +10,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 ++ + public static boolean asyncChunks = false; + private static void asyncChunks() { + ConfigurationSection section; +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override - public void a(PacketPlayInBEdit packetplayinbedit) { + public void handleEditBook(ServerboundEditBookPacket packet) { + // Paper start -+ ItemStack testStack = packetplayinbedit.getBook(); -+ if (!server.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { -+ NBTTagList pageList = testStack.getTag().getList("pages", 8); ++ ItemStack testStack = packet.getBook(); ++ if (!this.cserver.isPrimaryThread() && !testStack.isEmpty() && testStack.getTag() != null) { ++ ListTag 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!")); ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with too many pages"); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); + return; + } + long byteTotal = 0; @@ -46,8 +48,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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!")); ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); + return; + } + byteTotal += byteLength; @@ -69,8 +71,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + 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!")); ++ ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); ++ server.scheduleOnMain(() -> this.disconnect("Book too large!")); + return; + } + } diff --git a/patches/server/Bound-Treasure-Maps-to-World-Border.patch b/patches/server/Bound-Treasure-Maps-to-World-Border.patch new file mode 100644 index 0000000000..c5c06f1818 --- /dev/null +++ b/patches/server/Bound-Treasure-Maps-to-World-Border.patch @@ -0,0 +1,47 @@ +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) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + } + ++ // Paper start ++ private final BlockPos.MutableBlockPos mutPos = new BlockPos.MutableBlockPos(); ++ public boolean isBlockInBounds(int chunkX, int chunkZ) { ++ this.mutPos.set(chunkX, 64, chunkZ); ++ return this.isWithinBounds(this.mutPos); ++ } ++ public boolean isChunkInBounds(int chunkX, int chunkZ) { ++ this.mutPos.set(((chunkX << 4) + 15), 64, (chunkZ << 4) + 15); ++ return this.isWithinBounds(this.mutPos); ++ } ++ // Paper end ++ + public boolean isWithinBounds(ChunkPos pos) { + return (double) pos.getMaxBlockX() > this.getMinX() && (double) pos.getMinBlockX() < this.getMaxX() && (double) pos.getMaxBlockZ() > this.getMinZ() && (double) pos.getMinBlockZ() < this.getMaxZ(); + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -0,0 +0,0 @@ public abstract class StructureFeature { + int o = j + i * m; + int p = k + i * n; + ChunkPos chunkPos = this.getPotentialFeatureChunk(config, worldSeed, worldgenRandom, o, p); ++ if (!world.getWorldBorder().isChunkInBounds(chunkPos.x, chunkPos.z)) { continue; } // Paper + boolean bl3 = world.getBiomeManager().getPrimaryBiomeAtChunk(chunkPos).getGenerationSettings().isValidStart(this); + if (bl3) { + ChunkAccess chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); diff --git a/patches/server/Brand-support.patch b/patches/server/Brand-support.patch new file mode 100644 index 0000000000..9f3da7b777 --- /dev/null +++ b/patches/server/Brand-support.patch @@ -0,0 +1,91 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ import com.google.common.collect.Lists; + 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.Int2ObjectMap.Entry; +@@ -0,0 +0,0 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.Connection; ++import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.MutableComponent; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + 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 ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { + this.server = server; + this.connection = connection; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); + private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); + ++ private static final ResourceLocation MINECRAFT_BRAND = new ResourceLocation("brand"); // Paper - Brand support ++ + @Override + public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + try { + byte[] data = new byte[packet.data.readableBytes()]; + packet.data.readBytes(data); ++ // Paper start - Brand support ++ if (packet.identifier.equals(MINECRAFT_BRAND)) { ++ try { ++ this.clientBrandName = new FriendlyByteBuf(Unpooled.copiedBuffer(data)).readUtf(256); ++ } catch (StringIndexOutOfBoundsException ex) { ++ this.clientBrandName = "illegal"; ++ } ++ } ++ // Paper end + this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data); + } catch (Exception ex) { + ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + } + ++ // Paper start - brand support ++ public String getClientBrandName() { ++ return clientBrandName; ++ } ++ // Paper end ++ + public final boolean isDisconnected() { + return (!this.player.joining && !this.connection.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().connection != null ? getHandle().connection.getClientBrandName() : null; ++ } ++ // Paper end ++ + public Player.Spigot spigot() + { + return this.spigot; diff --git a/Spigot-Server-Patches/Break-up-and-make-tab-spam-limits-configurable.patch b/patches/server/Break-up-and-make-tab-spam-limits-configurable.patch similarity index 65% rename from Spigot-Server-Patches/Break-up-and-make-tab-spam-limits-configurable.patch rename to patches/server/Break-up-and-make-tab-spam-limits-configurable.patch index f2286f54ef..7be0c7ef64 100644 --- a/Spigot-Server-Patches/Break-up-and-make-tab-spam-limits-configurable.patch +++ b/patches/server/Break-up-and-make-tab-spam-limits-configurable.patch @@ -44,32 +44,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private long keepAliveChallenge; // CraftBukkit start - multithreaded fields - private volatile int chatThrottle; - private static final AtomicIntegerFieldUpdater chatSpamField = AtomicIntegerFieldUpdater.newUpdater(PlayerConnection.class, "chatThrottle"); + private AtomicInteger chatSpamTickCount = new AtomicInteger(); + 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(); + private int dropSpamTickCount; + private double firstGoodX; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.server.getProfiler().pop(); // CraftBukkit start - for (int spam; (spam = this.chatThrottle) > 0 && !chatSpamField.compareAndSet(this, spam, spam - 1); ) ; + for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(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) { + if (this.chatSpamTickCount > 0) { + --this.chatSpamTickCount; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { // 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 +- if (this.chatSpamTickCount.addAndGet(1) > 500 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { ++ if (this.chatSpamTickCount.addAndGet(com.destroystokyo.paper.PaperConfig.tabSpamIncrement) > com.destroystokyo.paper.PaperConfig.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable + server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper return; } diff --git a/Spigot-Server-Patches/Broadcast-join-message-to-console.patch b/patches/server/Broadcast-join-message-to-console.patch similarity index 77% rename from Spigot-Server-Patches/Broadcast-join-message-to-console.patch rename to patches/server/Broadcast-join-message-to-console.patch index 409e9c683e..64ff11a0b7 100644 --- a/Spigot-Server-Patches/Broadcast-join-message-to-console.patch +++ b/patches/server/Broadcast-join-message-to-console.patch @@ -12,9 +12,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +- this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure + // Paper start - Removed sendAll for loop and broadcasted to console also -+ server.getPlayerList().sendMessage(joinMessage); // Paper - Adventure ++ this.server.getPlayerList().broadcastMessage(joinMessage, ChatType.SYSTEM, Util.NIL_UUID); // Paper - Adventure + // Paper end } // CraftBukkit end diff --git a/patches/server/Buffer-joins-to-world.patch b/patches/server/Buffer-joins-to-world.patch new file mode 100644 index 0000000000..332ac170b0 --- /dev/null +++ b/patches/server/Buffer-joins-to-world.patch @@ -0,0 +1,58 @@ +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/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; + import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; ++import net.minecraft.server.MinecraftServer; + import net.minecraft.server.RunningOnDifferentThreadException; + import net.minecraft.server.network.ServerGamePacketListenerImpl; + import net.minecraft.server.network.ServerLoginPacketListenerImpl; +@@ -0,0 +0,0 @@ public class Connection 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 tick() { + this.flushQueue(); ++ // Paper start ++ if (currTick != MinecraftServer.currentTick) { ++ currTick = MinecraftServer.currentTick; ++ joinAttemptsThisTick = 0; ++ } ++ // Paper end + if (this.packetListener instanceof ServerLoginPacketListenerImpl) { ++ if ( ((ServerLoginPacketListenerImpl) this.packetListener).state != ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT // Paper ++ || (joinAttemptsThisTick++ < MAX_PER_TICK)) { // Paper - limit the number of joins which can be processed each tick + ((ServerLoginPacketListenerImpl) this.packetListener).tick(); ++ } // Paper + } + + if (this.packetListener instanceof ServerGamePacketListenerImpl) { diff --git a/patches/server/Build-system-changes.patch b/patches/server/Build-system-changes.patch new file mode 100644 index 0000000000..13e2d5f5bf --- /dev/null +++ b/patches/server/Build-system-changes.patch @@ -0,0 +1,97 @@ +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] Build system changes + + +diff --git a/build.gradle.kts b/build.gradle.kts +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ repositories { + dependencies { + implementation(project(":Paper-API")) + implementation("jline:jline:2.12.1") +- implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") { +- exclude(group = "org.apache.logging.log4j", module = "log4j-api") +- } ++ implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper ++ implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper + implementation("org.ow2.asm:asm:9.1") + implementation("com.googlecode.json-simple:json-simple:1.1.1") { + // This includes junit transitively for whatever reason + isTransitive = false + } + runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") +- runtimeOnly("mysql:mysql-connector-java:5.1.49") ++ runtimeOnly("mysql:mysql-connector-java:8.0.23") // Paper + + runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") + runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") + runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") + ++ implementation("co.aikar:cleaner:1.0-SNAPSHOT") // Paper ++ implementation("io.netty:netty-all:4.1.65.Final") // Paper ++ + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") + } +@@ -0,0 +0,0 @@ tasks.jar { + "Specification-Title" to "Bukkit", + "Specification-Version" to project.version, + "Specification-Vendor" to "Bukkit Team", ++ "Multi-Release" to "true", // Paper + ) + for (tld in setOf("net", "com", "org")) { + attributes("$tld/bukkit", "Sealed" to true) +@@ -0,0 +0,0 @@ publishing { + } + } + ++val generatePom = tasks.named("generatePomFileForMavenPublication") ++ + tasks.shadowJar { + archiveClassifier.set("mojang-mapped") + ++ // Needed for Paperclip's install to maven local feature ++ from(generatePom) { ++ into("META-INF/maven/io.papermc.paper/paper") ++ rename { "pom.xml" } ++ } ++ + val packageVersion = "1_17_R1" + relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v$packageVersion") { + exclude("org.bukkit.craftbukkit.Main*") + } + listOf( +- "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", ++ "jline", "org.apache.commons.codec", "org.apache.commons.io", // Paper - don't relocate fastutil + "org.apache.commons.lang3", "org.apache.http", "org.apache.maven", "org.codehaus.plexus", + "org.eclipse.aether", "org.eclipse.sisu", "org.objectweb.asm" + ).forEach { pack -> +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 (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { +- Date buildDate = new Date(Integer.parseInt(Main.class.getPackage().getImplementationVendor()) * 1000L); ++ Date buildDate = new java.text.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, -7); +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/io.papermc.paper/paper-api/pom.properties"); + Properties properties = new Properties(); + + if (stream != null) { diff --git a/Spigot-Server-Patches/Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch b/patches/server/Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch similarity index 100% rename from Spigot-Server-Patches/Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch rename to patches/server/Cache-DataFixerUpper-Rewrite-Rules-on-demand.patch diff --git a/Spigot-Server-Patches/Cache-block-data-strings.patch b/patches/server/Cache-block-data-strings.patch similarity index 68% rename from Spigot-Server-Patches/Cache-block-data-strings.patch rename to patches/server/Cache-block-data-strings.patch index 1b8e7d42f2..e3d873f60b 100644 --- a/Spigot-Server-Patches/Cache-block-data-strings.patch +++ b/patches/server/Cache-block-data-strings.patch @@ -8,28 +8,28 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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); + Preconditions.checkState(CraftBlockData.MAP.put(nms, bukkit) == null, "Duplicate mapping %s->%s", nms, bukkit); } + // Paper start - cache block data strings @@ -43,7 +43,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public static void reloadCache() { + stringDataCache.clear(); -+ Block.REGISTRY_ID.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); ++ Block.BLOCK_STATE_REGISTRY.forEach(blockData -> stringDataCache.put(blockData.toString(), blockData.createCraftBlockData())); + } + // Paper end + @@ -54,7 +54,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (material != null) { + Block block = CraftMagicNumbers.getBlock(material); + if (block != null) { -+ MinecraftKey key = IRegistry.BLOCK.getKey(block); ++ ResourceLocation key = Registry.BLOCK.getKey(block); + data = data == null ? key.toString() : key + data; + } + } @@ -65,6 +65,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static CraftBlockData createNewData(Material material, String data) { + // Paper end - cache block data strings - IBlockData blockData; + BlockState blockData; Block block = CraftMagicNumbers.getBlock(material); - Map, Comparable> parsed = null; + Map, Comparable> parsed = null; diff --git a/patches/server/Cache-burn-durations.patch b/patches/server/Cache-burn-durations.patch new file mode 100644 index 0000000000..d6e4a4e829 --- /dev/null +++ b/patches/server/Cache-burn-durations.patch @@ -0,0 +1,36 @@ +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/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipeType = recipeType; + } + ++ private static Map cachedBurnDurations = null; // Paper - cache burn durations + public static Map getFuel() { ++ // Paper start - cache burn durations ++ if(cachedBurnDurations != null) { ++ return cachedBurnDurations; ++ } ++ // Paper end + Map map = Maps.newLinkedHashMap(); + + AbstractFurnaceBlockEntity.add(map, (ItemLike) Items.LAVA_BUCKET, 20000); +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + AbstractFurnaceBlockEntity.add(map, (ItemLike) Blocks.COMPOSTER, 300); + AbstractFurnaceBlockEntity.add(map, (ItemLike) Blocks.AZALEA, 100); + AbstractFurnaceBlockEntity.add(map, (ItemLike) Blocks.FLOWERING_AZALEA, 100); +- return map; ++ // Paper start - cache burn durations ++ cachedBurnDurations = com.google.common.collect.ImmutableMap.copyOf(map); ++ return cachedBurnDurations; ++ // Paper end + } + + // CraftBukkit start - add fields and methods diff --git a/patches/server/Cache-user-authenticator-threads.patch b/patches/server/Cache-user-authenticator-threads.patch new file mode 100644 index 0000000000..398cfbf342 --- /dev/null +++ b/patches/server/Cache-user-authenticator-threads.patch @@ -0,0 +1,73 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Alfie Cleveland +Date: Fri, 25 Nov 2016 13:22:40 +0000 +Subject: [PATCH] Cache user authenticator threads + + +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + } + ++ // 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 -> { ++ Thread ret = new Thread(r, "User Authenticator #" + threadId.incrementAndGet()); ++ ++ ret.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); ++ ++ return ret; ++ } ++ ); ++ // Paper end + // Spigot start + public void initUUID() + { +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.nonce)); + } else { + // Spigot start +- new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { +- ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + @Override + public void run() { + try { +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + server.server.getLogger().log(java.util.logging.Level.WARNING, "Exception verifying " + ServerLoginPacketListenerImpl.this.gameProfile.getName(), ex); + } + } +- }.start(); ++ }); ++ // Paper end + // Spigot end + } + +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + throw new IllegalStateException("Protocol error", cryptographyexception); + } + +- Thread thread = new Thread("User Authenticator #" + ServerLoginPacketListenerImpl.UNIQUE_THREAD_ID.incrementAndGet()) { ++ // Paper start - Cache authenticator threads ++ authenticatorPool.execute(new Runnable() { + public void run() { + GameProfile gameprofile = ServerLoginPacketListenerImpl.this.gameProfile; + +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + + return ServerLoginPacketListenerImpl.this.server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; + } +- }; +- +- thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(ServerLoginPacketListenerImpl.LOGGER)); +- thread.start(); ++ }); ++ // Paper end + } + + // Spigot start diff --git a/Spigot-Server-Patches/Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server/Call-PaperServerListPingEvent-for-legacy-pings.patch similarity index 79% rename from Spigot-Server-Patches/Call-PaperServerListPingEvent-for-legacy-pings.patch rename to patches/server/Call-PaperServerListPingEvent-for-legacy-pings.patch index 073db9e8fd..b997959630 100644 --- a/Spigot-Server-Patches/Call-PaperServerListPingEvent-for-legacy-pings.patch +++ b/patches/server/Call-PaperServerListPingEvent-for-legacy-pings.patch @@ -83,10 +83,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + +} -diff --git a/src/main/java/net/minecraft/server/network/LegacyPingHandler.java b/src/main/java/net/minecraft/server/network/LegacyPingHandler.java +diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.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 +--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java @@ -0,0 +0,0 @@ package net.minecraft.server.network; @@ -95,8 +95,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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(); +@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + MinecraftServer minecraftserver = this.serverConnectionListener.getServer(); 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 @@ -105,7 +105,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 switch (i) { case 0: - LegacyPingHandler.LOGGER.debug("Ping: (<1.3.x) from {}:{}", inetsocketaddress.getAddress(), inetsocketaddress.getPort()); + LegacyQueryHandler.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); @@ -114,31 +114,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + break; + } + s = String.format("%s\u00a7%d\u00a7%d", PaperLegacyStatusClient.getUnformattedMotd(event), event.getNumPlayers(), event.getMaxPlayers()); - this.a(channelhandlercontext, this.a(s)); + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); break; case 1: -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { +@@ -0,0 +0,0 @@ public class LegacyQueryHandler 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 + LegacyQueryHandler.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.getServerVersion(), 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 ++ s = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", new Object[] { event.getProtocolVersion(), minecraftserver.getServerVersion(), event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()}); // CraftBukkit + // Paper end - this.a(channelhandlercontext, this.a(s)); + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); break; default: -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { +@@ -0,0 +0,0 @@ public class LegacyQueryHandler 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()); +- Byte.MAX_VALUE, server.getServerVersion(), 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); @@ -149,6 +149,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + 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)); + this.sendFlushAndClose(ctx, this.createReply(response)); } diff --git a/Spigot-Server-Patches/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch b/patches/server/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch similarity index 83% rename from Spigot-Server-Patches/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch rename to patches/server/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch index c4e0343e14..19d4fbe926 100644 --- a/Spigot-Server-Patches/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch +++ b/patches/server/Call-WhitelistToggleEvent-when-whitelist-is-toggled.patch @@ -11,8 +11,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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; + public void setUsingWhiteList(boolean whitelistEnabled) { ++ new com.destroystokyo.paper.event.server.WhitelistToggleEvent(whitelistEnabled).callEvent(); + this.doWhiteList = whitelistEnabled; } diff --git a/patches/server/Call-player-spectator-target-events-and-improve-impl.patch b/patches/server/Call-player-spectator-target-events-and-improve-impl.patch new file mode 100644 index 0000000000..8a2c107d50 --- /dev/null +++ b/patches/server/Call-player-spectator-target-events-and-improve-impl.patch @@ -0,0 +1,87 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } + + public void setCamera(Entity entity) { ++ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event and improve implementation + Entity entity1 = this.getCamera(); + +- this.camera = (Entity) (entity == null ? this : entity); +- if (entity1 != this.camera) { +- this.connection.send(new ClientboundSetCameraPacket(this.camera)); +- this.connection.b(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit ++ if (entity == null) { ++ entity = this; + } + ++ if (entity1 == entity) return; // new spec target is the current spec target ++ ++ if (entity == 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(), entity.getBukkitEntity()); ++ ++ if (!playerStartSpectatingEntityEvent.callEvent()) { ++ return; ++ } ++ } ++ // Validate ++ if (entity != this) { ++ if (entity.isRemoved() || !entity.valid || entity.level == null) { ++ MinecraftServer.LOGGER.info("Blocking player " + this + " from spectating invalid entity " + entity); ++ return; ++ } ++ if (this.isImmobile()) { ++ // use debug: clients might maliciously spam this ++ MinecraftServer.LOGGER.debug("Blocking frozen player " + this + " from spectating entity " + entity); ++ return; ++ } ++ } ++ ++ this.camera = entity; // only set after validating state ++ ++ if (entity != this) { ++ // Make sure we're in the right place ++ this.ejectPassengers(); // teleport can fail if we have passengers... ++ this.getBukkitEntity().teleport(new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ(), this.getYRot(), this.getXRot()), TeleportCause.SPECTATE); // Correctly handle cross-world entities from api calls by using CB teleport ++ ++ // Make sure we're tracking the entity before sending ++ ChunkMap.TrackedEntity tracker = ((ServerLevel)entity.level).getChunkSource().chunkMap.entityMap.get(entity.getId()); ++ if (tracker != null) { // dumb plugins... ++ tracker.updatePlayer(this); ++ } ++ } else { ++ this.connection.teleport(this.camera.getX(), this.camera.getY(), this.camera.getZ(), this.getYRot(), this.getXRot(), TeleportCause.SPECTATE); // CraftBukkit ++ } ++ this.connection.send(new ClientboundSetCameraPacket(entity)); ++ // Paper end + } + + @Override diff --git a/Spigot-Server-Patches/Cap-Entity-Collisions.patch b/patches/server/Cap-Entity-Collisions.patch similarity index 75% rename from Spigot-Server-Patches/Cap-Entity-Collisions.patch rename to patches/server/Cap-Entity-Collisions.patch index 923d549fb2..05e8aa4c03 100644 --- a/Spigot-Server-Patches/Cap-Entity-Collisions.patch +++ b/patches/server/Cap-Entity-Collisions.patch @@ -30,7 +30,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -38,20 +38,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity 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 ++ this.numCollisions = Math.max(0, this.numCollisions - this.level.paperConfig.maxCollisionsPerEntity); // Paper ++ for (j = 0; j < list.size() && this.numCollisions < this.level.paperConfig.maxCollisionsPerEntity; ++j) { // Paper Entity entity = (Entity) list.get(j); + entity.numCollisions++; // Paper -+ numCollisions++; // Paper ++ this.numCollisions++; // Paper - this.C(entity); + this.doPush(entity); } diff --git a/patches/server/Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server/Catch-JsonParseException-in-Entity-and-TE-names.patch new file mode 100644 index 0000000000..10c9fe210e --- /dev/null +++ b/patches/server/Catch-JsonParseException-in-Entity-and-TE-names.patch @@ -0,0 +1,112 @@ +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.BlockPos; + import net.minecraft.core.Direction; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.network.chat.Component; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; +@@ -0,0 +0,0 @@ public final class MCUtil { + } + } + ++ @Nullable ++ public static Component getBaseComponentFromNbt(String key, CompoundTag compound) { ++ if (!compound.contains(key)) { ++ return null; ++ } ++ String string = compound.getString(key); ++ try { ++ return Component.Serializer.fromJson(string); ++ } catch (com.google.gson.JsonParseException e) { ++ org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); ++ } ++ ++ return null; ++ } ++ + public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) { + return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status); + } +diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java ++++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +@@ -0,0 +0,0 @@ import net.minecraft.commands.CommandSourceStack; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.StringUtil; +@@ -0,0 +0,0 @@ public abstract class BaseCommandBlock implements CommandSource { + this.command = nbt.getString("Command"); + this.successCount = nbt.getInt("SuccessCount"); + if (nbt.contains("CustomName", 8)) { +- this.setName(Component.Serializer.fromJson(nbt.getString("CustomName"))); ++ this.setName(MCUtil.getBaseComponentFromNbt("CustomName", nbt)); // Paper - Catch ParseException + } + + if (nbt.contains("TrackOutput", 1)) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BannerBlockEntity.java +@@ -0,0 +0,0 @@ import net.minecraft.nbt.ListTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; ++import net.minecraft.server.MCUtil; + import net.minecraft.world.Nameable; + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.ItemStack; +@@ -0,0 +0,0 @@ public class BannerBlockEntity extends BlockEntity implements Nameable { + public void load(CompoundTag nbt) { + super.load(nbt); + if (nbt.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(nbt.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException + } + + this.itemPatterns = nbt.getList("Patterns", 10); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TranslatableComponent; ++import net.minecraft.server.MCUtil; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.sounds.SoundSource; + import net.minecraft.world.Container; +@@ -0,0 +0,0 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co + super.load(nbt); + this.lockKey = LockCode.fromTag(nbt); + if (nbt.contains("CustomName", 8)) { +- this.name = Component.Serializer.fromJson(nbt.getString("CustomName")); ++ this.name = MCUtil.getBaseComponentFromNbt("CustomName", nbt); // Paper - Catch ParseException + } + + } diff --git a/patches/server/Check-Drowned-for-Villager-Aggression-Config.patch b/patches/server/Check-Drowned-for-Villager-Aggression-Config.patch new file mode 100644 index 0000000000..c059c2d3e9 --- /dev/null +++ b/patches/server/Check-Drowned-for-Villager-Aggression-Config.patch @@ -0,0 +1,19 @@ +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/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +@@ -0,0 +0,0 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, Drowned.class)).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); ++ if (this.level.spigotConfig.zombieAggressiveTowardsVillager) this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); // Paper + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Axolotl.class, true, false)); + this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); diff --git a/Spigot-Server-Patches/Check-online-mode-before-converting-and-renaming-pla.patch b/patches/server/Check-online-mode-before-converting-and-renaming-pla.patch similarity index 54% rename from Spigot-Server-Patches/Check-online-mode-before-converting-and-renaming-pla.patch rename to patches/server/Check-online-mode-before-converting-and-renaming-pla.patch index 0324b67f96..1e04614ee5 100644 --- a/Spigot-Server-Patches/Check-online-mode-before-converting-and-renaming-pla.patch +++ b/patches/server/Check-online-mode-before-converting-and-renaming-pla.patch @@ -4,16 +4,16 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.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"); +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -0,0 +0,0 @@ public class PlayerDataStorage { + File file = new File(this.playerDir, player.getStringUUID() + ".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"); + file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + player.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat"); if ( file.exists() ) diff --git a/Spigot-Server-Patches/Chunk-Save-Reattempt.patch b/patches/server/Chunk-Save-Reattempt.patch similarity index 72% rename from Spigot-Server-Patches/Chunk-Save-Reattempt.patch rename to patches/server/Chunk-Save-Reattempt.patch index fd72511ff3..4896724473 100644 --- a/Spigot-Server-Patches/Chunk-Save-Reattempt.patch +++ b/patches/server/Chunk-Save-Reattempt.patch @@ -18,28 +18,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.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 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.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.nbt.CompoundTag; + import net.minecraft.nbt.NbtIo; +import net.minecraft.server.MinecraftServer; - import net.minecraft.util.ExceptionSuppressor; - import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.util.ExceptionCollector; + import net.minecraft.world.level.ChunkPos; -@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { - protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { - RegionFile regionfile = this.getFile(chunkcoordintpair, false); // CraftBukkit + protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { + RegionFile regionfile = this.getFile(pos, 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 { + if (nbt == null) { + regionfile.clear(pos); +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + } } + // Paper start diff --git a/Spigot-Server-Patches/Chunk-debug-command.patch b/patches/server/Chunk-debug-command.patch similarity index 68% rename from Spigot-Server-Patches/Chunk-debug-command.patch rename to patches/server/Chunk-debug-command.patch index cfe98045b6..e0583e74d1 100644 --- a/Spigot-Server-Patches/Chunk-debug-command.patch +++ b/patches/server/Chunk-debug-command.patch @@ -35,15 +35,19 @@ diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/ 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; +@@ -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.resources.ResourceLocation; 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.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityTypes; - import net.minecraft.world.level.ChunkCoordIntPair; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MCUtil; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -59,7 +63,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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)); + return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); break; + case "debug": + if (args.length == 2) { @@ -119,7 +123,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + int accumulatedEntityTicking = 0; + + for (org.bukkit.World bukkitWorld : worlds) { -+ WorldServer world = ((CraftWorld)bukkitWorld).getHandle(); ++ ServerLevel world = ((CraftWorld)bukkitWorld).getHandle(); + + int total = 0; + int inactive = 0; @@ -127,14 +131,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + int ticking = 0; + int entityTicking = 0; + -+ for (PlayerChunk chunk : world.getChunkProvider().playerChunkMap.updatingChunks.values()) { -+ if (chunk.getFullChunkIfCached() == null) { ++ for (ChunkHolder chunk : world.getChunkSource().chunkMap.updatingChunkMap.values()) { ++ if (chunk.getFullChunkUnchecked() == null) { + continue; + } + + ++total; + -+ PlayerChunk.State state = PlayerChunk.getChunkState(chunk.getTicketLevel()); ++ ChunkHolder.FullChunkStatus state = ChunkHolder.getFullChunkStatus(chunk.getTicketLevel()); + + switch (state) { + case INACCESSIBLE: @@ -211,23 +215,23 @@ diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/ 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; +@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; ++import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.DistanceManager; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; +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.ChunkPos; + import net.minecraft.world.level.ClipContext; + import net.minecraft.world.level.Level; ++import net.minecraft.world.level.chunk.ChunkAccess; +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; @@ -252,16 +256,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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(); + ++ public static ChunkStatus getChunkStatus(ChunkHolder chunk) { ++ List statuses = net.minecraft.server.level.ServerChunkCache.CHUNK_STATUSES; + 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) { ++ CompletableFuture> future = chunk.getFutureIfPresentUnchecked(curr); ++ if (future != ChunkHolder.UNLOADED_CHUNK_FUTURE) { + return curr; + } + } @@ -321,27 +324,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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; ++ ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); ++ ChunkMap chunkMap = world.getChunkSource().chunkMap; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; ++ DistanceManager chunkMapDistance = chunkMap.distanceManager; ++ List allChunks = new ArrayList<>(visibleChunks.values()); ++ List players = world.players; + + int fullLoadedChunks = 0; + -+ for (PlayerChunk chunk : allChunks) { -+ if (chunk.getFullChunkIfCached() != null) { ++ for (ChunkHolder chunk : allChunks) { ++ if (chunk.getFullChunkUnchecked() != 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); ++ allChunks.sort((ChunkHolder v1, ChunkHolder v2) -> { ++ if (v1.pos.x != v2.pos.x) { ++ return Integer.compare(v1.pos.x, v2.pos.x); + } -+ return Integer.compare(v1.location.z, v2.location.z); ++ return Integer.compare(v1.pos.z, v2.pos.z); + }); + + worldData.addProperty("name", world.getWorld().getName()); @@ -349,18 +352,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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("loaded-chunk-count", chunkMap.entitiesInLevel.size()); + worldData.addProperty("verified-fully-loaded-chunks", fullLoadedChunks); + + JsonArray playersData = new JsonArray(); + -+ for (EntityPlayer player : players) { ++ for (ServerPlayer 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()); ++ playerData.addProperty("name", player.getScoreboardName()); ++ playerData.addProperty("x", player.getX()); ++ playerData.addProperty("y", player.getY()); ++ playerData.addProperty("z", player.getZ()); + + playersData.add(playerData); + @@ -370,17 +373,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + JsonArray chunksData = new JsonArray(); + -+ for (PlayerChunk playerChunk : allChunks) { ++ for (ChunkHolder playerChunk : allChunks) { + JsonObject chunkData = new JsonObject(); + -+ Set> tickets = chunkMapDistance.tickets.get(playerChunk.location.pair()); ++ Set> tickets = chunkMapDistance.tickets.get(playerChunk.pos.longKey); + ChunkStatus status = getChunkStatus(playerChunk); + -+ chunkData.addProperty("x", playerChunk.location.x); -+ chunkData.addProperty("z", playerChunk.location.z); ++ chunkData.addProperty("x", playerChunk.pos.x); ++ chunkData.addProperty("z", playerChunk.pos.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("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); ++ chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.longKey)); + chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); + + JsonArray ticketsData = new JsonArray(); @@ -389,10 +392,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + for (Ticket ticket : tickets) { + JsonObject ticketData = new JsonObject(); + -+ ticketData.addProperty("ticket-type", ticket.getTicketType().toString()); ++ ticketData.addProperty("ticket-type", ticket.getType().toString()); + ticketData.addProperty("ticket-level", ticket.getTicketLevel()); -+ ticketData.addProperty("object-reason", String.valueOf(ticket.getObjectReason())); -+ ticketData.addProperty("add-tick", ticket.getCreationTick()); ++ ticketData.addProperty("object-reason", String.valueOf(ticket.key)); ++ ticketData.addProperty("add-tick", ticket.createdTick); + + ticketsData.add(ticketData); + } @@ -421,66 +424,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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; ++ + public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) { + return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status); } diff --git a/patches/server/ChunkMapDistance-CME.patch b/patches/server/ChunkMapDistance-CME.patch new file mode 100644 index 0000000000..8e14449633 --- /dev/null +++ b/patches/server/ChunkMapDistance-CME.patch @@ -0,0 +1,84 @@ +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/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + private boolean resendLight; + private CompletableFuture pendingFullStateConfirmation; + ++ boolean isUpdateQueued = false; // Paper + private final ChunkMap chunkMap; // Paper + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); + private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); + private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(33); +- final Set chunksToUpdateFutures = 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(ChunkHolder o) { ++ if (o.isUpdateQueued) return true; ++ o.isUpdateQueued = true; ++ return super.add(o); ++ } ++ }; ++ // Paper end + final ChunkTaskPriorityQueueSorter ticketThrottler; + final ProcessorHandle> ticketThrottlerInput; + final ProcessorHandle ticketThrottlerReleaser; +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + ; + } + +- if (!this.chunksToUpdateFutures.isEmpty()) { +- // CraftBukkit start +- // Iterate pending chunk updates with protection against concurrent modification exceptions +- java.util.Iterator iter = this.chunksToUpdateFutures.iterator(); +- int expectedSize = this.chunksToUpdateFutures.size(); +- do { +- ChunkHolder playerchunk = iter.next(); +- iter.remove(); +- expectedSize--; +- +- playerchunk.updateFutures(playerchunkmap, this.mainThreadExecutor); +- +- // Reset iterator if set was modified using add() +- if (this.chunksToUpdateFutures.size() != expectedSize) { +- expectedSize = this.chunksToUpdateFutures.size(); +- iter = this.chunksToUpdateFutures.iterator(); +- } +- } while (iter.hasNext()); +- // CraftBukkit end +- ++ // Paper start ++ if (!this.pendingChunkUpdates.isEmpty()) { ++ while(!this.pendingChunkUpdates.isEmpty()) { ++ ChunkHolder remove = this.pendingChunkUpdates.remove(); ++ remove.isUpdateQueued = false; ++ remove.updateFutures(playerchunkmap, this.mainThreadExecutor); ++ } ++ // Paper end + return true; + } else { + if (!this.ticketsToRelease.isEmpty()) { +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + if (k != level) { + playerchunk = DistanceManager.this.updateChunkScheduling(id, level, playerchunk, k); + if (playerchunk != null) { +- DistanceManager.this.chunksToUpdateFutures.add(playerchunk); ++ DistanceManager.this.pendingChunkUpdates.add(playerchunk); + } + + } diff --git a/patches/server/Clean-up-duplicated-GameProfile-Properties.patch b/patches/server/Clean-up-duplicated-GameProfile-Properties.patch new file mode 100644 index 0000000000..11bc0d037f --- /dev/null +++ b/patches/server/Clean-up-duplicated-GameProfile-Properties.patch @@ -0,0 +1,47 @@ +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/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/nbt/NbtUtils.java ++++ b/src/main/java/net/minecraft/nbt/NbtUtils.java +@@ -0,0 +0,0 @@ public final class NbtUtils { + for(String string2 : compoundTag.getAllKeys()) { + ListTag listTag = compoundTag.getList(string2, 10); + +- for(int i = 0; i < listTag.size(); ++i) { ++ if (listTag.size() == 0) continue; // Paper - remove duplicate properties ++ for (int i = listTag.size() - 1; i < listTag.size(); ++i) { // Paper - remove duplicate properties + CompoundTag compoundTag2 = listTag.getCompound(i); + String string3 = compoundTag2.getString("Value"); + if (compoundTag2.contains("Signature", 8)) { +diff --git a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/PlayerHeadItem.java ++++ b/src/main/java/net/minecraft/world/item/PlayerHeadItem.java +@@ -0,0 +0,0 @@ public class PlayerHeadItem extends StandingAndWallBlockItem { + }); + // CraftBukkit start + } else { ++ // Paper start - clean up old duplicated properties ++ CompoundTag properties = nbt.getCompound("SkullOwner").getCompound("Properties"); ++ for (String key : properties.getAllKeys()) { ++ net.minecraft.nbt.ListTag values = properties.getList(key, 10); ++ if (values.size() > 1) { ++ net.minecraft.nbt.Tag texture = values.get(values.size() - 1); ++ values = new net.minecraft.nbt.ListTag(); ++ values.add(texture); ++ properties.put(key, values); ++ } ++ } ++ // Paper end + net.minecraft.nbt.ListTag textures = nbt.getCompound("SkullOwner").getCompound("Properties").getList("textures", 10); // Safe due to method contracts + for (int i = 0; i < textures.size(); i++) { + if (textures.get(i) instanceof CompoundTag && !((CompoundTag) textures.get(i)).contains("Signature", 8) && ((CompoundTag) textures.get(i)).getString("Value").trim().isEmpty()) { diff --git a/Spigot-Server-Patches/Clear-SyncLoadInfo.patch b/patches/server/Clear-SyncLoadInfo.patch similarity index 96% rename from Spigot-Server-Patches/Clear-SyncLoadInfo.patch rename to patches/server/Clear-SyncLoadInfo.patch index 53556925c5..6b97609186 100644 --- a/Spigot-Server-Patches/Clear-SyncLoadInfo.patch +++ b/patches/server/Clear-SyncLoadInfo.patch @@ -35,6 +35,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + SYNC_LOADS.clear(); + } + - public static void logSyncLoad(final World world, final int chunkX, final int chunkZ) { + public static void logSyncLoad(final Level world, final int chunkX, final int chunkZ) { if (!ENABLED) { return; diff --git a/patches/server/Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/Climbing-should-not-bypass-cramming-gamerule.patch new file mode 100644 index 0000000000..3e70015e7f --- /dev/null +++ b/patches/server/Climbing-should-not-bypass-cramming-gamerule.patch @@ -0,0 +1,173 @@ +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 { + wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); + } + ++ public boolean fixClimbingBypassingCrammingRule = false; ++ private void fixClimbingBypassingCrammingRule() { ++ fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); ++ } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +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 Nameable, EntityAccess, CommandSource, n + } + + public boolean isPushable() { ++ // Paper start ++ return isCollidable(false); ++ } ++ ++ public boolean isCollidable(boolean ignoreClimbing) { ++ // Paper end + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -0,0 +0,0 @@ public final class EntitySelector { + } + + public static Predicate pushableBy(Entity entity) { ++ // Paper start - ignoreClimbing param ++ return pushable(entity, false); ++ } ++ ++ public static Predicate pushable(Entity entity, boolean ignoreClimbing) { ++ // Paper end + Team scoreboardteambase = entity.getTeam(); + Team.CollisionRule scoreboardteambase_enumteampush = scoreboardteambase == null ? Team.CollisionRule.ALWAYS : scoreboardteambase.getCollisionRule(); + + return (Predicate) (scoreboardteambase_enumteampush == Team.CollisionRule.NEVER ? Predicates.alwaysFalse() : EntitySelector.NO_SPECTATORS.and((entity1) -> { +- if (!entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API ++ if (!entity1.isCollidable(ignoreClimbing) || !entity1.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(entity1)) { // CraftBukkit - collidable API // Paper - isCollidable + return false; + } else if (entity.level.isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) { + return false; +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + return; + } + // Paper end - don't run getEntities if we're not going to use its result +- List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); ++ List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushable(this, level.paperConfig.fixClimbingBypassingCrammingRule)); // Paper - fix climbing bypassing cramming rule + + if (!list.isEmpty()) { + // Paper - move up +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + return !this.isRemoved() && this.collides; // CraftBukkit + } + ++ // Paper start + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit ++ return this.isCollidable(level.paperConfig.fixClimbingBypassingCrammingRule); ++ } ++ ++ @Override ++ public boolean isCollidable(boolean ignoreClimbing) { ++ return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit ++ // Paper end + } + + // CraftBukkit start - collidable API +diff --git a/src/main/java/net/minecraft/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java ++++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java +@@ -0,0 +0,0 @@ public class Bat extends AmbientCreature { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/animal/Parrot.java b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Parrot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Parrot.java +@@ -0,0 +0,0 @@ public class Parrot extends ShoulderRidingEntity implements FlyingAnimal { + } + + @Override +- public boolean isPushable() { +- return super.isPushable(); // 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/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java +@@ -0,0 +0,0 @@ public abstract class AbstractHorse extends Animal implements ContainerListener, + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return !this.isVehicle(); + } + +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return false; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -0,0 +0,0 @@ public abstract class AbstractMinecart extends Entity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -0,0 +0,0 @@ public class Boat extends Entity { + } + + @Override +- public boolean isPushable() { ++ public boolean isCollidable(boolean ignoreClimbing) { // Paper + return true; + } + diff --git a/patches/server/Collision-option-for-requiring-a-player-participant.patch b/patches/server/Collision-option-for-requiring-a-player-participant.patch new file mode 100644 index 0000000000..df0094b0a3 --- /dev/null +++ b/patches/server/Collision-option-for-requiring-a-player-participant.patch @@ -0,0 +1,81 @@ +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 Nameable, EntityAccess, CommandSource, n + public void push(Entity entity) { + if (!this.isPassengerOfSameVehicle(entity)) { + if (!entity.noPhysics && !this.noPhysics) { ++ if (this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper + double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); + double d2 = Mth.absMax(d0, d1); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; +@@ -0,0 +0,0 @@ public abstract class AbstractMinecart extends Entity { + public void push(Entity entity) { + if (!this.level.isClientSide) { + if (!entity.noPhysics && !this.noPhysics) { ++ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper + if (!this.hasPassenger(entity)) { + // CraftBukkit start + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), entity.getBukkitEntity()); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.FluidTags; +@@ -0,0 +0,0 @@ public class Boat extends Entity { + + @Override + public void push(Entity entity) { ++ if (!this.level.paperConfig.allowVehicleCollisions && this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer)) return; // Paper + if (entity instanceof Boat) { + if (entity.getBoundingBox().minY < this.getBoundingBox().maxY) { + // CraftBukkit start diff --git a/Spigot-Server-Patches/Complete-resource-pack-API.patch b/patches/server/Complete-resource-pack-API.patch similarity index 64% rename from Spigot-Server-Patches/Complete-resource-pack-API.patch rename to patches/server/Complete-resource-pack-API.patch index 8b227d16b4..fda921c869 100644 --- a/Spigot-Server-Patches/Complete-resource-pack-API.patch +++ b/patches/server/Complete-resource-pack-API.patch @@ -4,23 +4,24 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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()])); +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + ServerGamePacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack rejection", this.player.getName()); + this.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect")); + } +- this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()])); // CraftBukkit +- + // Paper start -+ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packetplayinresourcepackstatus.status.ordinal()]; ++ PlayerResourcePackStatusEvent.Status packStatus = PlayerResourcePackStatusEvent.Status.values()[packet.action.ordinal()]; + player.getBukkitEntity().setResourcePackStatus(packStatus); -+ this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus)); ++ this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), packStatus)); // CraftBukkit + // Paper end } - // CraftBukkit end + @Override 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 @@ -34,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private String resourcePackHash; + // Paper end - public CraftPlayer(CraftServer server, EntityPlayer entity) { + public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public boolean getAffectsSpawning() { @@ -45,7 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ this.getHandle().sendTexturePack(url, hash, false, new net.minecraft.network.chat.TextComponent("")); + } + + @Override diff --git a/Spigot-Server-Patches/Configurable-Alternative-LootPool-Luck-Formula.patch b/patches/server/Configurable-Alternative-LootPool-Luck-Formula.patch similarity index 71% rename from Spigot-Server-Patches/Configurable-Alternative-LootPool-Luck-Formula.patch rename to patches/server/Configurable-Alternative-LootPool-Luck-Formula.patch index 3048e10002..3dc4ee6675 100644 --- a/Spigot-Server-Patches/Configurable-Alternative-LootPool-Luck-Formula.patch +++ b/patches/server/Configurable-Alternative-LootPool-Luck-Formula.patch @@ -52,40 +52,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } } -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 +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.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() { -+ } - +--- a/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/entries/LootPoolSingletonContainer.java +@@ -0,0 +0,0 @@ public abstract class LootPoolSingletonContainer extends LootPoolEntryContainer + protected abstract class EntryBase implements LootPoolEntry { @Override - public int a(float f) { -- return Math.max(MathHelper.d((float) LootSelectorEntry.this.c + (float) LootSelectorEntry.this.e * f), 0); + public int getWeight(float luck) { +- return Math.max(Mth.floor((float)LootPoolSingletonContainer.this.weight + (float)LootPoolSingletonContainer.this.quality * luck), 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) { ++ if (LootPoolSingletonContainer.this.lastLuck != null && LootPoolSingletonContainer.this.lastLuck == luck) { + return lastWeight; + } + // This is vanilla -+ float qualityModifer = (float) getQuality() * f; -+ double baseWeight = (getWeight() + qualityModifer); ++ float qualityModifer = (float) LootPoolSingletonContainer.this.quality * luck; ++ double baseWeight = (LootPoolSingletonContainer.this.weight + qualityModifer); + if (com.destroystokyo.paper.PaperConfig.useAlternativeLuckFormula) { + // Random boost to avoid losing precision in the final int cast on return + final int weightBoost = 100; @@ -95,16 +78,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // =($B2*(($B2-100)/100/100)) + double impacted = baseWeight * ((baseWeight - weightBoost) / weightBoost / 100); + // =($B$7/100) -+ float luckModifier = Math.min(100, f * 10) / 100; ++ float luckModifier = Math.min(100, luck * 10) / 100; + // =B2 - (C2 *($B$7/100)) + baseWeight = Math.ceil(baseWeight - (impacted * luckModifier)); + } -+ lastLuck = f; -+ lastWeight = (int) Math.max(0, Math.floor(baseWeight)); ++ LootPoolSingletonContainer.this.lastLuck = luck; ++ LootPoolSingletonContainer.this.lastWeight = (int) Math.max(Math.floor(baseWeight), 0); + return lastWeight; } } + private Float lastLuck = null; + private int lastWeight = 0; + // Paper end - } + + @FunctionalInterface + protected interface EntryConstructor { diff --git a/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch b/patches/server/Configurable-Cartographer-Treasure-Maps.patch similarity index 57% rename from Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch rename to patches/server/Configurable-Cartographer-Treasure-Maps.patch index 1db2b7b30d..5b665b7cf0 100644 --- a/Spigot-Server-Patches/Configurable-Cartographer-Treasure-Maps.patch +++ b/patches/server/Configurable-Cartographer-Treasure-Maps.patch @@ -34,32 +34,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 + ServerLevel serverLevel = (ServerLevel)entity.level; +- BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, entity.blockPosition(), 100, true); ++ if (!serverLevel.paperConfig.enableTreasureMaps) return null; // Paper ++ BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, entity.blockPosition(), 100, !serverLevel.paperConfig.treasureMapsAlreadyDiscovered); // Paper + if (blockPos != null) { + ItemStack itemStack = MapItem.create(serverLevel, blockPos.getX(), blockPos.getZ(), (byte)2, true, true); + MapItem.renderBiomePreviewMap(serverLevel, itemStack); +diff --git a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.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); +--- a/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java ++++ b/src/main/java/net/minecraft/world/level/storage/loot/functions/ExplorationMapFunction.java +@@ -0,0 +0,0 @@ public class ExplorationMapFunction extends LootItemConditionalFunction { + Vec3 vec3 = context.getParamOrNull(LootContextParams.ORIGIN); + if (vec3 != null) { + ServerLevel serverLevel = context.getLevel(); +- BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, new BlockPos(vec3), this.searchRadius, this.skipKnownStructures); + // Paper start -+ if (!worldserver.paperConfig.enableTreasureMaps) { ++ if (!serverLevel.paperConfig.enableTreasureMaps) { + /* + * NOTE: I fear users will just get a plain map as their "treasure" + * This is preferable to disrespecting the config. + */ -+ return itemstack; ++ return stack; + } + // 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); ++ BlockPos blockPos = serverLevel.findNearestMapFeature(this.destination, new BlockPos(vec3), this.searchRadius, !serverLevel.paperConfig.treasureMapsAlreadyDiscovered && this.skipKnownStructures); // Paper + if (blockPos != null) { + ItemStack itemStack = MapItem.create(serverLevel, blockPos.getX(), blockPos.getZ(), this.zoom, true, true); + MapItem.renderBiomePreviewMap(serverLevel, itemStack); diff --git a/Spigot-Server-Patches/Configurable-Chunk-Inhabited-Time.patch b/patches/server/Configurable-Chunk-Inhabited-Time.patch similarity index 78% rename from Spigot-Server-Patches/Configurable-Chunk-Inhabited-Time.patch rename to patches/server/Configurable-Chunk-Inhabited-Time.patch index 3c0704a53d..b12a8bf6ac 100644 --- a/Spigot-Server-Patches/Configurable-Chunk-Inhabited-Time.patch +++ b/patches/server/Configurable-Chunk-Inhabited-Time.patch @@ -29,16 +29,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.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 { +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { @Override public long getInhabitedTime() { - return this.inhabitedTime; -+ return world.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : world.paperConfig.fixedInhabitedTime; // Paper ++ return this.level.paperConfig.fixedInhabitedTime < 0 ? this.inhabitedTime : this.level.paperConfig.fixedInhabitedTime; // Paper } @Override diff --git a/Spigot-Server-Patches/Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server/Configurable-Disabling-Cat-Chest-Detection.patch similarity index 60% rename from Spigot-Server-Patches/Configurable-Disabling-Cat-Chest-Detection.patch rename to patches/server/Configurable-Disabling-Cat-Chest-Detection.patch index 28bf04eaad..08ba68be30 100644 --- a/Spigot-Server-Patches/Configurable-Disabling-Cat-Chest-Detection.patch +++ b/patches/server/Configurable-Disabling-Cat-Chest-Detection.patch @@ -19,19 +19,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.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 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -0,0 +0,0 @@ public class ChestBlock extends AbstractChestBlock implements } - private static boolean b(GeneratorAccess generatoraccess, BlockPosition blockposition) { + private static boolean isCatSittingOnChest(LevelAccessor world, BlockPos pos) { + // Paper start - Option to disable chest cat detection -+ if (((World) generatoraccess).paperConfig.disableChestCatDetection) { ++ if (((Level) world).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))); + List list = world.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1))); if (!list.isEmpty()) { diff --git a/Spigot-Server-Patches/Configurable-Grass-Spread-Tick-Rate.patch b/patches/server/Configurable-Grass-Spread-Tick-Rate.patch similarity index 53% rename from Spigot-Server-Patches/Configurable-Grass-Spread-Tick-Rate.patch rename to patches/server/Configurable-Grass-Spread-Tick-Rate.patch index 25c227684c..e4a89bc4f1 100644 --- a/Spigot-Server-Patches/Configurable-Grass-Spread-Tick-Rate.patch +++ b/patches/server/Configurable-Grass-Spread-Tick-Rate.patch @@ -19,23 +19,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.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 +--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.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.core.BlockPos; + import net.minecraft.core.Direction; +import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.WorldServer; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.tags.FluidTags; import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsFluid; -@@ -0,0 +0,0 @@ public abstract class BlockDirtSnowSpreadable extends BlockDirtSnow { +@@ -0,0 +0,0 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { @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)) { + public void randomTick(BlockState state, ServerLevel world, BlockPos pos, Random random) { ++ if (this instanceof GrassBlock && world.paperConfig.grassUpdateRate != 1 && (world.paperConfig.grassUpdateRate < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig.grassUpdateRate != 0)) { return; } // Paper + if (!SpreadingSnowyDirtBlock.canBeGrass(state, (LevelReader) world, pos)) { // CraftBukkit start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(worldserver, blockposition, Blocks.DIRT.getBlockData()).isCancelled()) { + if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { diff --git a/Spigot-Server-Patches/Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/Configurable-Keep-Spawn-Loaded-range-per-world.patch similarity index 52% rename from Spigot-Server-Patches/Configurable-Keep-Spawn-Loaded-range-per-world.patch rename to patches/server/Configurable-Keep-Spawn-Loaded-range-per-world.patch index 7bb6222793..be49f3160a 100644 --- a/Spigot-Server-Patches/Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -10,52 +10,53 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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)); + } - } ++ + 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)); 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) { ++ public void removeTicketsForSpawn(int radiusInBlocks, BlockPos 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(); ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); + 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); ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(x, 0, z)), 2, Unit.INSTANCE); + } + } + @@ -155,80 +152,74 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(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 ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(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 ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(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 ++ chunkproviderserver.removeRegionTicket(TicketType.START, new ChunkPos(spawn.offset(-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())); + public void setDefaultSpawnPos(BlockPos pos, float angle) { +- ChunkPos chunkcoordintpair = new ChunkPos(new BlockPos(this.levelData.getXSpawn(), 0, this.levelData.getZSpawn())); + // Paper - configurable spawn radius -+ BlockPosition prevSpawn = this.getSpawn(); ++ BlockPos prevSpawn = this.getSharedSpawnPos(); + //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); + this.levelData.setSpawn(pos, angle); +- this.getChunkSource().removeRegionTicket(TicketType.START, chunkcoordintpair, 11, Unit.INSTANCE); +- this.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(pos), 11, Unit.INSTANCE); + 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.addTicketsForSpawn(this.paperConfig.keepLoadedRange, pos); + } - this.getMinecraftServer().getPlayerList().sendAll(new PacketPlayOutSpawnPosition(blockposition, f)); + this.getServer().getPlayerList().broadcastAll(new ClientboundSetDefaultSpawnPositionPacket(pos, angle)); } -diff --git a/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java b/src/main/java/net/minecraft/server/level/progress/WorldLoadListener.java +diff --git a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.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); +--- a/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/ChunkProgressListener.java +@@ -0,0 +0,0 @@ public interface ChunkProgressListener { + void start(); - void b(); + void stop(); + + 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 +diff --git a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.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 +--- a/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java ++++ b/src/main/java/net/minecraft/server/level/progress/LoggerChunkProgressListener.java @@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; - public class WorldLoadListenerLogger implements WorldLoadListener { + public class LoggerChunkProgressListener implements ChunkProgressListener { 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; +- private final int maxCount; ++ private int maxCount; // Paper - remove final + private int count; + private long startTime; + private long nextTickTime = Long.MAX_VALUE; - public WorldLoadListenerLogger(int i) { -- int j = i * 2 + 1; + public LoggerChunkProgressListener(int radius) { + // Paper start - Allow changing radius later for configurable spawn patch -+ this.setChunkRadius(i); // Move to method ++ this.setChunkRadius(radius); // Move to method + } + + @Override + public void setChunkRadius(int radius) { -+ // Paper - copied from above -+ int j = radius * 2 + 1; - - this.b = j * j; ++ // Paper end + int i = radius * 2 + 1; + this.maxCount = i * i; } -+ // 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 @@ -237,23 +228,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void setKeepSpawnInMemory(boolean keepLoaded) { +- world.keepSpawnInMemory = keepLoaded; + // Paper start - Configurable spawn radius + if (keepLoaded == world.keepSpawnInMemory) { + // do nothing, nothing has changed + return; + } - world.keepSpawnInMemory = keepLoaded; ++ this.world.keepSpawnInMemory = keepLoaded; // Grab the worlds spawn chunk -- BlockPosition chunkcoordinates = this.world.getSpawn(); -+ BlockPosition prevSpawn = this.world.getSpawn(); + BlockPos chunkcoordinates = this.world.getSharedSpawnPos(); if (keepLoaded) { -- world.getChunkProvider().addTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); -+ world.addTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); +- this.world.getChunkSource().addRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); ++ this.world.addTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates); } else { - // TODO: doesn't work well if spawn changed.... -- world.getChunkProvider().removeTicket(TicketType.START, new ChunkCoordIntPair(chunkcoordinates), 11, Unit.INSTANCE); +- this.world.getChunkSource().removeRegionTicket(TicketType.START, new ChunkPos(chunkcoordinates), 11, Unit.INSTANCE); + // TODO: doesn't work well if spawn changed.... // paper - resolved -+ world.removeTicketsForSpawn(world.paperConfig.keepLoadedRange, prevSpawn); ++ this.world.removeTicketsForSpawn(this.world.paperConfig.keepLoadedRange, chunkcoordinates); } + // Paper end } diff --git a/Spigot-Server-Patches/Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server/Configurable-Non-Player-Arrow-Despawn-Rate.patch similarity index 65% rename from Spigot-Server-Patches/Configurable-Non-Player-Arrow-Despawn-Rate.patch rename to patches/server/Configurable-Non-Player-Arrow-Despawn-Rate.patch index c1621a49aa..fe145bb911 100644 --- a/Spigot-Server-Patches/Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ b/patches/server/Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -29,16 +29,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EntityArrow.java -@@ -0,0 +0,0 @@ public abstract class EntityArrow extends IProjectile { +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -0,0 +0,0 @@ public abstract class AbstractArrow extends Projectile { - 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(); + protected void tickDespawn() { + ++this.life; +- if (this.life >= ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)) { // Spigot ++ if (this.life >= (pickup == Pickup.CREATIVE_ONLY ? level.paperConfig.creativeArrowDespawnRate : (pickup == Pickup.DISALLOWED ? level.paperConfig.nonPlayerArrowDespawnRate : ((this instanceof ThrownTrident) ? level.spigotConfig.tridentDespawnRate : level.spigotConfig.arrowDespawnRate)))) { // Spigot // Paper - TODO: Extract this to init? + this.discard(); } diff --git a/Spigot-Server-Patches/Configurable-Player-Collision.patch b/patches/server/Configurable-Player-Collision.patch similarity index 50% rename from Spigot-Server-Patches/Configurable-Player-Collision.patch rename to patches/server/Configurable-Player-Collision.patch index 00c04944a3..7d877edd32 100644 --- a/Spigot-Server-Patches/Configurable-Player-Collision.patch +++ b/patches/server/Configurable-Player-Collision.patch @@ -18,101 +18,101 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetPlayerTeamPacket.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()); ++ final ServerScoreboard scoreboard = this.getScoreboard(); ++ final java.util.Collection toRemove = scoreboard.getPlayerTeams().stream().filter(team -> team.getName().startsWith("collideRule_")).map(PlayerTeam::getName).collect(java.util.stream.Collectors.toList()); + for (String teamName : toRemove) { -+ scoreboard.removeTeam(scoreboard.getTeam(teamName)); // Clean up after ourselves ++ scoreboard.removePlayerTeam(scoreboard.getPlayersTeam(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 ++ PlayerTeam collideTeam = scoreboard.addPlayerTeam(this.getPlayerList().collideRuleTeamName); ++ collideTeam.setSeeFriendlyInvisibles(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(); + this.connection.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 @@ import net.minecraft.world.level.storage.PlayerDataStorage; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.Objective; + import net.minecraft.world.scores.PlayerTeam; ++import net.minecraft.world.scores.Scoreboard; // Paper + import net.minecraft.world.scores.Team; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; @@ -0,0 +0,0 @@ public abstract class PlayerList { // CraftBukkit start private CraftServer cserver; - private final Map playersByName = new java.util.HashMap<>(); + 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); + public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { + this.cserver = server.server = new CraftServer((DedicatedServer) server, this); @@ -0,0 +0,0 @@ public abstract class PlayerList { - } - entityplayer.syncInventory(); + player.initInventoryMenu(); + // CraftBukkit - Moved from above, added world + // 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); ++ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam collideRuleTeam = scoreboard.getPlayersTeam(this.collideRuleTeamName); ++ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) { ++ scoreboard.addPlayerToTeam(player.getScoreboardName(), 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()); + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ()); } + @@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.playerTick(); // SPIGOT-924 + entityplayer.doTick(); // 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); ++ final Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName); ++ if (entityplayer.getTeam() == team && team != null) { ++ scoreBoard.removePlayerFromTeam(entityplayer.getScoreboardName(), team); + } + } + // Paper end + - this.savePlayerFile(entityplayer); + this.save(entityplayer); if (entityplayer.isPassenger()) { Entity entity = entityplayer.getRootVehicle(); @@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -121,9 +121,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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); ++ final Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); ++ final PlayerTeam team = scoreboard.getPlayersTeam(this.collideRuleTeamName); ++ if (team != null) scoreboard.removePlayerTeam(team); + } + // Paper end } diff --git a/patches/server/Configurable-RCON-IP-address.patch b/patches/server/Configurable-RCON-IP-address.patch new file mode 100644 index 0000000000..4c9f5b3283 --- /dev/null +++ b/patches/server/Configurable-RCON-IP-address.patch @@ -0,0 +1,44 @@ +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 Settings +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/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTransformEvent; + public class Zombie extends Monster { + + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); ++ private final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); private final AttributeModifier babyModifier = this.SPEED_MODIFIER_BABY; // Paper - remove static - Make baby speed configurable + private static final EntityDataAccessor DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); + public static final EntityDataAccessor DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + if (this.level != null && !this.level.isClientSide) { + AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); + +- attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY); ++ attributemodifiable.removeModifier(this.babyModifier); // Paper + if (baby) { +- attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); ++ attributemodifiable.addTransientModifier(this.babyModifier); // Paper + } + } + diff --git a/patches/server/Configurable-cactus-bamboo-and-reed-growth-heights.patch b/patches/server/Configurable-cactus-bamboo-and-reed-growth-heights.patch new file mode 100644 index 0000000000..846a0408e7 --- /dev/null +++ b/patches/server/Configurable-cactus-bamboo-and-reed-growth-heights.patch @@ -0,0 +1,114 @@ +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/BambooBlock.java b/src/main/java/net/minecraft/world/level/block/BambooBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BambooBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BambooBlock.java +@@ -0,0 +0,0 @@ public class BambooBlock extends Block implements BonemealableBlock { + if (random.nextInt(Math.max(1, (int) (100.0F / world.spigotConfig.bambooModifier) * 3)) == 0 && world.isEmptyBlock(pos.above()) && world.getRawBrightness(pos.above(), 0) >= 9) { // Spigot + int i = this.getHeightBelowUpToMax((BlockGetter) world, pos) + 1; + +- if (i < 16) { ++ if (i < world.paperConfig.bambooMaxHeight) { // Paper + this.growBamboo(state, (Level) world, pos, random, i); + } + } +@@ -0,0 +0,0 @@ public class BambooBlock extends Block implements BonemealableBlock { + int i = this.getHeightAboveUpToMax(world, pos); + int j = this.getHeightBelowUpToMax(world, pos); + +- return i + j + 1 < 16 && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; ++ return i + j + 1 < ((Level) world).paperConfig.bambooMaxHeight && (Integer) world.getBlockState(pos.above(i)).getValue(BambooBlock.STAGE) != 1; // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class BambooBlock extends Block implements BonemealableBlock { + BlockPos blockposition1 = pos.above(i); + BlockState iblockdata1 = world.getBlockState(blockposition1); + +- if (k >= 16 || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // CraftBukkit - If the BlockSpreadEvent was cancelled, we have no bamboo here ++ if (k >= world.paperConfig.bambooMaxHeight || !iblockdata1.is(Blocks.BAMBOO) || (Integer) iblockdata1.getValue(BambooBlock.STAGE) == 1 || !world.isEmptyBlock(blockposition1.above())) { // 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 BambooBlock extends Block implements BonemealableBlock { + } + + int j = (Integer) state.getValue(BambooBlock.AGE) != 1 && !iblockdata2.is(Blocks.BAMBOO) ? 0 : 1; +- int k = (height < 11 || random.nextFloat() >= 0.25F) && height != 15 ? 0 : 1; ++ int k = (height < world.paperConfig.bambooMinHeight || random.nextFloat() >= 0.25F) && height != (world.paperConfig.bambooMaxHeight - 1) ? 0 : 1; // Paper + + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, pos.above(), (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(BambooBlock.AGE, j)).setValue(BambooBlock.LEAVES, blockpropertybamboosize)).setValue(BambooBlock.STAGE, k), 3)) { +@@ -0,0 +0,0 @@ public class BambooBlock extends Block implements BonemealableBlock { + protected int getHeightAboveUpToMax(BlockGetter world, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.above(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper + ; + } + +@@ -0,0 +0,0 @@ public class BambooBlock extends Block implements BonemealableBlock { + protected int getHeightBelowUpToMax(BlockGetter world, BlockPos pos) { + int i; + +- for (i = 0; i < 16 && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { ++ for (i = 0; i < ((Level) world).paperConfig.bambooMaxHeight && world.getBlockState(pos.below(i + 1)).is(Blocks.BAMBOO); ++i) { // Paper + ; + } + +diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java +@@ -0,0 +0,0 @@ public class CactusBlock extends Block { + ; + } + +- if (i < 3) { ++ if (i < world.paperConfig.cactusMaxHeight) { // Paper - Configurable growth height + int j = (Integer) state.getValue(CactusBlock.AGE); + + if (j >= (byte) range(3, ((100.0F / world.spigotConfig.cactusModifier) * 15) + 0.5F, 15)) { // Spigot +diff --git a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SugarCaneBlock.java +@@ -0,0 +0,0 @@ public class SugarCaneBlock extends Block { + ; + } + +- if (i < 3) { ++ if (i < world.paperConfig.reedMaxHeight) { // Paper - Configurable growth height + int j = (Integer) state.getValue(SugarCaneBlock.AGE); + + if (j >= (byte) range(3, ((100.0F / world.spigotConfig.caneModifier) * 15) + 0.5F, 15)) { // Spigot diff --git a/Spigot-Server-Patches/Configurable-chance-of-villager-zombie-infection.patch b/patches/server/Configurable-chance-of-villager-zombie-infection.patch similarity index 50% rename from Spigot-Server-Patches/Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/Configurable-chance-of-villager-zombie-infection.patch index 09eca278d0..b66a17cb34 100644 --- a/Spigot-Server-Patches/Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/Configurable-chance-of-villager-zombie-infection.patch @@ -12,33 +12,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 ++ + public int lightQueueSize = 20; + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.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 { +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -0,0 +0,0 @@ public class Zombie extends Monster { @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()) { + public void killed(ServerLevel world, LivingEntity other) { + super.killed(world, other); +- if ((world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) { +- if (world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { ++ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) { ++ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { return; } -+ if (world.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > world.paperConfig.zombieVillagerInfectionChance) { ++ if (level.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > level.paperConfig.zombieVillagerInfectionChance) { + return; + } // Paper end - EntityVillager entityvillager = (EntityVillager) entityliving; + Villager entityvillager = (Villager) other; // CraftBukkit start diff --git a/patches/server/Configurable-connection-throttle-kick-message.patch b/patches/server/Configurable-connection-throttle-kick-message.patch new file mode 100644 index 0000000000..002b5bea10 --- /dev/null +++ b/patches/server/Configurable-connection-throttle-kick-message.patch @@ -0,0 +1,35 @@ +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/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + synchronized (ServerHandshakePacketListenerImpl.throttleTracker) { + if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) { + ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime); +- TranslatableComponent chatmessage = new TranslatableComponent("Connection throttled! Please wait before reconnecting."); ++ TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; diff --git a/Spigot-Server-Patches/Configurable-container-update-tick-rate.patch b/patches/server/Configurable-container-update-tick-rate.patch similarity index 60% rename from Spigot-Server-Patches/Configurable-container-update-tick-rate.patch rename to patches/server/Configurable-container-update-tick-rate.patch index 13cf2d78b0..b3303b37db 100644 --- a/Spigot-Server-Patches/Configurable-container-update-tick-rate.patch +++ b/patches/server/Configurable-container-update-tick-rate.patch @@ -18,29 +18,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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; +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + private int containerCounter; + public int latency; + public boolean wonGame; + private int containerUpdateDelay; // Paper // CraftBukkit start public String displayName; -@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { - --this.noDamageTicks; +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + --this.invulnerableTime; } -- this.activeContainer.c(); +- this.containerMenu.broadcastChanges(); + // Paper start - Configurable container update tick rate + if (--containerUpdateDelay <= 0) { -+ this.activeContainer.c(); -+ containerUpdateDelay = world.paperConfig.containerUpdateTickRate; ++ this.containerMenu.broadcastChanges(); ++ containerUpdateDelay = level.paperConfig.containerUpdateTickRate; + } + // Paper end - if (!this.world.isClientSide && !this.activeContainer.canUse(this)) { - this.closeInventory(); - this.activeContainer = this.defaultContainer; + if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { + this.closeContainer(); + this.containerMenu = this.inventoryMenu; diff --git a/patches/server/Configurable-door-breaking-difficulty.patch b/patches/server/Configurable-door-breaking-difficulty.patch new file mode 100644 index 0000000000..79052186b7 --- /dev/null +++ b/patches/server/Configurable-door-breaking-difficulty.patch @@ -0,0 +1,86 @@ +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 @@ package com.destroystokyo.paper; + + import java.util.Arrays; + import java.util.List; +- ++import java.util.stream.Collectors; ++import net.minecraft.world.Difficulty; ++import net.minecraft.world.entity.monster.Vindicator; ++import net.minecraft.world.entity.monster.Zombie; + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; + import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; +@@ -0,0 +0,0 @@ public class PaperWorldConfig { + 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", ++ java.util.Arrays.stream(Difficulty.values()) ++ .filter(Zombie.DOOR_BREAKING_PREDICATE) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ vindicatorBreakDoors = getEnumList( ++ "door-breaking-difficulty.vindicator", ++ java.util.Arrays.stream(Difficulty.values()) ++ .filter(Vindicator.DOOR_BREAKING_PREDICATE) ++ .collect(Collectors.toList()), ++ Difficulty.class ++ ); ++ } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +@@ -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; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Vindicator.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Vindicator.java +@@ -0,0 +0,0 @@ public class Vindicator extends AbstractIllager { + + static class VindicatorBreakDoorGoal extends BreakDoorGoal { + public VindicatorBreakDoorGoal(Mob mob) { +- super(mob, 6, Vindicator.DOOR_BREAKING_PREDICATE); ++ super(mob, 6, com.google.common.base.Predicates.in(mob.level.paperConfig.vindicatorBreakDoors)); // Paper + this.setFlags(EnumSet.of(Goal.Flag.MOVE)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + + public Zombie(EntityType type, Level world) { + super(type, world); +- this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE); ++ this.breakDoorGoal = new BreakDoorGoal(this, com.google.common.base.Predicates.in(world.paperConfig.zombieBreakDoors)); // Paper + } + + public Zombie(Level world) { diff --git a/patches/server/Configurable-end-credits.patch b/patches/server/Configurable-end-credits.patch new file mode 100644 index 0000000000..5e1a6bda53 --- /dev/null +++ b/patches/server/Configurable-end-credits.patch @@ -0,0 +1,33 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.unRide(); + this.getLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + if (!this.wonGame) { ++ if (level.paperConfig.disableEndCredits) this.seenCredits = true; // Paper - Toggle to always disable end credits + this.wonGame = true; + this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); + this.seenCredits = true; diff --git a/Spigot-Server-Patches/Configurable-fishing-time-ranges.patch b/patches/server/Configurable-fishing-time-ranges.patch similarity index 72% rename from Spigot-Server-Patches/Configurable-fishing-time-ranges.patch rename to patches/server/Configurable-fishing-time-ranges.patch index 7952235d02..bbf1a9c7ed 100644 --- a/Spigot-Server-Patches/Configurable-fishing-time-ranges.patch +++ b/patches/server/Configurable-fishing-time-ranges.patch @@ -21,18 +21,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.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); +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -0,0 +0,0 @@ public class FishingHook extends Projectile { + this.noCulling = true; + this.luck = Math.max(0, lureLevel); + this.lureSpeed = Math.max(0, luckOfTheSeaLevel); + // Paper start + minWaitTime = world.paperConfig.fishingMinTicks; + maxWaitTime = world.paperConfig.fishingMaxTicks; + // paper end } - public EntityFishingHook(EntityHuman entityhuman, World world, int i, int j) { + public FishingHook(EntityType type, Level world) { diff --git a/Spigot-Server-Patches/Configurable-flying-kick-messages.patch b/patches/server/Configurable-flying-kick-messages.patch similarity index 55% rename from Spigot-Server-Patches/Configurable-flying-kick-messages.patch rename to patches/server/Configurable-flying-kick-messages.patch index a46d5752f9..1f514b8a6b 100644 --- a/Spigot-Server-Patches/Configurable-flying-kick-messages.patch +++ b/patches/server/Configurable-flying-kick-messages.patch @@ -20,24 +20,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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")); +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + if (this.clientIsFloating && !this.player.isSleeping()) { + if (++this.aboveGroundTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating too long!", this.player.getName().getString()); +- this.disconnect(new TranslatableComponent("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")); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + if (this.clientVehicleIsFloating && this.player.getRootVehicle().getControllingPassenger() == this.player) { + if (++this.aboveGroundVehicleTickCount > 80) { + ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked for floating a vehicle too long!", this.player.getName().getString()); +- this.disconnect(new TranslatableComponent("multiplayer.disconnect.flying")); + this.disconnect(com.destroystokyo.paper.PaperConfig.flyingKickVehicleMessage); // Paper - use configurable kick message return; } diff --git a/Spigot-Server-Patches/Configurable-inter-world-teleportation-safety.patch b/patches/server/Configurable-inter-world-teleportation-safety.patch similarity index 98% rename from Spigot-Server-Patches/Configurable-inter-world-teleportation-safety.patch rename to patches/server/Configurable-inter-world-teleportation-safety.patch index 0969946e5c..71f421ed4f 100644 --- a/Spigot-Server-Patches/Configurable-inter-world-teleportation-safety.patch +++ b/patches/server/Configurable-inter-world-teleportation-safety.patch @@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + entity.connection.teleport(to); } else { - server.getHandle().moveToWorld(entity, toWorld, true, to, true); + server.getHandle().moveToWorld(entity, toWorld, true, to, !toWorld.paperConfig.disableTeleportationSuffocationCheck); // Paper diff --git a/Spigot-Server-Patches/Configurable-max-leash-distance.patch b/patches/server/Configurable-max-leash-distance.patch similarity index 50% rename from Spigot-Server-Patches/Configurable-max-leash-distance.patch rename to patches/server/Configurable-max-leash-distance.patch index a5880f394f..03706c8646 100644 --- a/Spigot-Server-Patches/Configurable-max-leash-distance.patch +++ b/patches/server/Configurable-max-leash-distance.patch @@ -21,25 +21,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.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); +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -0,0 +0,0 @@ public abstract class PathfinderMob extends Mob { + float f = this.distanceTo(entity); - if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) { + if (this instanceof TamableAnimal && ((TamableAnimal) this).isInSittingPose()) { - 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); ++ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper + this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); } -@@ -0,0 +0,0 @@ public abstract class EntityCreature extends EntityInsentient { +@@ -0,0 +0,0 @@ public abstract class PathfinderMob extends Mob { } - this.x(f); + this.onLeashDistance(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); ++ if (f > entity.level.paperConfig.maxLeashDistance) { // Paper + this.level.getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit + this.dropLeash(true, true); + this.goalSelector.disableControlFlag(Goal.Flag.MOVE); diff --git a/patches/server/Configurable-mob-spawner-tick-rate.patch b/patches/server/Configurable-mob-spawner-tick-rate.patch new file mode 100644 index 0000000000..7ad5100943 --- /dev/null +++ b/patches/server/Configurable-mob-spawner-tick-rate.patch @@ -0,0 +1,62 @@ +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/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + public int requiredPlayerRange; + public int spawnRange; + private final Random random; ++ private int tickDelay = 0; // Paper + + public BaseSpawner() { + this.spawnPotentials = BaseSpawner.EMPTY_POTENTIALS; +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + } + + public void serverTick(ServerLevel world, BlockPos pos) { ++ // Paper start - Configurable mob spawner tick rate ++ if (spawnDelay > 0 && --tickDelay > 0) return; ++ tickDelay = world.paperConfig.mobSpawnerTickRate; ++ // Paper end + if (this.isNearPlayer(world, pos)) { +- if (this.spawnDelay == -1) { ++ if (this.spawnDelay < -tickDelay) { + this.delay(world, pos); + } + + if (this.spawnDelay > 0) { +- --this.spawnDelay; ++ this.spawnDelay -= tickDelay; // Paper + } else { + boolean flag = false; + +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + ((Mob) entity).finalizeSpawn(world, world.getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.SPAWNER, (SpawnGroupData) null, (CompoundTag) null); + } + // Spigot Start +- if ( entityinsentient.level.spigotConfig.nerfSpawnerMobs ) +- { ++ if (entityinsentient.level.spigotConfig.nerfSpawnerMobs) { + entityinsentient.aware = false; + } + // Spigot End diff --git a/Spigot-Server-Patches/Configurable-packet-in-spam-threshold.patch b/patches/server/Configurable-packet-in-spam-threshold.patch similarity index 61% rename from Spigot-Server-Patches/Configurable-packet-in-spam-threshold.patch rename to patches/server/Configurable-packet-in-spam-threshold.patch index d2d7766003..e55dec19fd 100644 --- a/Spigot-Server-Patches/Configurable-packet-in-spam-threshold.patch +++ b/patches/server/Configurable-packet-in-spam-threshold.patch @@ -22,24 +22,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // 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 +- if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < 30 && this.limitedPackets++ >= 4) { ++ if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < THRESHOLD && this.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; +- if (this.lastLimitedPacket == -1 || timestamp - this.lastLimitedPacket >= 30) { ++ if (this.lastLimitedPacket == -1 || timestamp - this.lastLimitedPacket >= THRESHOLD) { // Paper + this.lastLimitedPacket = timestamp; + this.limitedPackets = 0; return true; diff --git a/Spigot-Server-Patches/Configurable-projectile-relative-velocity.patch b/patches/server/Configurable-projectile-relative-velocity.patch similarity index 72% rename from Spigot-Server-Patches/Configurable-projectile-relative-velocity.patch rename to patches/server/Configurable-projectile-relative-velocity.patch index 0e58198579..73a7dffd47 100644 --- a/Spigot-Server-Patches/Configurable-projectile-relative-velocity.patch +++ b/patches/server/Configurable-projectile-relative-velocity.patch @@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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"); + log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); } } + @@ -38,16 +38,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -0,0 +0,0 @@ public abstract class Projectile extends Entity { + this.shoot((double) f5, (double) f6, (double) f7, modifierZ, modifierXYZ); + Vec3 vec3d = user.getDeltaMovement(); + +- this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); ++ if (!user.level.paperConfig.disableRelativeProjectileVelocity) this.setDeltaMovement(this.getDeltaMovement().add(vec3d.x, user.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/patches/server/Configurable-spawn-chances-for-skeleton-horses.patch similarity index 55% rename from Spigot-Server-Patches/Configurable-spawn-chances-for-skeleton-horses.patch rename to patches/server/Configurable-spawn-chances-for-skeleton-horses.patch index 6e3e87a434..a6c494cff7 100644 --- a/Spigot-Server-Patches/Configurable-spawn-chances-for-skeleton-horses.patch +++ b/patches/server/Configurable-spawn-chances-for-skeleton-horses.patch @@ -21,16 +21,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } } -diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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)); +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + blockposition = this.findLightningTargetAround(this.getBlockRandomPos(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 + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); +- boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * 0.01D && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); ++ boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper if (flag1) { - EntityHorseSkeleton entityhorseskeleton = (EntityHorseSkeleton) EntityTypes.SKELETON_HORSE.a((World) this); + SkeletonHorse entityhorseskeleton = (SkeletonHorse) EntityType.SKELETON_HORSE.create((net.minecraft.world.level.Level) this); diff --git a/patches/server/Configurable-speed-for-water-flowing-over-lava.patch b/patches/server/Configurable-speed-for-water-flowing-over-lava.patch new file mode 100644 index 0000000000..27d6888dd5 --- /dev/null +++ b/patches/server/Configurable-speed-for-water-flowing-over-lava.patch @@ -0,0 +1,71 @@ +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/LiquidBlock.java b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty; + import net.minecraft.world.level.material.FlowingFluid; + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.material.FluidState; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.level.storage.loot.LootContext; + import net.minecraft.world.phys.shapes.CollisionContext; +@@ -0,0 +0,0 @@ public class LiquidBlock extends Block implements BucketPickup { + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (this.shouldSpreadLiquid(world, pos, state)) { +- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + } + + } + ++ // Paper start - Get flow speed. Throttle if its water and flowing adjacent to lava ++ public int getFlowSpeed(Level world, BlockPos 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.fluid.getTickDelay(world); ++ } ++ // Paper end ++ + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { + if (state.getFluidState().isSource() || neighborState.getFluidState().isSource()) { +@@ -0,0 +0,0 @@ public class LiquidBlock extends Block implements BucketPickup { + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (this.shouldSpreadLiquid(world, pos, state)) { +- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); ++ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + } + + } diff --git a/Spigot-Server-Patches/Configurable-sprint-interruption-on-attack.patch b/patches/server/Configurable-sprint-interruption-on-attack.patch similarity index 76% rename from Spigot-Server-Patches/Configurable-sprint-interruption-on-attack.patch rename to patches/server/Configurable-sprint-interruption-on-attack.patch index 3120f02ae9..630b7c9ed2 100644 --- a/Spigot-Server-Patches/Configurable-sprint-interruption-on-attack.patch +++ b/patches/server/Configurable-sprint-interruption-on-attack.patch @@ -19,17 +19,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.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 { +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { } - this.setMot(this.getMot().d(0.6D, 1.0D, 0.6D)); + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); - this.setSprinting(false); + // Paper start - Configuration option to disable automatic sprint interruption -+ if (!world.paperConfig.disableSprintInterruptionOnAttack) { ++ if (!level.paperConfig.disableSprintInterruptionOnAttack) { + this.setSprinting(false); + } + // Paper end diff --git a/patches/server/Configurable-top-of-nether-void-damage.patch b/patches/server/Configurable-top-of-nether-void-damage.patch new file mode 100644 index 0000000000..dc61a73a04 --- /dev/null +++ b/patches/server/Configurable-top-of-nether-void-damage.patch @@ -0,0 +1,47 @@ +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 Nameable, EntityAccess, CommandSource, n + } + + public void checkOutOfWorld() { +- if (this.getY() < (double) (this.level.getMinBuildHeight() - 64)) { ++ // Paper start - Configurable nether ceiling damage ++ if (this.getY() < (double) (this.level.getMinBuildHeight() - 64) || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER ++ && level.paperConfig.doNetherTopVoidDamage() ++ && this.getY() >= this.level.paperConfig.netherVoidTopDamageHeight)) { ++ // Paper end + this.outOfWorld(); + } + diff --git a/Spigot-Server-Patches/Convert-legacy-attributes-in-Item-Meta.patch b/patches/server/Convert-legacy-attributes-in-Item-Meta.patch similarity index 96% rename from Spigot-Server-Patches/Convert-legacy-attributes-in-Item-Meta.patch rename to patches/server/Convert-legacy-attributes-in-Item-Meta.patch index 759f24dd73..cfd5f83c56 100644 --- a/Spigot-Server-Patches/Convert-legacy-attributes-in-Item-Meta.patch +++ b/patches/server/Convert-legacy-attributes-in-Item-Meta.patch @@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; public class CraftAttributeMap implements Attributable { - private final AttributeMapBase handle; + private final AttributeMap 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(); + @@ -27,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end - public CraftAttributeMap(AttributeMapBase handle) { + public CraftAttributeMap(AttributeMap 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 diff --git a/Spigot-Server-Patches/Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/Create-HoverEvent-from-ItemStack-Entity.patch similarity index 95% rename from Spigot-Server-Patches/Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/server/Create-HoverEvent-from-ItemStack-Entity.patch index 2b896e95c9..bcf162d1b9 100644 --- a/Spigot-Server-Patches/Create-HoverEvent-from-ItemStack-Entity.patch +++ b/patches/server/Create-HoverEvent-from-ItemStack-Entity.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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; + return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId()) : null; } + + @Override diff --git a/Spigot-Server-Patches/Custom-replacement-for-eaten-items.patch b/patches/server/Custom-replacement-for-eaten-items.patch similarity index 61% rename from Spigot-Server-Patches/Custom-replacement-for-eaten-items.patch rename to patches/server/Custom-replacement-for-eaten-items.patch index add86c6525..8d3c4668b9 100644 --- a/Spigot-Server-Patches/Custom-replacement-for-eaten-items.patch +++ b/patches/server/Custom-replacement-for-eaten-items.patch @@ -4,25 +4,25 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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); +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.triggerItemUseEffects(this.useItem, 16); // CraftBukkit start - fire PlayerItemConsumeEvent ItemStack itemstack; + PlayerItemConsumeEvent event = null; // Paper - if (this instanceof EntityPlayer) { - org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.activeItem); + if (this instanceof ServerPlayer) { + org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); - PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); + event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); // Paper - world.getServer().getPluginManager().callEvent(event); + level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { } else { - itemstack = this.activeItem.a(this.world, this); + itemstack = this.useItem.finishUsingItem(this.level, this); } + + // Paper start - save the default replacement item and change it if necessary @@ -33,14 +33,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end // CraftBukkit end - if (itemstack != this.activeItem) { -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + if (itemstack != this.useItem) { +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { } - this.clearActiveItem(); + this.stopUsingItem(); + // 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(); ++ if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); + } + // Paper end } diff --git a/patches/server/Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/Dead-Player-s-shouldn-t-be-able-to-move.patch new file mode 100644 index 0000000000..7262dbb10c --- /dev/null +++ b/patches/server/Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -0,0 +1,21 @@ +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/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + + @Override + protected boolean isImmobile() { +- return super.isImmobile() || this.isSleeping(); ++ return super.isImmobile() || this.isSleeping() || this.isRemoved() || !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/patches/server/Default-loading-permissions.yml-before-plugins.patch similarity index 84% rename from Spigot-Server-Patches/Default-loading-permissions.yml-before-plugins.patch rename to patches/server/Default-loading-permissions.yml-before-plugins.patch index d10d717f03..d2c0188246 100644 --- a/Spigot-Server-Patches/Default-loading-permissions.yml-before-plugins.patch +++ b/patches/server/Default-loading-permissions.yml-before-plugins.patch @@ -34,19 +34,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 (!Main.useConsole) { + this.getLogger().info("Console input is disabled due to --noconsole command argument"); + if (com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper } - Plugin[] plugins = pluginManager.getPlugins(); + this.configuration = YamlConfiguration.loadConfiguration(this.getConfigFile()); @@ -0,0 +0,0 @@ public final class CraftServer implements Server { - commandMap.registerServerAliases(); + this.commandMap.registerServerAliases(); DefaultPermissions.registerCorePermissions(); CraftDefaultPermissions.registerCorePermissions(); -- loadCustomPermissions(); -+ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) loadCustomPermissions(); // Paper - helpMap.initializeCommands(); - syncCommands(); +- this.loadCustomPermissions(); ++ if (!com.destroystokyo.paper.PaperConfig.loadPermsBeforePlugins) this.loadCustomPermissions(); // Paper + this.helpMap.initializeCommands(); + this.syncCommands(); } diff --git a/Spigot-Server-Patches/Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server/Delay-Chunk-Unloads-based-on-Player-Movement.patch similarity index 64% rename from Spigot-Server-Patches/Delay-Chunk-Unloads-based-on-Player-Movement.patch rename to patches/server/Delay-Chunk-Unloads-based-on-Player-Movement.patch index 80a820eff0..b747b0199c 100644 --- a/Spigot-Server-Patches/Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ b/patches/server/Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -21,10 +21,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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")); @@ -33,30 +32,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + delayChunkUnloadsBy *= 20; + } + } - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkMapDistance.java b/src/main/java/net/minecraft/server/level/ChunkMapDistance.java ++ + public boolean altItemDespawnRateEnabled; + public java.util.Map altItemDespawnRateMap; + private void altItemDespawnRate() { +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.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 { +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -0,0 +0,0 @@ public abstract class DistanceManager { 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) { ++ long delayChunkUnloadsBy = chunkMap.level.paperConfig.delayChunkUnloadsBy; ++ if (ticket.getType() == TicketType.PLAYER && delayChunkUnloadsBy > 0) { + boolean hasPlayer = false; + for (Ticket ticket1 : arraysetsorted) { -+ if (ticket1.getTicketType() == TicketType.PLAYER) { ++ if (ticket1.getType() == TicketType.PLAYER) { + hasPlayer = true; + break; + } + } -+ PlayerChunk playerChunk = chunkMap.getUpdatingChunk(i); ++ ChunkHolder playerChunk = chunkMap.getUpdatingChunkIfPresent(i); + if (!hasPlayer && playerChunk != null && playerChunk.isFullChunkReady()) { + Ticket delayUnload = new Ticket(TicketType.DELAY_UNLOAD, 33, i); + delayUnload.delayUnloadBy = delayChunkUnloadsBy; -+ delayUnload.setCurrentTick(this.currentTick); ++ delayUnload.setCreatedTick(this.ticketTickCounter); + arraysetsorted.remove(delayUnload); + // refresh ticket + arraysetsorted.add(delayUnload); @@ -71,37 +73,37 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 + private final int ticketLevel; + public final T key; + public long createdTick; + 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 + protected Ticket(TicketType type, int level, T argument) { + this.type = type; + this.ticketLevel = level; + this.key = argument; ++ this.delayUnloadBy = type.timeout; // Paper } - public int compareTo(Ticket ticket) { + @Override @@ -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; + protected boolean timedOut(long currentTick) { +- long l = this.type.timeout(); ++ long l = delayUnloadBy; // Paper + return l != 0L && currentTick - this.createdTick > l; } + } 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 final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit ++ public static final TicketType DELAY_UNLOAD = create("delay_unload", Long::compareTo, 300); // Paper - public static TicketType a(String s, Comparator comparator) { - return new TicketType<>(s, comparator, 0L); + public static TicketType create(String name, Comparator argumentComparator) { + return new TicketType<>(name, argumentComparator, 0L); diff --git a/Spigot-Server-Patches/Disable-Explicit-Network-Manager-Flushing.patch b/patches/server/Disable-Explicit-Network-Manager-Flushing.patch similarity index 69% rename from Spigot-Server-Patches/Disable-Explicit-Network-Manager-Flushing.patch rename to patches/server/Disable-Explicit-Network-Manager-Flushing.patch index f5b7a8d008..8808ee0f9f 100644 --- a/Spigot-Server-Patches/Disable-Explicit-Network-Manager-Flushing.patch +++ b/patches/server/Disable-Explicit-Network-Manager-Flushing.patch @@ -11,19 +11,19 @@ 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 +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.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> { +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ public class Connection 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> { + public Connection(PacketFlow side) { +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { } if (this.channel != null) { @@ -31,4 +31,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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) { + if (this.tickCount++ % 20 == 0) { diff --git a/Spigot-Server-Patches/Disable-Scoreboards-for-non-players-by-default.patch b/patches/server/Disable-Scoreboards-for-non-players-by-default.patch similarity index 60% rename from Spigot-Server-Patches/Disable-Scoreboards-for-non-players-by-default.patch rename to patches/server/Disable-Scoreboards-for-non-players-by-default.patch index 6f972cc9b2..e09dcbbd0b 100644 --- a/Spigot-Server-Patches/Disable-Scoreboards-for-non-players-by-default.patch +++ b/patches/server/Disable-Scoreboards-for-non-players-by-default.patch @@ -28,23 +28,23 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @Nullable - public ScoreboardTeamBase getScoreboardTeam() { -+ if (!this.world.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof EntityHuman)) { return null; } // Paper - return this.world.getScoreboard().getPlayerTeam(this.getName()); + public Team getTeam() { ++ if (!this.level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper + return this.level.getScoreboard().getPlayersTeam(this.getScoreboardName()); } -diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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); +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + if (nbt.contains("Team", 8)) { + String s = nbt.getString("Team"); + PlayerTeam scoreboardteam = this.level.getScoreboard().getPlayerTeam(s); ++ if (!level.paperConfig.nonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { scoreboardteam = null; } // Paper + boolean flag = scoreboardteam != null && this.level.getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); if (!flag) { diff --git a/patches/server/Disable-explosion-knockback.patch b/patches/server/Disable-explosion-knockback.patch new file mode 100644 index 0000000000..e75dd9d174 --- /dev/null +++ b/patches/server/Disable-explosion-knockback.patch @@ -0,0 +1,69 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + } + ++ boolean knockbackCancelled = level.paperConfig.disableExplosionKnockback && source.isExplosion() && this instanceof net.minecraft.world.entity.player.Player; // Paper - Disable explosion knockback + if (flag1) { + if (flag) { + this.level.broadcastEntityEvent(this, (byte) 29); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + b0 = 2; + } + ++ if (!knockbackCancelled) // Paper - Disable explosion knockback + this.level.broadcastEntityEvent(this, b0); + } + +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + } + ++ if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback + if (this.isDeadOrDying()) { + if (!this.checkTotemDeathProtection(source)) { + SoundEvent soundeffect = this.getDeathSound(); +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 LivingEntity) { +- d14 = ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); ++ d14 = entity instanceof Player && level.paperConfig.disableExplosionKnockback ? 0 : ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d13); // Paper - Disable explosion knockback + } + + entity.setDeltaMovement(entity.getDeltaMovement().add(d8 * d14, d9 * d14, d10 * d14)); + if (entity instanceof Player) { + Player entityhuman = (Player) entity; + +- if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying)) { ++ if (!entityhuman.isSpectator() && (!entityhuman.isCreative() || !entityhuman.getAbilities().flying) && !level.paperConfig.disableExplosionKnockback) { // Paper - Disable explosion knockback + this.hitPlayers.put(entityhuman, new Vec3(d8 * d13, d9 * d13, d10 * d13)); + } + } diff --git a/Spigot-Server-Patches/Disable-ice-and-snow.patch b/patches/server/Disable-ice-and-snow.patch similarity index 63% rename from Spigot-Server-Patches/Disable-ice-and-snow.patch rename to patches/server/Disable-ice-and-snow.patch index 60ab67faa2..83306185e6 100644 --- a/Spigot-Server-Patches/Disable-ice-and-snow.patch +++ b/patches/server/Disable-ice-and-snow.patch @@ -18,16 +18,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 { +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } - gameprofilerfiller.exitEnter("iceandsnow"); + gameprofilerfiller.popPush("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); + blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15)); + BlockPos blockposition1 = blockposition.below(); + Biome biomebase = this.getBiome(blockposition); diff --git a/patches/server/Disable-spigot-tick-limiters.patch b/patches/server/Disable-spigot-tick-limiters.patch new file mode 100644 index 0000000000..3f12790ffb --- /dev/null +++ b/patches/server/Disable-spigot-tick-limiters.patch @@ -0,0 +1,21 @@ +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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Spigot start + // Iterator iterator = this.blockEntityTickers.iterator(); + int tilesThisCycle = 0; +- for (this.tileLimiter.initTick(); +- tilesThisCycle < this.blockEntityTickers.size() && (tilesThisCycle % 10 != 0 || this.tileLimiter.shouldContinue()); +- this.tileTickPosition++, tilesThisCycle++) { ++ for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters + this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0; + TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(tileTickPosition); + // Spigot start diff --git a/Spigot-Server-Patches/Disable-thunder.patch b/patches/server/Disable-thunder.patch similarity index 54% rename from Spigot-Server-Patches/Disable-thunder.patch rename to patches/server/Disable-thunder.patch index e68a19d729..53ff1c9aa0 100644 --- a/Spigot-Server-Patches/Disable-thunder.patch +++ b/patches/server/Disable-thunder.patch @@ -18,16 +18,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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; +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + gameprofilerfiller.push("thunder"); + BlockPos 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 (flag && this.isThundering() && this.random.nextInt(100000) == 0) { ++ if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder + blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15)); if (this.isRainingAt(blockposition)) { - DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); + DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); diff --git a/patches/server/Do-less-work-if-we-have-a-custom-Bukkit-generator.patch b/patches/server/Do-less-work-if-we-have-a-custom-Bukkit-generator.patch new file mode 100644 index 0000000000..58b532937e --- /dev/null +++ b/patches/server/Do-less-work-if-we-have-a-custom-Bukkit-generator.patch @@ -0,0 +1,42 @@ +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 ReentrantBlockableEventLoop { +- return biomebase.getMobSettings().playerSpawnFriendly(); +- }, random); +- ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); ++ // Paper start - moved down + // CraftBukkit start + if (world.generator != null) { + Random rand = new Random(world.getSeed()); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ return biomebase.getMobSettings().playerSpawnFriendly(); ++ }, random); ++ ChunkPos chunkcoordintpair = blockposition == null ? new ChunkPos(0, 0) : new ChunkPos(blockposition); ++ // Paper end + + if (blockposition == null) { + MinecraftServer.LOGGER.warn("Unable to find spawn biome"); diff --git a/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch new file mode 100644 index 0000000000..4123b6d1e3 --- /dev/null +++ b/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch @@ -0,0 +1,42 @@ +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/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + if (this.hivePos == null) { + return false; + } else { ++ if (!this.level.isLoadedAndInBounds(hivePos)) return false; // Paper + BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); + + return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby(); +@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + } + + private boolean doesHiveHaveSpace(BlockPos pos) { ++ if (!this.level.isLoadedAndInBounds(pos)) return false; // Paper + BlockEntity tileentity = this.level.getBlockEntity(pos); + + return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false; +@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + @Override + public boolean canBeeUse() { + if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) { ++ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return false; // Paper + BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); + + if (tileentity instanceof BeehiveBlockEntity) { +@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + + @Override + public void start() { ++ if (!Bee.this.level.isLoadedAndInBounds(Bee.this.hivePos)) return; // Paper + BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos); + + if (tileentity instanceof BeehiveBlockEntity) { diff --git a/Spigot-Server-Patches/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch b/patches/server/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch similarity index 57% rename from Spigot-Server-Patches/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch rename to patches/server/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch index c256938f1d..5ac05622bf 100644 --- a/Spigot-Server-Patches/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch +++ b/patches/server/Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch @@ -5,19 +5,19 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.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 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -0,0 +0,0 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa Bukkit.getPluginManager().callEvent(event); } if (!event.isCancelled()) { -- merchantrecipelist.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); +- recipeList.add(CraftMerchantRecipe.fromBukkit(event.getRecipe()).toMinecraft()); + // Paper start + final CraftMerchantRecipe craftMerchantRecipe = CraftMerchantRecipe.fromBukkit(event.getRecipe()); + if (craftMerchantRecipe.getIngredients().isEmpty()) return; -+ merchantrecipelist.add(craftMerchantRecipe.toMinecraft()); ++ recipeList.add(craftMerchantRecipe.toMinecraft()); + // Paper end } // CraftBukkit end diff --git a/patches/server/Do-not-let-armorstands-drown.patch b/patches/server/Do-not-let-armorstands-drown.patch new file mode 100644 index 0000000000..7d19c8843b --- /dev/null +++ b/patches/server/Do-not-let-armorstands-drown.patch @@ -0,0 +1,23 @@ +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/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + super.move(type, movement); + } + } ++ ++ // Paper start ++ @Override ++ public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization ++ return true; ++ } ++ // Paper end + // Paper end + } diff --git a/Spigot-Server-Patches/Do-not-let-the-server-load-chunks-from-newer-version.patch b/patches/server/Do-not-let-the-server-load-chunks-from-newer-version.patch similarity index 53% rename from Spigot-Server-Patches/Do-not-let-the-server-load-chunks-from-newer-version.patch rename to patches/server/Do-not-let-the-server-load-chunks-from-newer-version.patch index c6b153248f..c586b2fd77 100644 --- a/Spigot-Server-Patches/Do-not-let-the-server-load-chunks-from-newer-version.patch +++ b/patches/server/Do-not-let-the-server-load-chunks-from-newer-version.patch @@ -8,32 +8,33 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.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 { +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { + holder.tasks.forEach(Runnable::run); return holder.protoChunk; } - ++ + // Paper start -+ private static final int CURRENT_DATA_VERSION = SharedConstants.getGameVersion().getWorldVersion(); ++ private static final int CURRENT_DATA_VERSION = SharedConstants.getCurrentVersion().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<>(); + public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) { + java.util.ArrayDeque tasksToExecuteOnMain = new java.util.ArrayDeque<>(); // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + // Paper start - Do NOT attempt to load chunks saved with newer versions -+ if (nbttagcompound.hasKeyOfType("DataVersion", 99)) { -+ int dataVersion = nbttagcompound.getInt("DataVersion"); ++ if (nbt.contains("DataVersion", 99)) { ++ int dataVersion = nbt.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 + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); + CompoundTag nbttagcompound1 = nbt.getCompound("Level"); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate + ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate diff --git a/patches/server/Do-not-load-chunks-for-Pathfinding.patch b/patches/server/Do-not-load-chunks-for-Pathfinding.patch new file mode 100644 index 0000000000..40acfa111b --- /dev/null +++ b/patches/server/Do-not-load-chunks-for-Pathfinding.patch @@ -0,0 +1,42 @@ +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/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -0,0 +0,0 @@ public class WalkNodeEvaluator extends NodeEvaluator { + for(int n = -1; n <= 1; ++n) { + if (l != 0 || n != 0) { + pos.set(i + l, j + m, k + n); +- BlockState blockState = world.getBlockState(pos); ++ // Paper start ++ BlockState blockState = world.getTypeIfLoaded(pos); ++ if (blockState == null) { ++ return BlockPathTypes.BLOCKED; ++ } else { ++ // Paper end + if (blockState.is(Blocks.CACTUS)) { + return BlockPathTypes.DANGER_CACTUS; + } +@@ -0,0 +0,0 @@ public class WalkNodeEvaluator extends NodeEvaluator { + if (world.getFluidState(pos).is(FluidTags.WATER)) { + return BlockPathTypes.WATER_BORDER; + } ++ } // Paper + } + } + } +@@ -0,0 +0,0 @@ public class WalkNodeEvaluator extends NodeEvaluator { + } + + protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter world, BlockPos pos) { +- BlockState blockState = world.getBlockState(pos); ++ BlockState blockState = world.getTypeIfLoaded(pos); // Paper ++ if (blockState == null) return BlockPathTypes.BLOCKED; // Paper + Block block = blockState.getBlock(); + Material material = blockState.getMaterial(); + if (blockState.isAir()) { diff --git a/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch b/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch new file mode 100644 index 0000000000..49c3037f92 --- /dev/null +++ b/patches/server/Don-t-allow-digging-into-unloaded-chunks.patch @@ -0,0 +1,68 @@ +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/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + BlockState iblockdata; + + if (this.hasDelayedDestroy) { +- iblockdata = this.level.getBlockState(this.delayedDestroyPos); +- if (iblockdata.isAir()) { ++ iblockdata = this.level.getTypeIfLoaded(this.delayedDestroyPos); // Paper ++ if (iblockdata == null || iblockdata.isAir()) { // Paper + this.hasDelayedDestroy = false; + } else { + float f = this.incrementDestroyProgress(iblockdata, this.delayedDestroyPos, this.delayedTickStart); +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + } + } + } else if (this.isDestroyingBlock) { +- iblockdata = this.level.getBlockState(this.destroyPos); ++ // Paper start - don't want to do same logic as above, return instead ++ iblockdata = this.level.getTypeIfLoaded(this.destroyPos); ++ if (iblockdata == null) { ++ this.isDestroyingBlock = false; ++ return; ++ } ++ // Paper end + if (iblockdata.isAir()) { + this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); + this.lastSentState = -1; +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + this.player.connection.send(new ClientboundBlockBreakAckPacket(pos, this.level.getBlockState(pos), action, true, "stopped destroying")); + } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { + this.isDestroyingBlock = false; +- if (!Objects.equals(this.destroyPos, pos)) { ++ if (!Objects.equals(this.destroyPos, pos) && !BlockPos.ZERO.equals(this.destroyPos)) { + ServerPlayerGameMode.LOGGER.debug("Mismatch in destroy block pos: {} {}", this.destroyPos, pos); // CraftBukkit - SPIGOT-5457 sent by client when interact event cancelled +- this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); +- this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, this.level.getBlockState(this.destroyPos), action, true, "aborted mismatched destroying")); ++ BlockState type = this.level.getTypeIfLoaded(this.destroyPos); // Paper - don't load unloaded chunks for stale records here ++ if (type != null) this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); // Paper ++ if (type != null) this.player.connection.send(new ClientboundBlockBreakAckPacket(this.destroyPos, type, action, true, "aborted mismatched destroying")); // Paper ++ this.destroyPos = BlockPos.ZERO; // Paper + } + + this.level.destroyBlockProgress(this.player.getId(), pos, -1); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + case START_DESTROY_BLOCK: + case ABORT_DESTROY_BLOCK: + case STOP_DESTROY_BLOCK: ++ // Paper start - Don't allow digging in unloaded chunks ++ if (this.player.level.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { ++ return; ++ } ++ // Paper end - Don't allow digging in unloaded chunks + this.player.gameMode.handleBlockBreakAction(blockposition, packetplayinblockdig_enumplayerdigtype, packet.getDirection(), this.player.level.getMaxBuildHeight()); + return; + default: diff --git a/Spigot-Server-Patches/Don-t-allow-entities-to-ride-themselves-572.patch b/patches/server/Don-t-allow-entities-to-ride-themselves-572.patch similarity index 90% rename from Spigot-Server-Patches/Don-t-allow-entities-to-ride-themselves-572.patch rename to patches/server/Don-t-allow-entities-to-ride-themselves-572.patch index 932c57cd1c..71c5377469 100644 --- a/Spigot-Server-Patches/Don-t-allow-entities-to-ride-themselves-572.patch +++ b/patches/server/Don-t-allow-entities-to-ride-themselves-572.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } protected boolean addPassenger(Entity entity) { // CraftBukkit diff --git a/patches/server/Don-t-allow-null-UUID-s-for-chat.patch b/patches/server/Don-t-allow-null-UUID-s-for-chat.patch new file mode 100644 index 0000000000..227b8a9644 --- /dev/null +++ b/patches/server/Don-t-allow-null-UUID-s-for-chat.patch @@ -0,0 +1,19 @@ +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/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -0,0 +0,0 @@ public class ClientboundChatPacket implements Packet { + public ClientboundChatPacket(Component message, ChatType location, UUID sender) { + this.message = message; + this.type = location; +- this.sender = sender; ++ this.sender = sender != null ? sender : net.minecraft.Util.NIL_UUID; + } + + public ClientboundChatPacket(FriendlyByteBuf buf) { diff --git a/Spigot-Server-Patches/Don-t-call-getItemMeta-on-hasItemMeta.patch b/patches/server/Don-t-call-getItemMeta-on-hasItemMeta.patch similarity index 88% rename from Spigot-Server-Patches/Don-t-call-getItemMeta-on-hasItemMeta.patch rename to patches/server/Don-t-call-getItemMeta-on-hasItemMeta.patch index 79420ffc6a..9b5e953099 100644 --- a/Spigot-Server-Patches/Don-t-call-getItemMeta-on-hasItemMeta.patch +++ b/patches/server/Don-t-call-getItemMeta-on-hasItemMeta.patch @@ -18,8 +18,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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 +- return CraftItemStack.hasItemMeta(this.handle) && !CraftItemFactory.instance().equals(this.getItemMeta(), null); ++ return CraftItemStack.hasItemMeta(this.handle) && (this.handle.getDamageValue() != 0 || (this.handle.getTag() != null && this.handle.getTag().tags.size() >= (this.handle.getTag().contains(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/patches/server/Don-t-check-ConvertSigns-boolean-every-sign-save.patch b/patches/server/Don-t-check-ConvertSigns-boolean-every-sign-save.patch new file mode 100644 index 0000000000..c7658cee0c --- /dev/null +++ b/patches/server/Don-t-check-ConvertSigns-boolean-every-sign-save.patch @@ -0,0 +1,29 @@ +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/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -0,0 +0,0 @@ import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + + public class SignBlockEntity extends BlockEntity implements CommandSource { // CraftBukkit - implements ++ private static final boolean CONVERT_LEGACY_SIGNS = Boolean.getBoolean("convertLegacySigns"); // Paper + + public static final int LINES = 4; + private static final String[] RAW_TEXT_FIELD_NAMES = new String[]{"Text1", "Text2", "Text3", "Text4"}; +@@ -0,0 +0,0 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + } + + // CraftBukkit start +- if (Boolean.getBoolean("convertLegacySigns")) { ++ if (CONVERT_LEGACY_SIGNS) { // Paper + nbt.putBoolean("Bukkit.isConverted", true); + } + // CraftBukkit end diff --git a/Spigot-Server-Patches/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch similarity index 56% rename from Spigot-Server-Patches/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch rename to patches/server/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch index 322f2263d8..302fd9eaf2 100644 --- a/Spigot-Server-Patches/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ b/patches/server/Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch @@ -4,16 +4,16 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity 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); +- if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { ++ if (entity != null && entity != this.getVehicle() && !this.level.isClientSide && entity.valid) { // Paper - don't process on world gen + this.dismountVehicle(entity); } diff --git a/patches/server/Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch b/patches/server/Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch new file mode 100644 index 0000000000..c143fab0de --- /dev/null +++ b/patches/server/Don-t-crash-if-player-is-attempted-to-be-removed-fro.patch @@ -0,0 +1,23 @@ +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/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + ObjectSet objectset = (ObjectSet) this.playersPerChunk.get(i); + if (objectset == null) return; // CraftBukkit - SPIGOT-6208 + +- objectset.remove(player); +- if (objectset.isEmpty()) { ++ if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. ++ if (objectset == null || objectset.isEmpty()) { // Paper + this.playersPerChunk.remove(i); + this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); + this.playerTicketManager.update(i, Integer.MAX_VALUE, false); diff --git a/patches/server/Don-t-fire-BlockFade-on-worldgen-threads.patch b/patches/server/Don-t-fire-BlockFade-on-worldgen-threads.patch new file mode 100644 index 0000000000..15a2e801cf --- /dev/null +++ b/patches/server/Don-t-fire-BlockFade-on-worldgen-threads.patch @@ -0,0 +1,28 @@ +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/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -0,0 +0,0 @@ public class FireBlock extends BaseFireBlock { + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { + // CraftBukkit start ++ if (!(world instanceof ServerLevel)) return this.canSurvive(state, world, pos) ? (BlockState) this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)) : Blocks.AIR.defaultBlockState(); // Paper - don't fire events in world generation + if (!this.canSurvive(state, world, pos)) { + // Suppress during worldgen + if (!(world instanceof Level)) { +@@ -0,0 +0,0 @@ public class FireBlock extends BaseFireBlock { + return blockState.getHandle(); + } + } +- return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); ++ return this.getStateWithAge(world, pos, (Integer) state.getValue(FireBlock.AGE)); // Paper - diff on change, see "don't fire events in world generation" + // CraftBukkit end + } + diff --git a/patches/server/Don-t-ignore-result-of-PlayerEditBookEvent.patch b/patches/server/Don-t-ignore-result-of-PlayerEditBookEvent.patch new file mode 100644 index 0000000000..706116c0eb --- /dev/null +++ b/patches/server/Don-t-ignore-result-of-PlayerEditBookEvent.patch @@ -0,0 +1,19 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + + itemstack.addTagElement("pages", (Tag) nbttaglist); +- CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack); // CraftBukkit ++ this.player.containerMenu.setItem(slot, CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemstack)); // CraftBukkit // Paper - Don't ignore result (see other callsite for handleEditBookEvent) + } + + @Override diff --git a/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch b/patches/server/Don-t-let-fishinghooks-use-portals.patch similarity index 51% rename from Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch rename to patches/server/Don-t-let-fishinghooks-use-portals.patch index c03d023707..62553c4460 100644 --- a/Spigot-Server-Patches/Don-t-let-fishinghooks-use-portals.patch +++ b/patches/server/Don-t-let-fishinghooks-use-portals.patch @@ -4,17 +4,17 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.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 { +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -0,0 +0,0 @@ public class FishingHook extends Projectile { - this.setMot(this.getMot().a(0.92D)); - this.af(); + this.setDeltaMovement(this.getDeltaMovement().scale(0.92D)); + this.reapplyPosition(); + // Paper start - These shouldn't be going through portals -+ if (this.inPortal) { -+ this.die(); ++ if (this.isInsidePortal) { ++ this.discard(); + } + // Paper end } diff --git a/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch new file mode 100644 index 0000000000..208b0512cb --- /dev/null +++ b/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch @@ -0,0 +1,32 @@ +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/DoubleBlockCombiner.java b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java ++++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +@@ -0,0 +0,0 @@ public class DoubleBlockCombiner { + return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity); + } else { + BlockPos blockPos = pos.relative(function.apply(state)); +- BlockState blockState = world.getBlockState(blockPos); ++ // Paper start ++ BlockState blockState = world.getTypeIfLoaded(blockPos); ++ if (blockState == null) { ++ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity); ++ } ++ // Paper end + if (blockState.is(state.getBlock())) { + DoubleBlockCombiner.BlockType blockType2 = typeMapper.apply(blockState); + if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE && blockType != blockType2 && blockState.getValue(directionProperty) == state.getValue(directionProperty)) { diff --git a/patches/server/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/patches/server/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch new file mode 100644 index 0000000000..6646a83c5b --- /dev/null +++ b/patches/server/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch @@ -0,0 +1,19 @@ +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/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java ++++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java +@@ -0,0 +0,0 @@ public class GameProfileCache { + repository.findProfilesByNames(new String[]{name}, Agent.MINECRAFT, profilelookupcallback); + GameProfile gameprofile = (GameProfile) atomicreference.get(); + +- if (!GameProfileCache.usesAuthentication() && gameprofile == null) { ++ if (!GameProfileCache.usesAuthentication() && gameprofile == null && !org.apache.commons.lang3.StringUtils.isBlank(name)) { // Paper - Don't lookup a profile with a blank name + UUID uuid = Player.createPlayerUUID(new GameProfile((UUID) null, name)); + + gameprofile = new GameProfile(uuid, name); diff --git a/patches/server/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch b/patches/server/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch new file mode 100644 index 0000000000..a6f3949f00 --- /dev/null +++ b/patches/server/Don-t-mark-dirty-in-invalid-locations-SPIGOT-6086.patch @@ -0,0 +1,18 @@ +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/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + } + + public void blockChanged(BlockPos pos) { ++ if (!pos.isValidLocation(levelHeightAccessor)) return; // Paper - SPIGOT-6086 for all invalid locations; avoid acquiring locks + LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { diff --git a/patches/server/Don-t-move-existing-players-to-world-spawn.patch b/patches/server/Don-t-move-existing-players-to-world-spawn.patch new file mode 100644 index 0000000000..e128b64886 --- /dev/null +++ b/patches/server/Don-t-move-existing-players-to-world-spawn.patch @@ -0,0 +1,46 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.stats = server.getPlayerList().getStatisticManager(this); + this.advancements = server.getPlayerList().getPlayerAdvancements(this); + this.maxUpStep = 1.0F; +- this.fudgeSpawnLocation(world); ++ //this.c(worldserver); // Paper - don't move to spawn on login, only first join + + this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); + } + this.level = world; +- this.setPos(position.x(), position.y(), position.z()); ++ this.setPosRaw(position.x(), position.y(), position.z()); // Paper - don't register to chunks yet + } + this.gameMode.setLevel((ServerLevel) 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) player.fudgeSpawnLocation(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are.... ++ + player.setLevel(worldserver1); + String s1 = "local"; + diff --git a/patches/server/Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/patches/server/Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch new file mode 100644 index 0000000000..2a5e346340 --- /dev/null +++ b/patches/server/Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch @@ -0,0 +1,27 @@ +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/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -0,0 +0,0 @@ public class ClientboundChatPacket implements Packet { + // Paper end + // Spigot start + if (this.components != null) { +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components)); ++ // buf.writeUtf(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) { ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ } else { ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ } ++ // Paper end + } else { + buf.writeComponent(this.message); + } diff --git a/patches/server/Don-t-require-FACING-data.patch b/patches/server/Don-t-require-FACING-data.patch new file mode 100644 index 0000000000..f95cfd341e --- /dev/null +++ b/patches/server/Don-t-require-FACING-data.patch @@ -0,0 +1,35 @@ +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/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +@@ -0,0 +0,0 @@ import org.bukkit.event.block.BlockDispenseEvent; + // CraftBukkit end + + public class DefaultDispenseItemBehavior implements DispenseItemBehavior { ++ private Direction enumdirection; // Paper + + public DefaultDispenseItemBehavior() {} + + @Override + public final ItemStack dispense(BlockSource pointer, ItemStack stack) { ++ enumdirection = pointer.getBlockState().getValue(DispenserBlock.FACING); // Paper - cache facing direction + ItemStack itemstack1 = this.execute(pointer, stack); + + this.playSound(pointer); +- this.playAnimation(pointer, (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING)); ++ this.playAnimation(pointer, enumdirection); // Paper - cache facing direction + return itemstack1; + } + + protected ItemStack execute(BlockSource pointer, ItemStack stack) { +- Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING); ++ // Paper - cached enum direction + Position iposition = DispenserBlock.getDispensePosition(pointer); + ItemStack itemstack1 = stack.split(1); + diff --git a/patches/server/Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/Don-t-run-entity-collision-code-if-not-needed.patch new file mode 100644 index 0000000000..ac2b692c1a --- /dev/null +++ b/patches/server/Don-t-run-entity-collision-code-if-not-needed.patch @@ -0,0 +1,30 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + protected void serverAiStep() {} + + protected void pushEntities() { ++ // Paper start - don't run getEntities if we're not going to use its result ++ int i = this.level.getGameRules().getInt(GameRules.RULE_MAX_ENTITY_CRAMMING); ++ if (i <= 0 && level.paperConfig.maxCollisionsPerEntity <= 0) { ++ return; ++ } ++ // Paper end - don't run getEntities if we're not going to use its result + List list = this.level.getEntities(this, this.getBoundingBox(), EntitySelector.pushableBy(this)); + + if (!list.isEmpty()) { +- int i = this.level.getGameRules().getInt(GameRules.RULE_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/patches/server/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch similarity index 59% rename from Spigot-Server-Patches/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch rename to patches/server/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch index 240c806b19..8eec3bcfde 100644 --- a/Spigot-Server-Patches/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch +++ b/patches/server/Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch @@ -18,15 +18,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.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 { +--- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java ++++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java +@@ -0,0 +0,0 @@ public class ScoreboardSaveData extends SavedData { + ListTag listTag = new ListTag(); - 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()); + for(PlayerTeam playerTeam : this.scoreboard.getPlayerTeams()) { ++ if (!com.destroystokyo.paper.PaperConfig.saveEmptyScoreboardTeams && playerTeam.getPlayers().isEmpty()) continue; // Paper + CompoundTag compoundTag = new CompoundTag(); + compoundTag.putString("Name", playerTeam.getName()); + compoundTag.putString("DisplayName", Component.Serializer.toJson(playerTeam.getDisplayName())); diff --git a/Spigot-Server-Patches/Don-t-sleep-after-profile-lookups-if-not-needed.patch b/patches/server/Don-t-sleep-after-profile-lookups-if-not-needed.patch similarity index 100% rename from Spigot-Server-Patches/Don-t-sleep-after-profile-lookups-if-not-needed.patch rename to patches/server/Don-t-sleep-after-profile-lookups-if-not-needed.patch diff --git a/patches/server/Don-t-tick-dead-players.patch b/patches/server/Don-t-tick-dead-players.patch new file mode 100644 index 0000000000..75dae1c0ab --- /dev/null +++ b/patches/server/Don-t-tick-dead-players.patch @@ -0,0 +1,21 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + + public void doTick() { + try { +- if (!this.isSpectator() || !this.touchingUnloadedChunk()) { ++ if (valid && !this.isSpectator() || !this.touchingUnloadedChunk()) { // 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/patches/server/Drop-carried-item-when-player-has-disconnected.patch similarity index 60% rename from Spigot-Server-Patches/Drop-carried-item-when-player-has-disconnected.patch rename to patches/server/Drop-carried-item-when-player-has-disconnected.patch index c0a265425d..05eb06b90c 100644 --- a/Spigot-Server-Patches/Drop-carried-item-when-player-has-disconnected.patch +++ b/patches/server/Drop-carried-item-when-player-has-disconnected.patch @@ -10,26 +10,18 @@ diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/ma 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); ++ if (!entityplayer.containerMenu.getCarried().isEmpty()) { ++ net.minecraft.world.item.ItemStack carried = entityplayer.containerMenu.getCarried(); ++ entityplayer.containerMenu.setCarried(net.minecraft.world.item.ItemStack.EMPTY); + entityplayer.drop(carried, false); + } + // Paper end + - this.savePlayerFile(entityplayer); + this.save(entityplayer); if (entityplayer.isPassenger()) { Entity entity = entityplayer.getRootVehicle(); diff --git a/patches/server/Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server/Drop-falling-block-and-tnt-entities-at-the-specified.patch new file mode 100644 index 0000000000..927d2f5c6c --- /dev/null +++ b/patches/server/Drop-falling-block-and-tnt-entities-at-the-specified.patch @@ -0,0 +1,82 @@ +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/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity { + } + + this.move(MoverType.SELF, this.getDeltaMovement()); ++ ++ // Paper start - Configurable EntityFallingBlock height nerf ++ if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { ++ if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { ++ this.spawnAtLocation(block); ++ } ++ ++ this.discard(); ++ return; ++ } ++ // Paper end + if (!this.level.isClientSide) { + blockposition = this.blockPosition(); + boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -0,0 +0,0 @@ public class PrimedTnt extends Entity { + } + + this.move(MoverType.SELF, this.getDeltaMovement()); ++ // Paper start - Configurable TNT entity height nerf ++ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { ++ this.discard(); ++ return; ++ } ++ // Paper end + this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); + if (this.onGround) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.7D, -0.5D, 0.7D)); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartTNT.java +@@ -0,0 +0,0 @@ public class MinecartTNT extends AbstractMinecart { + public void tick() { + super.tick(); + if (this.fuse > 0) { ++ // Paper start - Configurable TNT entity height nerf ++ if (this.level.paperConfig.entityTNTHeightNerf != 0 && this.getY() > this.level.paperConfig.entityTNTHeightNerf) { ++ this.discard(); ++ return; ++ } ++ // Paper end + --this.fuse; + this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); + } else if (this.fuse == 0) { diff --git a/Spigot-Server-Patches/Duplicate-UUID-Resolve-Option.patch b/patches/server/Duplicate-UUID-Resolve-Option.patch similarity index 51% rename from Spigot-Server-Patches/Duplicate-UUID-Resolve-Option.patch rename to patches/server/Duplicate-UUID-Resolve-Option.patch index 935a07d801..da978470ce 100644 --- a/Spigot-Server-Patches/Duplicate-UUID-Resolve-Option.patch +++ b/patches/server/Duplicate-UUID-Resolve-Option.patch @@ -37,10 +37,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 + } @@ -79,11 +78,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + break; + } + } - } -diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java ++ + public boolean countAllMobsForSpawning = false; + private void countAllMobsForSpawning() { + countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -0,0 +0,0 @@ package net.minecraft.server.level; @@ -92,12 +94,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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; +@@ -0,0 +0,0 @@ import java.io.File; import java.io.IOException; import java.io.Writer; + import java.util.BitSet; +import java.util.HashMap; // Paper - import java.util.Collection; ++import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; // Paper @@ -109,141 +111,118 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 { + import java.util.concurrent.CompletionStage; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + entity.discard(); + needsRemoval = true; + } ++ checkDupeUUID(worldserver, entity); // Paper + return !needsRemoval; + })); + // CraftBukkit end +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }); } + // Paper start -+ private void checkDupeUUID(Entity entity) { -+ PaperWorldConfig.DuplicateUUIDMode mode = world.paperConfig.duplicateUUIDMode; ++ private static void checkDupeUUID(ServerLevel level, Entity entity) { ++ PaperWorldConfig.DuplicateUUIDMode mode = level.paperConfig.duplicateUUIDMode; + if (mode != PaperWorldConfig.DuplicateUUIDMode.WARN + && mode != PaperWorldConfig.DuplicateUUIDMode.DELETE + && mode != PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN) { + return; + } -+ Entity other = world.getEntity(entity.getUniqueID()); ++ Entity other = level.getEntity(entity.getUUID()); + -+ 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 (mode == PaperWorldConfig.DuplicateUUIDMode.SAFE_REGEN && other != null && !other.isRemoved() ++ && Objects.equals(other.getEncodeId(), entity.getEncodeId()) ++ && entity.getBukkitEntity().getLocation().distance(other.getBukkitEntity().getLocation()) < level.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; ++ if (Level.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.discard(); + return; + } -+ if (other != null && !other.dead) { ++ if (other != null && !other.isRemoved()) { + 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."); ++ if (Level.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; ++ if (Level.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.discard(); + 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."); ++ if (Level.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 + public CompletableFuture> prepareTickingChunk(ChunkHolder holder) { + ChunkPos chunkcoordintpair = holder.getPos(); + CompletableFuture, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkRangeFuture(chunkcoordintpair, 1, (i) -> { +diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.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 { +--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java ++++ b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A + + private boolean addEntityUuid(T entity) { + if (!this.knownUuids.add(entity.getUUID())) { + // Paper start -+ if (entity1.dead) { -+ unregisterEntity(entity1); // remove the existing entity ++ if (((Entity) entity).isRemoved()) { ++ stopTracking(entity); // 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 + LOGGER.warn("UUID of added entity already exists: {}", (Object)entity); + // Paper start -+ if (DEBUG_ENTITIES && entity.world.paperConfig.duplicateUUIDMode != PaperWorldConfig.DuplicateUUIDMode.NOTHING) { -+ if (entity1.addedToWorldStack != null) { -+ entity1.addedToWorldStack.printStackTrace(); ++ if (net.minecraft.world.level.Level.DEBUG_ENTITIES && ((Entity) entity).level.paperConfig.duplicateUUIDMode != com.destroystokyo.paper.PaperWorldConfig.DuplicateUUIDMode.NOTHING) { ++ if (((Entity) entity).addedToWorldStack != null) { ++ ((Entity) entity).addedToWorldStack.printStackTrace(); + } -+ -+ getAddToWorldStackTrace(entity).printStackTrace(); ++ net.minecraft.server.level.ServerLevel.getAddToWorldStackTrace((net.minecraft.world.entity.Entity) entity).printStackTrace(); + } + // Paper end + return false; + } else { return true; - } +@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A } -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 void processUnloads() { +- this.chunksToUnload.removeIf((pos) -> { ++ this.chunksToUnload.removeIf((java.util.function.LongPredicate) (pos) -> { // Paper - decompile fix + return this.chunkVisibility.get(pos) != Visibility.HIDDEN ? true : this.processChunkUnload(pos); }); } +@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A + } -+ 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 - } + public void autoSave() { +- this.getAllChunksToSave().forEach((pos) -> { ++ this.getAllChunksToSave().forEach((java.util.function.LongConsumer) (pos) -> { // Paper - decompile fix + boolean bl = this.chunkVisibility.get(pos) == Visibility.HIDDEN; + if (bl) { + this.processChunkUnload(pos); +@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A + while(!longSet.isEmpty()) { + this.permanentStorage.flush(); + this.processPendingLoads(); +- longSet.removeIf((pos) -> { ++ longSet.removeIf((java.util.function.LongPredicate) (pos) -> { // Paper - decompile fix + boolean bl = this.chunkVisibility.get(pos) == Visibility.HIDDEN; + return bl ? this.processChunkUnload(pos) : this.storeChunkSections(pos, (entityAccess) -> { + }); +@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A - int k = MathHelper.floor(entity.locY() / 16.0D); + public void dumpSections(Writer writer) throws IOException { + CsvOutput csvOutput = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("visibility").addColumn("load_status").addColumn("entity_count").build(writer); +- this.sectionStorage.getAllChunksWithExistingSections().forEach((chunkPos) -> { ++ this.sectionStorage.getAllChunksWithExistingSections().forEach((java.util.function.LongConsumer) (chunkPos) -> { // Paper - decompile fix + PersistentEntitySectionManager.ChunkLoadStatus chunkLoadStatus = this.chunkLoadStatuses.get(chunkPos); + this.sectionStorage.getExistingSectionPositionsInChunk(chunkPos).forEach((sectionPos) -> { + EntitySection entitySection = this.sectionStorage.getSection(sectionPos); diff --git a/Spigot-Server-Patches/Empty-commands-shall-not-be-dispatched.patch b/patches/server/Empty-commands-shall-not-be-dispatched.patch similarity index 65% rename from Spigot-Server-Patches/Empty-commands-shall-not-be-dispatched.patch rename to patches/server/Empty-commands-shall-not-be-dispatched.patch index 6d12505db1..d3d5e7f080 100644 --- a/Spigot-Server-Patches/Empty-commands-shall-not-be-dispatched.patch +++ b/patches/server/Empty-commands-shall-not-be-dispatched.patch @@ -4,11 +4,11 @@ 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 +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.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 { +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -0,0 +0,0 @@ public class Commands { command = event.getCommand(); String[] args = command.split(" "); diff --git a/patches/server/EnderDragon-Events.patch b/patches/server/EnderDragon-Events.patch new file mode 100644 index 0000000000..663e89c73e --- /dev/null +++ b/patches/server/EnderDragon-Events.patch @@ -0,0 +1,53 @@ +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/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java +@@ -0,0 +0,0 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase { + this.flame.setDuration(200); + this.flame.setParticle(ParticleTypes.DRAGON_BREATH); + this.flame.addEffect(new MobEffectInstance(MobEffects.HARM)); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper + this.dragon.level.addFreshEntity(this.flame); ++ // Paper start ++ } else { ++ this.end(); ++ } ++ // Paper end + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java +@@ -0,0 +0,0 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance { + + DragonFireball dragonFireball = new DragonFireball(this.dragon.level, this.dragon, r, s, t); + dragonFireball.moveTo(o, p, q, 0.0F, 0.0F); ++ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) dragonFireball.getBukkitEntity()).callEvent()) // Paper + this.dragon.level.addFreshEntity(dragonFireball); ++ else dragonFireball.discard(); // Paper + this.fireballCharge = 0; + if (this.currentPath != null) { + while(!this.currentPath.isDone()) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java +@@ -0,0 +0,0 @@ public class DragonFireball extends AbstractHurtingProjectile { + } + } + ++ if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) areaEffectCloud.getBukkitEntity()).callEvent()) { // Paper + this.level.levelEvent(2006, this.blockPosition(), this.isSilent() ? -1 : 1); + this.level.addFreshEntity(areaEffectCloud); ++ } else areaEffectCloud.discard(); // Paper + this.discard(); + } + diff --git a/Spigot-Server-Patches/Enderman.teleportRandomly.patch b/patches/server/Enderman.teleportRandomly.patch similarity index 59% rename from Spigot-Server-Patches/Enderman.teleportRandomly.patch rename to patches/server/Enderman.teleportRandomly.patch index a23005b1f7..f93e16b993 100644 --- a/Spigot-Server-Patches/Enderman.teleportRandomly.patch +++ b/patches/server/Enderman.teleportRandomly.patch @@ -5,18 +5,19 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.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(); +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + super.customServerAiStep(); } -+ 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; +- protected boolean teleport() { ++ public boolean teleport() { // Paper - protected->public + if (!this.level.isClientSide() && this.isAlive()) { + double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; + double d1 = this.getY() + (double) (this.random.nextInt(64) - 32); 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 @@ -25,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 super(server, entity); } -+ @Override public boolean teleportRandomly() { return getHandle().teleportRandomly(); } // Paper ++ @Override public boolean teleportRandomly() { return getHandle().teleport(); } // Paper @Override public MaterialData getCarriedMaterial() { - IBlockData blockData = getHandle().getCarried(); + BlockState blockData = this.getHandle().getCarriedBlock(); diff --git a/patches/server/EndermanAttackPlayerEvent.patch b/patches/server/EndermanAttackPlayerEvent.patch new file mode 100644 index 0000000000..c2d177ebfa --- /dev/null +++ b/patches/server/EndermanAttackPlayerEvent.patch @@ -0,0 +1,30 @@ +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/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + this.readPersistentAngerSaveData(this.level, nbt); + } + +- boolean isLookingAtMe(Player player) { ++ // Paper start - EndermanAttackPlayerEvent ++ private boolean isLookingAtMe(Player player) { ++ boolean shouldAttack = isLookingAtMe_check(player); ++ com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent event = new com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent((org.bukkit.entity.Enderman) getBukkitEntity(), (org.bukkit.entity.Player) player.getBukkitEntity()); ++ event.setCancelled(!shouldAttack); ++ return event.callEvent(); ++ } ++ private boolean isLookingAtMe_check(Player player) { ++ // Paper end + ItemStack itemstack = (ItemStack) player.getInventory().armor.get(3); + + if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) { diff --git a/patches/server/EndermanEscapeEvent.patch b/patches/server/EndermanEscapeEvent.patch new file mode 100644 index 0000000000..e9c788650e --- /dev/null +++ b/patches/server/EndermanEscapeEvent.patch @@ -0,0 +1,65 @@ +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/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + this.setGoalTarget(target, org.bukkit.event.entity.EntityTargetEvent.TargetReason.UNKNOWN, true); + } + ++ // Paper start ++ private boolean tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason reason) { ++ return new com.destroystokyo.paper.event.entity.EndermanEscapeEvent((org.bukkit.craftbukkit.entity.CraftEnderman) this.getBukkitEntity(), reason).callEvent(); ++ } ++ // Paper end ++ + @Override + public boolean setGoalTarget(LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { + if (!super.setGoalTarget(entityliving, reason, fireEvent)) { +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { + float f = this.getBrightness(); + +- if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { ++ if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper + this.setTarget((LivingEntity) null); + this.teleport(); + } +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + if (this.isInvulnerableTo(source)) { + return false; + } else if (source instanceof IndirectEntityDamageSource) { ++ if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start + for (int i = 0; i < 64; ++i) { + if (this.teleport()) { + return true; + } + } ++ } // Paper end + + return false; + } else { + boolean flag = super.hurt(source, amount); + +- if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { ++ if (!this.level.isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0 && this.tryEscape(source == DamageSource.DROWN ? com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.DROWN : com.destroystokyo.paper.event.entity.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.teleport(); + } + +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + } else { + if (this.target != null && !this.enderman.isPassenger()) { + if (this.enderman.isLookingAtMe((Player) this.target)) { +- if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) { ++ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D && this.enderman.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.STARE)) { // Paper + this.enderman.teleport(); + } + diff --git a/Spigot-Server-Patches/Enforce-Sync-Player-Saves.patch b/patches/server/Enforce-Sync-Player-Saves.patch similarity index 77% rename from Spigot-Server-Patches/Enforce-Sync-Player-Saves.patch rename to patches/server/Enforce-Sync-Player-Saves.patch index e17331a33e..ce18c830ee 100644 --- a/Spigot-Server-Patches/Enforce-Sync-Player-Saves.patch +++ b/patches/server/Enforce-Sync-Player-Saves.patch @@ -13,14 +13,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class PlayerList { } - public void savePlayers() { -+ MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + public void saveAll() { ++ net.minecraft.server.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)); +- this.save((ServerPlayer) this.players.get(i)); ++ this.save(this.players.get(i)); } MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main } - public WhiteList getWhitelist() { + public UserWhiteList getWhiteList() { diff --git a/Spigot-Server-Patches/Enhance-console-tab-completions-for-brigadier-comman.patch b/patches/server/Enhance-console-tab-completions-for-brigadier-comman.patch similarity index 75% rename from Spigot-Server-Patches/Enhance-console-tab-completions-for-brigadier-comman.patch rename to patches/server/Enhance-console-tab-completions-for-brigadier-comman.patch index 80071ff2d5..4376fdf3c8 100644 --- a/Spigot-Server-Patches/Enhance-console-tab-completions-for-brigadier-comman.patch +++ b/patches/server/Enhance-console-tab-completions-for-brigadier-comman.patch @@ -24,14 +24,6 @@ diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/s 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 @@ -43,8 +35,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 .completer(new ConsoleCommandCompleter(this.server)) - ); + .option(LineReader.Option.COMPLETE_IN_WORD, true); -+ if (PaperConfig.enableBrigadierConsoleHighlighting) { -+ builder.highlighter(new BrigadierCommandHighlighter(this.server, this.server.getServerCommandListener())); ++ if (com.destroystokyo.paper.PaperConfig.enableBrigadierConsoleHighlighting) { ++ builder.highlighter(new io.papermc.paper.console.BrigadierCommandHighlighter(this.server, this.server.createCommandSourceStack())); + } + return super.buildReader(builder); } @@ -64,8 +56,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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.commands.CommandSourceStack; ++import net.minecraft.network.chat.ComponentUtils; +import net.minecraft.server.dedicated.DedicatedServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jline.reader.Candidate; @@ -79,10 +71,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import static com.destroystokyo.paper.event.server.AsyncTabCompleteEvent.Completion.completion; + +public final class BrigadierCommandCompleter { -+ private final CommandListenerWrapper commandSourceStack; ++ private final CommandSourceStack commandSourceStack; + private final DedicatedServer server; + -+ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { ++ public BrigadierCommandCompleter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { + this.server = server; + this.commandSourceStack = commandSourceStack; + } @@ -92,8 +84,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.addCandidates(candidates, Collections.emptyList(), existing); + return; + } -+ final CommandDispatcher dispatcher = this.server.getCommandDispatcher().dispatcher(); -+ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); ++ final CommandDispatcher dispatcher = this.server.getCommands().getDispatcher(); ++ final ParseResults results = dispatcher.parse(prepareStringReader(line.line()), this.commandSourceStack); + this.addCandidates( + candidates, + dispatcher.getCompletionSuggestions(results, line.cursor()).join().getList(), @@ -140,7 +132,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (suggestion.getTooltip() == null) { + return completion(suggestion.getText()); + } -+ return completion(suggestion.getText(), PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(suggestion.getTooltip()))); ++ return completion(suggestion.getText(), PaperAdventure.asAdventure(ComponentUtils.fromMessage(suggestion.getTooltip()))); + } + + static @NonNull StringReader prepareStringReader(final @NonNull String line) { @@ -162,7 +154,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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.commands.CommandSourceStack; +import net.minecraft.server.dedicated.DedicatedServer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.jline.reader.Highlighter; @@ -173,10 +165,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +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 CommandSourceStack commandSourceStack; + private final DedicatedServer server; + -+ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandListenerWrapper commandSourceStack) { ++ public BrigadierCommandHighlighter(final @NonNull DedicatedServer server, final @NonNull CommandSourceStack commandSourceStack) { + this.server = server; + this.commandSourceStack = commandSourceStack; + } @@ -184,14 +176,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @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); ++ final ParseResults results = this.server.getCommands().getDispatcher().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()) { ++ for (final ParsedCommandNode node : results.getContext().getLastChild().getNodes()) { + if (node.getRange().getStart() >= buffer.length()) { + break; + } @@ -214,41 +206,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 @@ -261,7 +218,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public ConsoleCommandCompleter(DedicatedServer server) { // Paper - CraftServer -> DedicatedServer this.server = server; -+ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.getServerCommandListener()); // Paper ++ this.brigadierCompleter = new io.papermc.paper.console.BrigadierCommandCompleter(this.server, this.server.createCommandSourceStack()); // Paper } // Paper start - Change method signature for JLine update diff --git a/patches/server/Ensure-Entity-AABB-s-are-never-invalid.patch b/patches/server/Ensure-Entity-AABB-s-are-never-invalid.patch new file mode 100644 index 0000000000..97eb5627be --- /dev/null +++ b/patches/server/Ensure-Entity-AABB-s-are-never-invalid.patch @@ -0,0 +1,32 @@ +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 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + + public void setPos(double x, double y, double z) { + this.setPosRaw(x, y, z); +- this.setBoundingBox(this.makeBoundingBox()); ++ // this.setBoundingBox(this.makeBoundingBox()); // Paper - move into setPositionRaw + } + + protected AABB makeBoundingBox() { +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + + public final void setPosRaw(double x, double y, double z) { ++ // Paper start - never allow AABB to become desynced from position ++ // hanging has its own special logic ++ if (!(this instanceof net.minecraft.world.entity.decoration.HangingEntity) && (this.position.x != x || this.position.y != y || this.position.z != z)) { ++ this.setBoundingBox(this.dimensions.makeBoundingBox(x, y, z)); ++ } ++ // Paper end + if (this.position.x != x || this.position.y != y || this.position.z != z) { + this.position = new Vec3(x, y, z); + int i = Mth.floor(x); diff --git a/patches/server/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch new file mode 100644 index 0000000000..a7b87e482c --- /dev/null +++ b/patches/server/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch @@ -0,0 +1,19 @@ +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/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/raid/Raider.java ++++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java +@@ -0,0 +0,0 @@ public abstract class Raider extends PatrollingMonster { + + @Override + public boolean canUse() { ++ if (!this.mob.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items + Raid raid = this.mob.getCurrentRaid(); + + if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) { diff --git a/Spigot-Server-Patches/Ensure-commands-are-not-ran-async.patch b/patches/server/Ensure-commands-are-not-ran-async.patch similarity index 90% rename from Spigot-Server-Patches/Ensure-commands-are-not-ran-async.patch rename to patches/server/Ensure-commands-are-not-ran-async.patch index 3c2d0809c3..6eda570629 100644 --- a/Spigot-Server-Patches/Ensure-commands-are-not-ran-async.patch +++ b/patches/server/Ensure-commands-are-not-ran-async.patch @@ -13,11 +13,11 @@ This change will synchronize the command execution back to the main thread, caus 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } if (!async && s.startsWith("/")) { @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + }; -+ minecraftServer.processQueue.add(wait); ++ server.processQueue.add(wait); + try { + wait.get(); + return; @@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper End this.handleCommand(s); - } else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) { + } else if (this.player.getChatVisibility() == ChatVisiblity.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 @@ -77,8 +77,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + // Paper End -+ - if (commandMap.dispatch(sender, commandLine)) { + if (this.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 @@ -90,7 +89,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 try { org.spigotmc.AsyncCatcher.enabled = false; // Spigot + org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper - server.close(); + this.server.close(); } finally { try { diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java diff --git a/patches/server/Ensure-inv-drag-is-in-bounds.patch b/patches/server/Ensure-inv-drag-is-in-bounds.patch new file mode 100644 index 0000000000..350426330f --- /dev/null +++ b/patches/server/Ensure-inv-drag-is-in-bounds.patch @@ -0,0 +1,19 @@ +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/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -0,0 +0,0 @@ public abstract class AbstractContainerMenu { + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { +- slot = (Slot) this.slots.get(slotIndex); ++ slot = slotIndex < this.slots.size() ? this.slots.get(slotIndex) : null; // Paper - Ensure drag in bounds + itemstack = this.getCarried(); + if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { + this.quickcraftSlots.add(slot); diff --git a/patches/server/Ensure-safe-gateway-teleport.patch b/patches/server/Ensure-safe-gateway-teleport.patch new file mode 100644 index 0000000000..ed45257899 --- /dev/null +++ b/patches/server/Ensure-safe-gateway-teleport.patch @@ -0,0 +1,26 @@ +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/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -0,0 +0,0 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + List list = world.getEntitiesOfClass(Entity.class, new AABB(pos), TheEndGatewayBlockEntity::canEntityTeleport); + + if (!list.isEmpty()) { +- TheEndGatewayBlockEntity.teleportEntity(world, pos, state, (Entity) list.get(world.random.nextInt(list.size())), blockEntity); ++ // Paper start ++ for (Entity entity : list) { ++ if (entity.canChangeDimensions()) { ++ TheEndGatewayBlockEntity.teleportEntity(world, pos, state, entity, blockEntity); ++ break; ++ } ++ } ++ // Paper end + } + + if (blockEntity.age % 2400L == 0L) { diff --git a/patches/server/Entity-Activation-Range-2.0.patch b/patches/server/Entity-Activation-Range-2.0.patch new file mode 100644 index 0000000000..a1d98102c6 --- /dev/null +++ b/patches/server/Entity-Activation-Range-2.0.patch @@ -0,0 +1,743 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ package net.minecraft.server.level; + + import com.google.common.annotations.VisibleForTesting; + import co.aikar.timings.TimingHistory; // Paper +-import co.aikar.timings.Timings; // Paper + import com.google.common.collect.Lists; + import com.mojang.datafixers.DataFixer; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +-import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.LevelChunkSection; + import net.minecraft.world.level.chunk.storage.EntityStorage; + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.dimension.end.EndDragonFight; +-import net.minecraft.world.level.entity.EntityAccess; + import net.minecraft.world.level.entity.EntityPersistentStorage; + import net.minecraft.world.level.entity.EntityTickList; + import net.minecraft.world.level.entity.EntityTypeTest; +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + ++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.tickCount++; + timer = entity.getType().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.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); ++ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper + try { + // Paper end - timings + entity.setOldPosAndRot(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); ++ if (isActive) { // Paper - EAR 2 ++ TimingHistory.activatedEntityTicks++; + entity.tick(); + entity.postTick(); // CraftBukkit ++ } else { entity.inactiveTick(); } // Paper - EAR 2 + this.getProfiler().pop(); ++ } finally { timer.stopTiming(); } // Paper - timings + Iterator iterator = entity.getPassengers().iterator(); + + while (iterator.hasNext()) { +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(entity, entity1); + } + +- } finally { timer.stopTiming(); } // Paper - timings ++ // } finally { timer.stopTiming(); } // Paper - timings - move up + + } + + private void tickPassenger(Entity vehicle, Entity passenger) { + if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { + if (passenger instanceof Player || this.entityTickList.contains(passenger)) { ++ // Paper - EAR 2 ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); ++ co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper ++ try { ++ // Paper end + passenger.setOldPosAndRot(); + ++passenger.tickCount; + ProfilerFiller gameprofilerfiller = this.getProfiler(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickPassenger"); ++ // Paper start - EAR 2 ++ if (isActive) { + passenger.rideTick(); + passenger.postTick(); // CraftBukkit ++ } else { ++ passenger.setDeltaMovement(Vec3.ZERO); ++ passenger.inactiveTick(); ++ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary ++ vehicle.positionRider(passenger); ++ } ++ // Paper end - EAR 2 + gameprofilerfiller.pop(); + Iterator iterator = passenger.getPassengers().iterator(); + +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(passenger, entity2); + } + ++ } finally { timer.stopTiming(); }// Paper - EAR2 timings + } + } else { + passenger.stopRiding(); +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 Nameable, EntityAccess, CommandSource, n + 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 Nameable, EntityAccess, CommandSource, n + } else { + this.wasOnFire = this.isOnFire(); + if (movementType == MoverType.PISTON) { ++ this.activatedTick = MinecraftServer.currentTick + 20; // Paper + movement = this.limitPistonMovement(movement); + if (movement.equals(Vec3.ZERO)) { + return; +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.stuckSpeedMultiplier = Vec3.ZERO; + this.setDeltaMovement(Vec3.ZERO); + } ++ // Paper start - ignore movement changes while inactive. ++ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) && movement == getDeltaMovement() && movementType == MoverType.SELF) { ++ setDeltaMovement(Vec3.ZERO); ++ this.level.getProfiler().pop(); ++ return; ++ } ++ // Paper end + + movement = this.maybeBackOffFromEdge(movement, movementType); + Vec3 vec3d1 = this.collide(movement); +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + return this.lookControl; + } + ++ // Paper start ++ @Override ++ public void inactiveTick() { ++ super.inactiveTick(); ++ if (this.goalSelector.inactiveTick()) { ++ this.goalSelector.tick(); ++ } ++ if (this.targetSelector.inactiveTick()) { ++ this.targetSelector.tick(); ++ } ++ } ++ // Paper end ++ + public MoveControl getMoveControl() { + if (this.isPassenger() && this.getVehicle() instanceof Mob) { + Mob entityinsentient = (Mob) this.getVehicle(); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityUnleashEvent; + public abstract class PathfinderMob extends Mob { + + public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ public BlockPos movingTarget = null; public BlockPos getMovingTarget() { return movingTarget; } // Paper + + protected PathfinderMob(EntityType type, Level world) { + super(type, world); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -0,0 +0,0 @@ public class GoalSelector { + private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); + private int tickCount; + private int newGoalRate = 3; ++ private int curRate; + + public GoalSelector(Supplier profiler) { + this.profiler = profiler; +@@ -0,0 +0,0 @@ public class GoalSelector { + this.availableGoals.clear(); + } + ++ // Paper start ++ public boolean inactiveTick() { ++ this.curRate++; ++ return this.curRate % this.newGoalRate == 0; ++ } ++ public boolean hasTasks() { ++ for (WrappedGoal task : this.availableGoals) { ++ if (task.isRunning()) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + public void removeGoal(Goal goal) { + this.availableGoals.stream().filter((wrappedGoal) -> { + return wrappedGoal.getGoal() == goal; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal { + protected int nextStartTick; + protected int tryTicks; + private int maxStayTicks; +- protected BlockPos blockPos = BlockPos.ZERO; @Deprecated public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER ++ protected BlockPos blockPos = BlockPos.ZERO; @Deprecated public final BlockPos getTargetPosition() { return this.blockPos; } @Deprecated public void setTargetPosition(BlockPos pos) { this.blockPos = pos; mob.movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER + private boolean reachedTarget; + private final int searchRange; + private final int verticalSearchRange; +@@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal { + public MoveToBlockGoal(PathfinderMob mob, double speed, int range) { + this(mob, speed, range, 1); + } ++ // Paper start - activation range improvements ++ @Override ++ public void stop() { ++ super.stop(); ++ setTargetPosition(BlockPos.ZERO); ++ } ++ // Paper end + + public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) { + this.mob = mob; +@@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal { + mutableBlockPos.setWithOffset(blockPos, m, k - 1, n); + if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level, mutableBlockPos)) { + this.blockPos = mutableBlockPos; ++ setTargetPosition(mutableBlockPos.immutable()); // Paper + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void inactiveTick() { + // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( +- if (level.spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { +- this.customServerAiStep(); ++ // Paper start ++ if (this.getUnhappyCounter() > 0) { ++ this.setUnhappyCounter(this.getUnhappyCounter() - 1); ++ } ++ if (this.isEffectiveAi()) { ++ if (level.spigotConfig.tickInactiveVillagers) { ++ this.customServerAiStep(); ++ } else { ++ this.mobTick(true); ++ } + } ++ maybeDecayGossip(); ++ // Paper end ++ + super.inactiveTick(); + } + // Spigot End + + @Override +- protected void customServerAiStep() { ++ protected void customServerAiStep() { mobTick(false); } ++ protected void mobTick(boolean inactive) { + this.level.getProfiler().push("villagerBrain"); +- this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error ++ if (!inactive) this.getBrain().tick((ServerLevel) this.level, this); // CraftBukkit - decompile error // Paper + this.level.getProfiler().pop(); + if (this.assignProfessionWhenSpawned) { + this.assignProfessionWhenSpawned = false; +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.lastTradedPlayer = null; + } + +- if (!this.isNoAi() && this.random.nextInt(100) == 0) { ++ if (!inactive && !this.isNoAi() && this.random.nextInt(100) == 0) { // Paper + Raid raid = ((ServerLevel) this.level).getRaidAt(this.blockPosition()); + + if (raid != null && raid.isActive() && !raid.isOver()) { +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.isTrading()) { + this.stopTrading(); + } ++ if (inactive) return; // Paper + + super.customServerAiStep(); + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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 @@ + package org.spigotmc; + +-import java.util.Collection; ++import net.minecraft.core.BlockPos; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.world.entity.Entity; ++import net.minecraft.world.entity.FlyingMob; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.PathfinderMob; ++import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ambient.AmbientCreature; + import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.animal.Bee; + import net.minecraft.world.entity.animal.Sheep; ++import net.minecraft.world.entity.animal.WaterAnimal; ++import net.minecraft.world.entity.animal.horse.Llama; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EndCrystal; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import net.minecraft.world.entity.boss.wither.WitherBoss; + import net.minecraft.world.entity.item.PrimedTnt; + import net.minecraft.world.entity.monster.Creeper; +-import net.minecraft.world.entity.monster.Monster; +-import net.minecraft.world.entity.monster.Slime; ++import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.Pillager; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; ++import net.minecraft.world.entity.projectile.EyeOfEnder; + import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.entity.projectile.ThrowableProjectile; + import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.entity.raid.Raider; ++import co.aikar.timings.MinecraftTimings; ++import net.minecraft.world.entity.schedule.Activity; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.AABB; +-import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { + + public enum ActivationType + { ++ WATER, // Paper ++ FLYING_MONSTER, // Paper ++ VILLAGER, // Paper + MONSTER, + ANIMAL, + RAIDER, +@@ -0,0 +0,0 @@ public class ActivationRange + + AABB boundingBox = new AABB( 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) { ++ Level world = entity.level; ++ 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 AABB maxBB = new AABB( 0, 0, 0, 0, 0, 0 ); + +@@ -0,0 +0,0 @@ public class ActivationRange + */ + public static ActivationType initializeEntityActivationType(Entity entity) + { ++ if (entity instanceof WaterAnimal) { return ActivationType.WATER; } // Paper ++ else if (entity instanceof Villager) { return ActivationType.VILLAGER; } // Paper ++ else if (entity instanceof FlyingMob && entity instanceof Enemy) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future + if ( entity instanceof Raider ) + { + return ActivationType.RAIDER; +- } else if ( entity instanceof Monster || entity instanceof Slime ) ++ } else if ( entity instanceof Enemy ) // Paper - correct monster check + { + return ActivationType.MONSTER; + } else if ( entity instanceof PathfinderMob || entity instanceof AmbientCreature ) +@@ -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 EyeOfEnder // Paper + || entity instanceof Player + || entity instanceof ThrowableProjectile + || entity instanceof EnderDragon +@@ -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 ServerChunkCache chunkProvider = (ServerChunkCache) world.getChunkSource(); ++ // 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 ( Player player : world.players() ) +@@ -0,0 +0,0 @@ public class ActivationRange + ActivationType.RAIDER.boundingBox = player.getBoundingBox().inflate( raiderActivationRange, 256, raiderActivationRange ); + ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, 256, animalActivationRange ); + ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, 256, monsterActivationRange ); ++ // Paper start ++ ActivationType.WATER.boundingBox = player.getBoundingBox().inflate( waterActivationRange, 256, waterActivationRange ); ++ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().inflate( flyingActivationRange, 256, flyingActivationRange ); ++ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, 256, waterActivationRange ); ++ // Paper end + + world.getEntities().get(maxBB, ActivationRange::activateEntity); + } +@@ -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.level.spigotConfig; ++ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); ++ if (inactiveWakeUpImmunity > -1) { ++ return inactiveWakeUpImmunity; ++ } ++ if (entity.remainingFireTicks > 0) { ++ return 2; ++ } ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ // Paper end + // quick checks. +- if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) ++ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper + { +- return true; ++ return 100; // Paper + } + if ( !( entity instanceof AbstractArrow ) ) + { +- if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) ++ if ( (!entity.isOnGround() && !(entity instanceof FlyingMob)) ) // Paper - remove passengers logic + { +- return true; ++ return 10; // Paper + } + } else if ( !( (AbstractArrow) entity ).inGround ) + { +- return true; ++ return 1; // Paper + } + // special cases. + if ( entity instanceof LivingEntity ) + { + LivingEntity living = (LivingEntity) entity; +- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTime > 0 || living.activeEffects.size() > 0 ) ++ if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper + { +- return true; ++ return 1; // Paper + } +- if ( entity instanceof PathfinderMob && ( (PathfinderMob) entity ).getTarget() != null ) ++ if ( entity instanceof Mob && ((Mob) entity ).getTarget() != null) // Paper + { +- return true; ++ return 20; // Paper ++ } ++ // Paper start ++ if (entity instanceof Bee) { ++ Bee bee = (Bee)entity; ++ BlockPos movingTarget = bee.getMovingTarget(); ++ if (bee.isAngry() || ++ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || ++ (bee.getSavedFlowerPos() != null && bee.getSavedFlowerPos().equals(movingTarget)) ++ ) { ++ return 20; ++ } ++ } ++ if ( entity instanceof Villager ) { ++ Brain behaviorController = ((Villager) entity).getBrain(); ++ ++ if (config.villagersActiveForPanic) { ++ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { ++ if (behaviorController.isActive(activity)) { ++ return 20*5; ++ } ++ } ++ } ++ ++ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { ++ if (behaviorController.isActive(Activity.WORK)) { ++ return config.villagersWorkImmunityFor; ++ } ++ } + } +- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) ++ if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() ) + { +- return true; ++ return 1; + } ++ // Paper end + if ( entity instanceof Animal ) + { + Animal animal = (Animal) entity; + if ( animal.isBaby() || animal.isInLove() ) + { +- return true; ++ return 5; // Paper + } + if ( entity instanceof Sheep && ( (Sheep) entity ).isSheared() ) + { +- return true; ++ return 1; // Paper + } + } + if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive +- return true; ++ return 20; // Paper ++ } ++ // Paper start ++ if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { ++ return 0; ++ } ++ if (entity instanceof Pillager) { ++ Pillager pillager = (Pillager) entity; ++ // TODO:? + } ++ // Paper end + } +- return false; ++ return -1; // Paper + } + + /** +@@ -0,0 +0,0 @@ public class ActivationRange + if ( entity instanceof FireworkRocketEntity ) { + return true; + } ++ // Paper start - special case always immunities ++ // immunize brand new entities, dead entities, and portal scenarios ++ if (entity.defaultActivationState || entity.tickCount < 20*10 || !entity.isAlive() || entity.isInsidePortal || entity.portalCooldown > 0) { ++ return true; ++ } ++ // immunize leashed entities ++ if (entity instanceof Mob && ((Mob)entity).leashHolder instanceof Player) { ++ 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 ( ActivationRange.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.tickCount % 4 == 0 && !ActivationRange.checkEntityImmunities( entity ) ) ++ } else if ( entity.tickCount % 4 == 0 && ActivationRange.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", this.animalActivationRange) != this.animalActivationRange; // Paper + this.animalActivationRange = this.getInt( "entity-activation-range.animals", this.animalActivationRange ); + this.monsterActivationRange = this.getInt( "entity-activation-range.monsters", this.monsterActivationRange ); + this.raiderActivationRange = this.getInt( "entity-activation-range.raiders", this.raiderActivationRange ); + this.miscActivationRange = this.getInt( "entity-activation-range.misc", this.miscActivationRange ); ++ // Paper start ++ this.waterActivationRange = this.getInt( "entity-activation-range.water", this.waterActivationRange ); ++ this.villagerActivationRange = this.getInt( "entity-activation-range.villagers", hasAnimalsConfig ? this.animalActivationRange : this.villagerActivationRange ); ++ this.flyingMonsterActivationRange = this.getInt( "entity-activation-range.flying-monsters", this.flyingMonsterActivationRange ); ++ ++ this.wakeUpInactiveAnimals = this.getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", this.wakeUpInactiveAnimals); ++ this.wakeUpInactiveAnimalsEvery = this.getInt("entity-activation-range.wake-up-inactive.animals-every", this.wakeUpInactiveAnimalsEvery); ++ this.wakeUpInactiveAnimalsFor = this.getInt("entity-activation-range.wake-up-inactive.animals-for", this.wakeUpInactiveAnimalsFor); ++ ++ this.wakeUpInactiveMonsters = this.getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", this.wakeUpInactiveMonsters); ++ this.wakeUpInactiveMonstersEvery = this.getInt("entity-activation-range.wake-up-inactive.monsters-every", this.wakeUpInactiveMonstersEvery); ++ this.wakeUpInactiveMonstersFor = this.getInt("entity-activation-range.wake-up-inactive.monsters-for", this.wakeUpInactiveMonstersFor); ++ ++ this.wakeUpInactiveVillagers = this.getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", this.wakeUpInactiveVillagers); ++ this.wakeUpInactiveVillagersEvery = this.getInt("entity-activation-range.wake-up-inactive.villagers-every", this.wakeUpInactiveVillagersEvery); ++ this.wakeUpInactiveVillagersFor = this.getInt("entity-activation-range.wake-up-inactive.villagers-for", this.wakeUpInactiveVillagersFor); ++ ++ this.wakeUpInactiveFlying = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", this.wakeUpInactiveFlying); ++ this.wakeUpInactiveFlyingEvery = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", this.wakeUpInactiveFlyingEvery); ++ this.wakeUpInactiveFlyingFor = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", this.wakeUpInactiveFlyingFor); ++ ++ this.villagersWorkImmunityAfter = this.getInt( "entity-activation-range.villagers-work-immunity-after", this.villagersWorkImmunityAfter ); ++ this.villagersWorkImmunityFor = this.getInt( "entity-activation-range.villagers-work-immunity-for", this.villagersWorkImmunityFor ); ++ this.villagersActiveForPanic = this.getBoolean( "entity-activation-range.villagers-active-for-panic", this.villagersActiveForPanic ); ++ // Paper end + this.tickInactiveVillagers = this.getBoolean( "entity-activation-range.tick-inactive-villagers", this.tickInactiveVillagers ); + this.log( "Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers ); + } diff --git a/patches/server/Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server/Entity-AddTo-RemoveFrom-World-Events.patch new file mode 100644 index 0000000000..3640e92db3 --- /dev/null +++ b/patches/server/Entity-AddTo-RemoveFrom-World-Events.patch @@ -0,0 +1,26 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + entity.setOrigin(entity.getBukkitEntity().getLocation()); + } + // Paper end ++ new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + + public void onTrackingEnd(Entity entity) { +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + entity.valid = false; // CraftBukkit ++ new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid + } + } + } diff --git a/Spigot-Server-Patches/Entity-Jump-API.patch b/patches/server/Entity-Jump-API.patch similarity index 57% rename from Spigot-Server-Patches/Entity-Jump-API.patch rename to patches/server/Entity-Jump-API.patch index cbec4f8ca4..627a6f2289 100644 --- a/Spigot-Server-Patches/Entity-Jump-API.patch +++ b/patches/server/Entity-Jump-API.patch @@ -4,31 +4,31 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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) { +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } else if (this.isInLava() && (!this.onGround || d7 > d8)) { + this.jumpInLiquid((Tag) FluidTags.LAVA); + } else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) { + if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - this.jump(); - this.jumpTicks = 10; + this.jumpFromGround(); + this.noJumpDelay = 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 + this.noJumpDelay = 0; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.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(); +--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java +@@ -0,0 +0,0 @@ public class Panda extends Animal { + Panda entitypanda = (Panda) iterator.next(); - if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.fh()) { + if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.canPerformAction()) { + if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper - entitypanda.jump(); + entitypanda.jumpFromGround(); + } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop } } @@ -39,7 +39,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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; + return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; } + + @Override @@ -50,9 +50,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public void setJumping(boolean jumping) { + getHandle().setJumping(jumping); -+ if (jumping && getHandle() instanceof EntityInsentient) { ++ if (jumping && getHandle() instanceof Mob) { + // this is needed to actually make a mob jump -+ ((EntityInsentient) getHandle()).getControllerJump().jump(); ++ ((Mob) getHandle()).getJumpControl().jump(); + } + } // Paper end diff --git a/patches/server/Entity-Origin-API.patch b/patches/server/Entity-Origin-API.patch new file mode 100644 index 0000000000..4a8317e2a4 --- /dev/null +++ b/patches/server/Entity-Origin-API.patch @@ -0,0 +1,150 @@ +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/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + entity.valid = true; // CraftBukkit ++ // Paper start - Set origin location when the entity is being added to the world ++ if (entity.getOriginVector() == null) { ++ entity.setOrigin(entity.getBukkitEntity().getLocation()); ++ } ++ // Paper end + } + + public void onTrackingEnd(Entity 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 Nameable, EntityAccess, CommandSource, n + public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only + public boolean forceExplosionKnockback; // SPIGOT-949 + public boolean persistentInvisibility = false; ++ // Paper start ++ @javax.annotation.Nullable ++ private org.bukkit.util.Vector origin; ++ @javax.annotation.Nullable ++ private UUID originWorld; ++ ++ public void setOrigin(@javax.annotation.Nonnull Location location) { ++ this.origin = location.toVector(); ++ this.originWorld = location.getWorld().getUID(); ++ } ++ ++ @javax.annotation.Nullable ++ public org.bukkit.util.Vector getOriginVector() { ++ return this.origin != null ? this.origin.clone() : null; ++ } ++ ++ @javax.annotation.Nullable ++ public UUID getOriginWorld() { ++ return this.originWorld; ++ } ++ // Paper end + // 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 Nameable, EntityAccess, CommandSource, n + this.bukkitEntity.storeBukkitValues(nbt); + } + // CraftBukkit end ++ // Paper start - Save the entity's origin location ++ if (this.origin != null) { ++ nbt.putUUID("Paper.OriginWorld", originWorld); ++ nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); ++ } ++ // Paper end + return nbt; + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + // CraftBukkit end + ++ // Paper start - Restore the entity's origin location ++ ListTag originTag = nbt.getList("Paper.Origin", 6); ++ if (!originTag.isEmpty()) { ++ UUID originWorld = level.getWorld().getUID(); ++ if (nbt.contains("Paper.OriginWorld")) { ++ originWorld = nbt.getUUID("Paper.OriginWorld"); ++ } ++ this.originWorld = originWorld; ++ origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2)); ++ } ++ // Paper end ++ + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being loaded"); +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity { + this.blockState = Blocks.SAND.defaultBlockState(); + } + ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (nbt.contains("SourceLoc_x")) { ++ int srcX = nbt.getInt("SourceLoc_x"); ++ int srcY = nbt.getInt("SourceLoc_y"); ++ int srcZ = nbt.getInt("SourceLoc_z"); ++ this.setOrigin(new org.bukkit.Location(level.getWorld(), srcX, srcY, srcZ)); ++ } ++ // Paper end + } + + public Level getLevel() { +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -0,0 +0,0 @@ public class PrimedTnt extends Entity { + @Override + protected void readAdditionalSaveData(CompoundTag nbt) { + this.setFuse(nbt.getShort("Fuse")); ++ // Paper start - Try and load origin location from the old NBT tags for backwards compatibility ++ if (nbt.contains("SourceLoc_x")) { ++ int srcX = nbt.getInt("SourceLoc_x"); ++ int srcY = nbt.getInt("SourceLoc_y"); ++ int srcZ = nbt.getInt("SourceLoc_z"); ++ this.setOrigin(new org.bukkit.Location(level.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 this.spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public Location getOrigin() { ++ Vector originVector = this.getHandle().getOriginVector(); ++ if (originVector == null) { ++ return null; ++ } ++ World world = this.getWorld(); ++ if (this.getHandle().getOriginWorld() != null) { ++ world = org.bukkit.Bukkit.getWorld(this.getHandle().getOriginWorld()); ++ } ++ ++ //noinspection ConstantConditions ++ return originVector.toLocation(world); ++ } ++ // Paper end + } diff --git a/Spigot-Server-Patches/Entity-fromMobSpawner.patch b/patches/server/Entity-fromMobSpawner.patch similarity index 55% rename from Spigot-Server-Patches/Entity-fromMobSpawner.patch rename to patches/server/Entity-fromMobSpawner.patch index 72a76c566a..4a19a8e0c3 100644 --- a/Spigot-Server-Patches/Entity-fromMobSpawner.patch +++ b/patches/server/Entity-fromMobSpawner.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -16,45 +16,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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())); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + nbt.putUUID("Paper.OriginWorld", originWorld); + nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); } + // Save entity's from mob spawner status + if (spawnedViaMobSpawner) { -+ nbttagcompound.setBoolean("Paper.FromMobSpawner", true); ++ nbt.putBoolean("Paper.FromMobSpawner", true); + } // Paper end - return nbttagcompound; + return nbt; } 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)); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.originWorld = originWorld; + origin = new org.bukkit.util.Vector(originTag.getDouble(0), originTag.getDouble(1), originTag.getDouble(2)); } + -+ spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ spawnedViaMobSpawner = nbt.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 +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.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 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { } + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper - // Spigot Start - if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, blockposition).isCancelled()) { - Entity vehicle = entity.getVehicle(); + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).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(); + //noinspection ConstantConditions + return originVector.toLocation(world); } + + @Override diff --git a/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch b/patches/server/Entity-getEntitySpawnReason.patch similarity index 52% rename from Spigot-Server-Patches/Entity-getEntitySpawnReason.patch rename to patches/server/Entity-getEntitySpawnReason.patch index b469bc0a8c..d2e608bdd4 100644 --- a/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch +++ b/patches/server/Entity-getEntitySpawnReason.patch @@ -9,27 +9,27 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return true; + } + // Paper end + if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper - // Paper start - if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); + if (entity.isRemoved()) { + // Paper start + if (DEBUG_ENTITIES) { 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; + ServerLevel finalWorldServer = worldserver1; + Entity entity = EntityType.loadEntityRecursive(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { +- return !finalWorldServer.addWithUUID(entity1) ? null : entity1; + return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper // CraftBukkit end }); @@ -38,39 +38,39 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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; +@@ -0,0 +0,0 @@ import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.Nameable; 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 ++import net.minecraft.world.entity.animal.AbstractFish; ++import net.minecraft.world.entity.animal.Animal; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.vehicle.Boat; +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } } }; - 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())); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + nbt.putUUID("Paper.OriginWorld", originWorld); + nbt.put("Paper.Origin", this.newDoubleList(origin.getX(), origin.getY(), origin.getZ())); } + if (spawnReason != null) { -+ nbttagcompound.setString("Paper.SpawnReason", spawnReason.name()); ++ nbt.putString("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 + nbt.putBoolean("Paper.FromMobSpawner", true); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - spawnedViaMobSpawner = nbttagcompound.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status -+ if (nbttagcompound.hasKey("Paper.SpawnReason")) { -+ String spawnReasonName = nbttagcompound.getString("Paper.SpawnReason"); + spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status ++ if (nbt.contains("Paper.SpawnReason")) { ++ String spawnReasonName = nbt.getString("Paper.SpawnReason"); + try { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.valueOf(spawnReasonName); + } catch (Exception ignored) { @@ -80,8 +80,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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")) { ++ } else if (this instanceof Mob && (this instanceof Animal || this instanceof AbstractFish) && !((Mob) this).removeWhenFarAway(0.0)) { ++ if (!nbt.getBoolean("PersistenceRequired")) { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; + } + } @@ -92,18 +92,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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 +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.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 - } +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + // 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()) { ++ entity.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; // Paper + flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).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 diff --git a/Spigot-Server-Patches/Entity-isTicking.patch b/patches/server/Entity-isTicking.patch similarity index 73% rename from Spigot-Server-Patches/Entity-isTicking.patch rename to patches/server/Entity-isTicking.patch index 85834c6b36..b3f149125e 100644 --- a/Spigot-Server-Patches/Entity-isTicking.patch +++ b/patches/server/Entity-isTicking.patch @@ -8,21 +8,21 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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; +@@ -0,0 +0,0 @@ import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; 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.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.TicketType; -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public static int nextEntityId() { - return entityCount.incrementAndGet(); + return ENTITY_COUNTER.incrementAndGet(); } + + public boolean isTicking() { -+ return ((ChunkProviderServer) world.getChunkProvider()).isInEntityTickingChunk(this); ++ return ((ServerChunkCache) level.getChunkSource()).isPositionTicking(this); + } // Paper end } diff --git a/patches/server/Entity-load-save-limit-per-chunk.patch b/patches/server/Entity-load-save-limit-per-chunk.patch new file mode 100644 index 0000000000..2550ae6663 --- /dev/null +++ b/patches/server/Entity-load-save-limit-per-chunk.patch @@ -0,0 +1,96 @@ +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 @@ + package com.destroystokyo.paper; + + import java.util.Arrays; ++import java.util.HashMap; + import java.util.List; ++import java.util.Map; + import java.util.stream.Collectors; + import net.minecraft.world.Difficulty; ++import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.monster.Vindicator; + import net.minecraft.world.entity.monster.Zombie; + import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode; +@@ -0,0 +0,0 @@ public class PaperWorldConfig { + ); + } + ++ 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); ++ EntityType.getEntityNameList().forEach(name -> { ++ final EntityType type = EntityType.byString(name.getPath()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); ++ final String path = ".entity-per-chunk-save-limit." + name.getPath(); ++ 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); ++ }); ++ } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + final Spliterator spliterator = entityNbtList.spliterator(); + + return StreamSupport.stream(new Spliterator() { ++ final java.util.Map, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper + public boolean tryAdvance(Consumer consumer) { + return spliterator.tryAdvance((nbtbase) -> { + EntityType.loadEntityRecursive((CompoundTag) nbtbase, world, (entity) -> { ++ // Paper start ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (this.loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return null; ++ } ++ this.loadedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + consumer.accept(entity); + return entity; + }); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +@@ -0,0 +0,0 @@ public class EntityStorage implements EntityPersistentStorage { + + } else { + ListTag listTag = new ListTag(); ++ final java.util.Map, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper + dataList.getEntities().forEach((entity) -> { ++ // Paper start ++ final EntityType entityType = entity.getType(); ++ final int saveLimit = this.level.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + CompoundTag compoundTag = new CompoundTag(); + if (entity.save(compoundTag)) { + listTag.add(compoundTag); diff --git a/patches/server/EntityMoveEvent.patch b/patches/server/EntityMoveEvent.patch new file mode 100644 index 0000000000..d0da40ed9d --- /dev/null +++ b/patches/server/EntityMoveEvent.patch @@ -0,0 +1,55 @@ +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 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper ++ worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.profiler.push(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper ++ public boolean hasEntityMoveEvent = false; // Paper + public 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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + + this.pushEntities(); + this.level.getProfiler().pop(); ++ // Paper start ++ if (((ServerLevel) this.level).hasEntityMoveEvent) { ++ if (this.xo != getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { ++ Location from = new Location(this.level.getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); ++ Location to = new Location (this.level.getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); ++ io.papermc.paper.event.entity.EntityMoveEvent event = new io.papermc.paper.event.entity.EntityMoveEvent(this.getBukkitLivingEntity(), from, to.clone()); ++ if (!event.callEvent()) { ++ absMoveTo(from.getX(), from.getY(), from.getZ(), from.getYaw(), from.getPitch()); ++ } else if (!to.equals(event.getTo())) { ++ absMoveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); ++ } ++ } ++ } ++ // Paper end + if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(DamageSource.DROWN, 1.0F); + } diff --git a/patches/server/EntityPathfindEvent.patch b/patches/server/EntityPathfindEvent.patch new file mode 100644 index 0000000000..a0c4c849ea --- /dev/null +++ b/patches/server/EntityPathfindEvent.patch @@ -0,0 +1,109 @@ +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/FlyingPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java +@@ -0,0 +0,0 @@ public class FlyingPathNavigation extends PathNavigation { + + @Override + public Path createPath(Entity entity, int distance) { +- return this.createPath(entity.blockPosition(), distance); ++ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +@@ -0,0 +0,0 @@ public class GroundPathNavigation extends PathNavigation { + + @Override + public Path createPath(Entity entity, int distance) { +- return this.createPath(entity.blockPosition(), distance); ++ return this.a(entity.blockPosition(), entity, distance); // Paper - Forward target entity + } + + private int getSurfaceY() { +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Vec3i; + import net.minecraft.network.protocol.game.DebugPackets; + import net.minecraft.tags.BlockTags; ++import net.minecraft.server.MCUtil; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.Mob; +@@ -0,0 +0,0 @@ public abstract class PathNavigation { + + @Nullable + public Path createPath(BlockPos target, int distance) { +- return this.createPath(ImmutableSet.of(target), 8, false, distance); ++ // Paper start - add target parameter ++ return this.a(target, null, distance); ++ } ++ @Nullable public Path a(BlockPos blockposition, Entity target, int distance) { ++ return this.createPath(ImmutableSet.of(blockposition), target, 8, false, distance); ++ // Paper end + } + + @Nullable +@@ -0,0 +0,0 @@ public abstract class PathNavigation { + + @Nullable + public Path createPath(Entity entity, int distance) { +- return this.createPath(ImmutableSet.of(entity.blockPosition()), 16, true, distance); ++ return this.createPath(ImmutableSet.of(entity.blockPosition()), entity, 16, true, distance); // Paper + } + + @Nullable +@@ -0,0 +0,0 @@ public abstract class PathNavigation { + + @Nullable + protected Path createPath(Set positions, int range, boolean useHeadPos, int distance, float followRange) { ++ return this.createPath(positions, null, range, useHeadPos, distance, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE)); ++ } ++ ++ @Nullable ++ protected Path createPath(Set positions, Entity target, int range, boolean useHeadPos, int distance) { ++ return this.createPath(positions, target, range, useHeadPos, distance, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE)); ++ } ++ ++ @Nullable protected Path createPath(Set positions, Entity target, int range, boolean useHeadPos, int distance, float followRange) { ++ // Paper end + if (positions.isEmpty()) { + return null; + } else if (this.mob.getY() < (double)this.level.getMinBuildHeight()) { +@@ -0,0 +0,0 @@ public abstract class PathNavigation { + } else if (this.path != null && !this.path.isDone() && positions.contains(this.targetPos)) { + return this.path; + } else { ++ // Paper start - Pathfind event ++ boolean copiedSet = false; ++ for (BlockPos possibleTarget : positions) { ++ if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(), ++ MCUtil.toLocation(this.mob.level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { ++ if (!copiedSet) { ++ copiedSet = true; ++ positions = new java.util.HashSet<>(positions); ++ } ++ // note: since we copy the set this remove call is safe, since we're iterating over the old copy ++ positions.remove(possibleTarget); ++ if (positions.isEmpty()) { ++ return null; ++ } ++ } ++ } ++ // Paper end + this.level.getProfiler().push("pathfind"); + BlockPos blockPos = useHeadPos ? this.mob.blockPosition().above() : this.mob.blockPosition(); + int i = (int)(followRange + (float)range); diff --git a/patches/server/EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server/EntityRegainHealthEvent-isFastRegen-API.patch new file mode 100644 index 0000000000..11d235352e --- /dev/null +++ b/patches/server/EntityRegainHealthEvent-isFastRegen-API.patch @@ -0,0 +1,42 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity 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.level.getCraftServer().getPluginManager().callEvent(event); +diff --git a/src/main/java/net/minecraft/world/food/FoodData.java b/src/main/java/net/minecraft/world/food/FoodData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/food/FoodData.java ++++ b/src/main/java/net/minecraft/world/food/FoodData.java +@@ -0,0 +0,0 @@ public class FoodData { + if (this.tickTimer >= this.saturatedRegenRate) { // CraftBukkit + float f = Math.min(this.saturationLevel, 6.0F); + +- player.heal(f / 6.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.SATIATED); // CraftBukkit - added RegainReason ++ player.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 + player.applyExhaustion(f, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.REGEN); // CraftBukkit - EntityExhaustionEvent + this.tickTimer = 0; diff --git a/Spigot-Server-Patches/Expand-Explosions-API.patch b/patches/server/Expand-Explosions-API.patch similarity index 67% rename from Spigot-Server-Patches/Expand-Explosions-API.patch rename to patches/server/Expand-Explosions-API.patch index 7da769e18b..abaa81a5a1 100644 --- a/Spigot-Server-Patches/Expand-Explosions-API.patch +++ b/patches/server/Expand-Explosions-API.patch @@ -11,11 +11,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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; + return !this.world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; } + // Paper start ++ @Override + 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; ++ return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? Explosion.BlockInteraction.BREAK : Explosion.BlockInteraction.NONE).wasCanceled; + } + // Paper end diff --git a/Spigot-Server-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server/Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 55% rename from Spigot-Server-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch rename to patches/server/Expand-World.spawnParticle-API-and-add-Builder.patch index 93cc71f053..2da3b724db 100644 --- a/Spigot-Server-Patches/Expand-World.spawnParticle-API-and-add-Builder.patch +++ b/patches/server/Expand-World.spawnParticle-API-and-add-Builder.patch @@ -9,39 +9,30 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 { +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } - 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) { + public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { + // 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) { ++ public int sendParticles(List receivers, ServerPlayer 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); + ClientboundLevelParticlesPacket packetplayoutworldparticles = new ClientboundLevelParticlesPacket(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i); // CraftBukkit end int j = 0; - for (int k = 0; k < this.players.size(); ++k) { -- EntityPlayer entityplayer = (EntityPlayer) this.players.get(k); -+ for (EntityHuman entityhuman : receivers) { // Paper - Particle API Expansion -+ EntityPlayer entityplayer = (EntityPlayer) entityhuman; // Paper - Particle API Expansion +- ServerPlayer entityplayer = (ServerPlayer) this.players.get(k); ++ for (Player entityhuman : receivers) { // Paper - Particle API Expansion ++ ServerPlayer entityplayer = (ServerPlayer) 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 + if (this.sendParticles(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 @@ -58,9 +49,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (data != null && !particle.getDataType().isInstance(data)) { throw new IllegalArgumentException("data should be " + particle.getDataType() + " got " + data.getClass()); } - getHandle().sendParticles( + this.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 ++ 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 diff --git a/Spigot-Server-Patches/ExperienceOrbMergeEvent.patch b/patches/server/ExperienceOrbMergeEvent.patch similarity index 61% rename from Spigot-Server-Patches/ExperienceOrbMergeEvent.patch rename to patches/server/ExperienceOrbMergeEvent.patch index a577862204..5449389178 100644 --- a/Spigot-Server-Patches/ExperienceOrbMergeEvent.patch +++ b/patches/server/ExperienceOrbMergeEvent.patch @@ -3,6 +3,7 @@ From: Aikar Date: Tue, 19 Dec 2017 22:57:26 -0500 Subject: [PATCH] ExperienceOrbMergeEvent +Has to be reimplemented at one point maybe 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. @@ -12,11 +13,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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; + if (e instanceof net.minecraft.world.entity.ExperienceOrb) { + net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) 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 +- if (!loopItem.isRemoved() && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ if (!loopItem.isRemoved() && !(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 - ExperienceOrbMergeEvent long newTotal = (long)xp.value + (long)loopItem.value; if ((int) newTotal < 0) continue; // Overflow if (maxValue > 0 && newTotal > (long)maxValue) { diff --git a/patches/server/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch new file mode 100644 index 0000000000..b6c7f851d7 --- /dev/null +++ b/patches/server/ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -0,0 +1,338 @@ +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/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + + // Drop event experience + if (flag && event != null) { +- iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop()); ++ iblockdata.getBlock().popExperience(this.level, pos, event.getExpToDrop(), this.player); // Paper + } + + return true; +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + public int value; + private int count; + private Player followingPlayer; ++ // 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(CompoundTag nbttagcompound) { ++ if (!nbttagcompound.contains("Paper.ExpData", 10)) { // 10 = compound ++ return; ++ } ++ CompoundTag 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.contains("reason")) { ++ String reason = comp.getString("reason"); ++ try { ++ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason); ++ } catch (Exception e) { ++ this.level.getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason); ++ } ++ } ++ } ++ private void savePaperNBT(CompoundTag nbttagcompound) { ++ CompoundTag comp = new CompoundTag(); ++ if (this.sourceEntityId != null) { ++ comp.putUUID("source", this.sourceEntityId); ++ } ++ if (this.triggerEntityId != null) { ++ comp.putUUID("trigger", triggerEntityId); ++ } ++ if (this.spawnReason != null && this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) { ++ comp.putString("reason", this.spawnReason.name()); ++ } ++ nbttagcompound.put("Paper.ExpData", comp); ++ } + + public ExperienceOrb(Level world, double x, double y, double z, int amount) { ++ this(world, x, y, z, amount, null, null); ++ } ++ ++ public ExperienceOrb(Level 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 ExperienceOrb(Level world, double d0, double d1, double d2, int i, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { + this(EntityType.EXPERIENCE_ORB, world); +- this.setPos(x, y, z); ++ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null; ++ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null; ++ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; ++ // Paper end ++ this.setPos(d0, d1, d2); + this.setYRot((float) (this.random.nextDouble() * 360.0D)); + this.setDeltaMovement((this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D, this.random.nextDouble() * 0.2D * 2.0D, (this.random.nextDouble() * 0.20000000298023224D - 0.10000000149011612D) * 2.0D); +- this.value = amount; ++ this.value = i; + } + + public ExperienceOrb(EntityType type, Level world) { +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + } + + public static void award(ServerLevel world, Vec3 pos, int amount) { ++ // Paper start - add reasons for orbs ++ award(world, pos, amount, null, null, null); ++ } ++ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId) { ++ award(world, pos, amount, reason, triggerId, null); ++ } ++ public static void award(ServerLevel world, Vec3 pos, int amount, org.bukkit.entity.ExperienceOrb.SpawnReason reason, Entity triggerId, Entity sourceId) { ++ // Paper end - add reasons for orbs + while (amount > 0) { + int j = ExperienceOrb.getExperienceValue(amount); + + amount -= j; + if (!ExperienceOrb.tryMergeToExisting(world, pos, j)) { +- world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j)); ++ world.addFreshEntity(new ExperienceOrb(world, pos.x(), pos.y(), pos.z(), j, reason, triggerId, sourceId)); // Paper - add reason + } + } + +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + nbt.putShort("Age", (short) this.age); + nbt.putShort("Value", (short) this.value); + nbt.putInt("Count", this.count); ++ this.savePaperNBT(nbt); // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + this.age = nbt.getShort("Age"); + this.value = nbt.getShort("Value"); + this.count = Math.max(nbt.getInt("Count"), 1); ++ this.loadPaperNBT(nbt); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + protected void dropExperience() { + // CraftBukkit start - Update getExpReward() above if the removed if() changes! + if (true) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop); ++ LivingEntity attacker = this.lastHurtByPlayer != null ? this.lastHurtByPlayer : this.lastHurtByMob; // Paper ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, attacker, this); // Paper + this.expToDrop = 0; + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java +@@ -0,0 +0,0 @@ public abstract class Animal extends AgeableMob { + if (world.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience)); ++ world.addFreshEntity(new ExperienceOrb(world, this.getX(), this.getY(), this.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityageable)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java +@@ -0,0 +0,0 @@ public class Fox extends Animal { + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + // CraftBukkit start - use event experience + if (experience > 0) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), experience, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer, entityfox)); // Paper + } + // CraftBukkit end + } +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -0,0 +0,0 @@ public class Turtle extends Animal { + Random random = this.animal.getRandom(); + + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.animal.getX(), this.animal.getY(), this.animal.getZ(), random.nextInt(7) + 1, org.bukkit.entity.ExperienceOrb.SpawnReason.BREED, entityplayer)); // Paper; + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -0,0 +0,0 @@ public class EnderDragon extends Mob implements Enemy { + + if (this.level instanceof ServerLevel) { + if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && flag) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F)); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper + } + + if (this.dragonDeathTime == 1 && !this.isSilent()) { +@@ -0,0 +0,0 @@ public class EnderDragon extends Mob implements Enemy { + this.yBodyRot = this.getYRot(); + if (this.dragonDeathTime == 200 && this.level instanceof ServerLevel) { + if (flag) { +- ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F)); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), Mth.floor((float) short0 * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper + } + + if (this.dragonFight != null) { +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + + if (offer.shouldRewardExp()) { +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -0,0 +0,0 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + if (offer.shouldRewardExp()) { + int i = 3 + this.random.nextInt(4); + +- this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i)); ++ this.level.addFreshEntity(new ExperienceOrb(this.level, this.getX(), this.getY() + 0.5D, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +@@ -0,0 +0,0 @@ public class FishingHook extends Projectile { + this.level.addFreshEntity(entityitem); + // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop() + if (playerFishEvent.getExpToDrop() > 0) { +- entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop())); ++ entityhuman.level.addFreshEntity(new ExperienceOrb(entityhuman.level, entityhuman.getX(), entityhuman.getY() + 0.5D, entityhuman.getZ() + 0.5D, playerFishEvent.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.FISHING, this.getPlayerOwner(), this)); // Paper + } + // CraftBukkit end + if (itemstack1.is((Tag) ItemTags.FISHES)) { +diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownExperienceBottle.java +@@ -0,0 +0,0 @@ public class ThrownExperienceBottle extends ThrowableItemProjectile { + } + // CraftBukkit end + +- ExperienceOrb.award((ServerLevel) this.level, this.position(), i); ++ ExperienceOrb.award((ServerLevel) this.level, this.position(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.EXP_BOTTLE, this.getOwner(), this); // Paper + this.discard(); + } + +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -0,0 +0,0 @@ public class GrindstoneMenu extends AbstractContainerMenu { + public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) { + context.execute((world, blockposition) -> { + if (world instanceof ServerLevel) { +- ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf((Vec3i) blockposition), this.getExperienceAmount(world)); ++ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf((Vec3i) blockposition), this.getExperienceAmount(world), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); // Paper + } + + world.levelEvent(1042, blockposition, 0); +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 BlockBehaviour implements ItemLike { + } + + public void popExperience(ServerLevel world, BlockPos pos, int size) { ++ // Paper start - add player parameter ++ popExperience(world, pos, size, null); ++ } ++ public void popExperience(ServerLevel world, BlockPos pos, int size, net.minecraft.server.level.ServerPlayer player) { ++ // Paper end - add player parameter + if (world.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS)) { +- ExperienceOrb.award(world, Vec3.atCenterOf((Vec3i) pos), size); ++ ExperienceOrb.award(world, Vec3.atCenterOf((Vec3i) pos), size, org.bukkit.entity.ExperienceOrb.SpawnReason.BLOCK_BREAK, player); // Paper + } + + } +diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + j = event.getExpToDrop(); + // CraftBukkit end + +- ExperienceOrb.award(worldserver, vec3d, j); ++ ExperienceOrb.award(worldserver, vec3d, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman); // Paper + } + + @Override +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 PrimedTnt(this.world, x, y, z, null); + } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { +- entity = new net.minecraft.world.entity.ExperienceOrb(this.world, x, y, z, 0); ++ entity = new net.minecraft.world.entity.ExperienceOrb(this.world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper + } else if (LightningStrike.class.isAssignableFrom(clazz)) { + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(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 { + this.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 net.minecraft.world.entity.ExperienceOrb getHandle() { + return (net.minecraft.world.entity.ExperienceOrb) entity; diff --git a/Spigot-Server-Patches/Expose-Arrow-getItemStack.patch b/patches/server/Expose-Arrow-getItemStack.patch similarity index 52% rename from Spigot-Server-Patches/Expose-Arrow-getItemStack.patch rename to patches/server/Expose-Arrow-getItemStack.patch index 3fef098cb0..0c7af0da2c 100644 --- a/Spigot-Server-Patches/Expose-Arrow-getItemStack.patch +++ b/patches/server/Expose-Arrow-getItemStack.patch @@ -4,30 +4,18 @@ 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()); + this.getHandle().pickup = net.minecraft.world.entity.projectile.AbstractArrow.Pickup.byOrdinal(status.ordinal()); } + // Paper start + @Override + public org.bukkit.craftbukkit.inventory.CraftItemStack getItemStack() { -+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getOriginalItemStack()); ++ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(getHandle().getPickupItem()); + } + //Paper end + diff --git a/patches/server/Expose-LivingEntity-hurt-direction.patch b/patches/server/Expose-LivingEntity-hurt-direction.patch new file mode 100644 index 0000000000..a86f75098a --- /dev/null +++ b/patches/server/Expose-LivingEntity-hurt-direction.patch @@ -0,0 +1,26 @@ +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/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().take(((CraftItem) item).getHandle(), quantity); + } ++ ++ @Override ++ public float getHurtDirection() { ++ return getHandle().hurtDir; ++ } ++ ++ @Override ++ public void setHurtDirection(float hurtDirection) { ++ getHandle().hurtDir = hurtDirection; ++ } + // Paper end + } diff --git a/Spigot-Server-Patches/Expose-MinecraftServer-isRunning.patch b/patches/server/Expose-MinecraftServer-isRunning.patch similarity index 100% rename from Spigot-Server-Patches/Expose-MinecraftServer-isRunning.patch rename to patches/server/Expose-MinecraftServer-isRunning.patch diff --git a/patches/server/Expose-Tracked-Players.patch b/patches/server/Expose-Tracked-Players.patch new file mode 100644 index 0000000000..da89eb153d --- /dev/null +++ b/patches/server/Expose-Tracked-Players.patch @@ -0,0 +1,32 @@ +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/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 ++ @Override ++ public Set getTrackedPlayers() { ++ if (entity.tracker == null) { ++ return java.util.Collections.emptySet(); ++ } ++ ++ Set set = new HashSet<>(entity.tracker.seenBy.size()); ++ for (net.minecraft.server.network.ServerPlayerConnection connection : entity.tracker.seenBy) { ++ set.add(connection.getPlayer().getBukkitEntity().getPlayer()); ++ } ++ return set; ++ } ++ // Paper end ++ + // Spigot start + private final Player.Spigot spigot = new Player.Spigot() + { diff --git a/patches/server/Expose-attack-cooldown-methods-for-Player.patch b/patches/server/Expose-attack-cooldown-methods-for-Player.patch new file mode 100644 index 0000000000..314a45240a --- /dev/null +++ b/patches/server/Expose-attack-cooldown-methods-for-Player.patch @@ -0,0 +1,32 @@ +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/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.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND)); + connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected())); + } ++ ++ @Override ++ public float getCooldownPeriod() { ++ return getHandle().getCurrentItemAttackStrengthDelay(); ++ } ++ ++ @Override ++ public float getCooledAttackStrength(float adjustTicks) { ++ return getHandle().getAttackStrengthScale(adjustTicks); ++ } ++ ++ @Override ++ public void resetCooldown() { ++ getHandle().resetAttackStrengthTicker(); ++ } + // Paper end + + // Spigot start diff --git a/Spigot-Server-Patches/Expose-client-protocol-version-and-virtual-host.patch b/patches/server/Expose-client-protocol-version-and-virtual-host.patch similarity index 54% rename from Spigot-Server-Patches/Expose-client-protocol-version-and-virtual-host.patch rename to patches/server/Expose-client-protocol-version-and-virtual-host.patch index 14d625af67..d78a465b7b 100644 --- a/Spigot-Server-Patches/Expose-client-protocol-version-and-virtual-host.patch +++ b/patches/server/Expose-client-protocol-version-and-virtual-host.patch @@ -12,23 +12,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.network; + -+import net.minecraft.network.NetworkManager; -+ +import java.net.InetSocketAddress; + +import javax.annotation.Nullable; ++import net.minecraft.network.Connection; + +public class PaperNetworkClient implements NetworkClient { + -+ private final NetworkManager networkManager; ++ private final Connection networkManager; + -+ PaperNetworkClient(NetworkManager networkManager) { ++ PaperNetworkClient(Connection networkManager) { + this.networkManager = networkManager; + } + + @Override + public InetSocketAddress getAddress() { -+ return (InetSocketAddress) this.networkManager.getSocketAddress(); ++ return (InetSocketAddress) this.networkManager.getRemoteAddress(); + } + + @Override @@ -60,44 +59,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + +} -diff --git a/src/main/java/net/minecraft/network/NetworkManager.java b/src/main/java/net/minecraft/network/NetworkManager.java +diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.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; +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + private float averageSentPackets; + private int tickCount; + private boolean handlingFault; + // 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 + public Connection(PacketFlow side) { + this.receiving = side; +diff --git a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.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: 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/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, pos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); + if (event.isCancelled()) { + // Let the client know the block still exists ++ // Paper start - brute force neighbor blocks for any attached blocks ++ for (Direction dir : Direction.values()) { ++ this.player.connection.send(new ClientboundBlockUpdatePacket(level, pos.relative(dir))); ++ } ++ // Paper end + this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, pos)); + // Update any tile entity data for this block + BlockEntity tileentity = this.level.getBlockEntity(pos); +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + + // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) + player.connection.send(new ClientboundBlockUpdatePacket(world, blockposition.above())); ++ // Paper start - extend Player Interact cancellation // TODO: consider merging this into the extracted method ++ } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.StructureBlock) { ++ player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId)); ++ } else if (iblockdata.getBlock() instanceof net.minecraft.world.level.block.CommandBlock) { ++ player.connection.send(new net.minecraft.network.protocol.game.ClientboundContainerClosePacket(this.player.containerMenu.containerId)); + } ++ // Paper end - extend Player Interact cancellation + player.getBukkitEntity().updateInventory(); // SPIGOT-2867 + enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; + } else if (this.gameModeForPlayer == GameType.SPECTATOR) { diff --git a/patches/server/Extend-block-drop-capture-to-capture-all-items-added.patch b/patches/server/Extend-block-drop-capture-to-capture-all-items-added.patch new file mode 100644 index 0000000000..214699470c --- /dev/null +++ b/patches/server/Extend-block-drop-capture-to-capture-all-items-added.patch @@ -0,0 +1,52 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit + return false; + } else { ++ // Paper start - capture all item additions to the world ++ if (captureDrops != null && entity instanceof net.minecraft.world.entity.item.ItemEntity) { ++ captureDrops.add((net.minecraft.world.entity.item.ItemEntity) entity); ++ return true; ++ } ++ // Paper end ++ + if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) { + return false; + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; + import net.minecraft.world.MenuProvider; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.DoubleHighBlockItem; + import net.minecraft.world.item.ItemStack; +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + // return true; // CraftBukkit + } + // CraftBukkit start ++ java.util.List itemsToDrop = level.captureDrops; // Paper - store current list ++ level.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, level.captureDrops); ++ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - use stored ref + } +- level.captureDrops = null; ++ //world.captureDrops = null; // Paper - move up + + // Drop event experience + if (flag && event != null) { diff --git a/patches/server/Faster-redstone-torch-rapid-clock-removal.patch b/patches/server/Faster-redstone-torch-rapid-clock-removal.patch new file mode 100644 index 0000000000..94603f383f --- /dev/null +++ b/patches/server/Faster-redstone-torch-rapid-clock-removal.patch @@ -0,0 +1,81 @@ +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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -0,0 +0,0 @@ import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit + public class RedstoneTorchBlock extends TorchBlock { + + public static final BooleanProperty LIT = BlockStateProperties.LIT; +- private static final Map> RECENT_TOGGLES = new WeakHashMap(); ++ // Paper - Move the mapped list to World + public static final int RECENT_TOGGLE_TIMER = 60; + public static final int MAX_RECENT_TOGGLES = 8; + public static final int RESTART_DELAY = 160; +@@ -0,0 +0,0 @@ public class RedstoneTorchBlock extends TorchBlock { + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { + boolean flag = this.hasNeighborSignal((Level) world, pos, state); +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.get(world); +- +- while (list != null && !list.isEmpty() && world.getGameTime() - ((RedstoneTorchBlock.Toggle) list.get(0)).when > 60L) { +- list.remove(0); ++ // Paper start ++ java.util.ArrayDeque redstoneUpdateInfos = world.redstoneUpdateInfos; ++ if (redstoneUpdateInfos != null) { ++ RedstoneTorchBlock.Toggle curr; ++ while ((curr = redstoneUpdateInfos.peek()) != null && world.getGameTime() - curr.when > 60L) { ++ redstoneUpdateInfos.poll(); ++ } + } ++ // Paper end + + // CraftBukkit start + org.bukkit.plugin.PluginManager manager = world.getCraftServer().getPluginManager(); +@@ -0,0 +0,0 @@ public class RedstoneTorchBlock extends TorchBlock { + } + + private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) { +- List list = (List) RedstoneTorchBlock.RECENT_TOGGLES.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 (addNew) { + list.add(new RedstoneTorchBlock.Toggle(pos.immutable(), world.getGameTime())); +@@ -0,0 +0,0 @@ public class RedstoneTorchBlock extends TorchBlock { + + int i = 0; + +- for (int j = 0; j < list.size(); ++j) { +- RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = (RedstoneTorchBlock.Toggle) list.get(j); +- ++ for (java.util.Iterator iterator = list.iterator(); iterator.hasNext();) { ++ RedstoneTorchBlock.Toggle blockredstonetorch_redstoneupdateinfo = iterator.next(); ++ // Paper end + if (blockredstonetorch_redstoneupdateinfo.pos.equals(pos)) { + ++i; + if (i >= 8) { diff --git a/Spigot-Server-Patches/Fill-Profile-Property-Events.patch b/patches/server/Fill-Profile-Property-Events.patch similarity index 100% rename from Spigot-Server-Patches/Fill-Profile-Property-Events.patch rename to patches/server/Fill-Profile-Property-Events.patch diff --git a/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/patches/server/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch similarity index 51% rename from Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch rename to patches/server/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch index b94709a61f..283dafc399 100644 --- a/Spigot-Server-Patches/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ b/patches/server/Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch @@ -8,14 +8,6 @@ diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/m 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); @@ -29,21 +21,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } } -diff --git a/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java b/src/main/java/net/minecraft/world/entity/item/EntityFallingBlock.java +diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity { @Override - protected void loadData(NBTTagCompound nbttagcompound) { - this.block = GameProfileSerializer.c(nbttagcompound.getCompound("BlockState")); + protected void readAdditionalSaveData(CompoundTag nbt) { + this.blockState = NbtUtils.readBlockState(nbt.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(); ++ final Block b = this.blockState.getBlock(); ++ if (this.level.paperConfig.filterNBTFromSpawnEgg ++ && (b == Blocks.COMMAND_BLOCK ++ || b == Blocks.REPEATING_COMMAND_BLOCK ++ || b == Blocks.CHAIN_COMMAND_BLOCK ++ || b == Blocks.JIGSAW ++ || b == Blocks.STRUCTURE_BLOCK ++ || b instanceof net.minecraft.world.level.block.GameMasterBlock)) { ++ this.blockState = Blocks.STONE.defaultBlockState(); + } + // Paper end - this.ticksLived = nbttagcompound.getInt("Time"); - if (nbttagcompound.hasKeyOfType("HurtEntities", 99)) { - this.hurtEntities = nbttagcompound.getBoolean("HurtEntities"); + this.time = nbt.getInt("Time"); + if (nbt.contains("HurtEntities", 99)) { + this.hurtEntities = nbt.getBoolean("HurtEntities"); diff --git a/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/patches/server/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch similarity index 76% rename from Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch rename to patches/server/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch index b706fccec8..aaa03eccd8 100644 --- a/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch +++ b/patches/server/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch @@ -23,20 +23,20 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.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 { +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { } // CraftBukkit start -- if (!this.sticky) { +- if (!this.isSticky) { + //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()); + org.bukkit.block.Block block = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.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 { + world.getCraftServer().getPluginManager().callEvent(event); +@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { if (event.isCancelled()) { return; } @@ -44,4 +44,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + //} // Paper // PAIL: checkME - what happened to setTypeAndData? // CraftBukkit end - world.playBlockAction(blockposition, this, b0, enumdirection.c()); + world.blockEvent(pos, this, b0, enumdirection.get3DDataValue()); diff --git a/patches/server/Fire-event-on-GS4-query.patch b/patches/server/Fire-event-on-GS4-query.patch new file mode 100644 index 0000000000..d98be1e2f4 --- /dev/null +++ b/patches/server/Fire-event-on-GS4-query.patch @@ -0,0 +1,209 @@ +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/NetworkDataOutputStream.java b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java ++++ b/src/main/java/net/minecraft/server/rcon/NetworkDataOutputStream.java +@@ -0,0 +0,0 @@ public class NetworkDataOutputStream { + this.dataOutputStream.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 write(int value) throws IOException { + this.dataOutputStream.write(value); + } +diff --git a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java ++++ b/src/main/java/net/minecraft/server/rcon/thread/QueryThreadGs4.java +@@ -0,0 +0,0 @@ public class QueryThreadGs4 extends GenericThread { + if (3 <= i && -2 == bs[0] && -3 == bs[1]) { + LOGGER.debug("Packet '{}' [{}]", PktUtils.toHexString(bs[2]), socketAddress); + switch(bs[2]) { +- case 0: +- if (!this.validChallenge(packet)) { +- LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress); +- return false; +- } else if (15 == i) { +- this.sendTo(this.buildRuleResponse(packet), packet); +- LOGGER.debug("Rules [{}]", (Object)socketAddress); +- } else { +- NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460); +- networkDataOutputStream.write(0); +- networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress())); +- networkDataOutputStream.writeString(this.serverName); +- networkDataOutputStream.writeString("SMP"); +- networkDataOutputStream.writeString(this.worldName); +- networkDataOutputStream.writeString(Integer.toString(this.serverInterface.getPlayerCount())); +- networkDataOutputStream.writeString(Integer.toString(this.maxPlayers)); +- networkDataOutputStream.writeShort((short)this.serverPort); +- networkDataOutputStream.writeString(this.hostIp); +- this.sendTo(networkDataOutputStream.toByteArray(), packet); +- LOGGER.debug("Status [{}]", (Object)socketAddress); +- } +- default: +- return true; +- case 9: +- this.sendChallenge(packet); +- LOGGER.debug("Challenge [{}]", (Object)socketAddress); +- return true; ++ case 0: ++ if (!this.validChallenge(packet)) { ++ LOGGER.debug("Invalid challenge [{}]", (Object)socketAddress); ++ return false; ++ } else if (15 == i) { ++ this.sendTo(this.buildRuleResponse(packet), packet); ++ LOGGER.debug("Rules [{}]", (Object)socketAddress); ++ } else { ++ NetworkDataOutputStream networkDataOutputStream = new NetworkDataOutputStream(1460); ++ networkDataOutputStream.write(0); ++ networkDataOutputStream.writeBytes(this.getIdentBytes(packet.getSocketAddress())); ++ ++ 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.serverName) ++ .map(this.worldName) ++ .currentPlayers(this.serverInterface.getPlayerCount()) ++ .maxPlayers(this.maxPlayers) ++ .port(this.serverPort) ++ .hostname(this.hostIp) ++ .gameVersion(this.serverInterface.getServerVersion()) ++ .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, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); ++ ++ networkDataOutputStream.writeString(queryResponse.getMotd()); ++ networkDataOutputStream.writeString("SMP"); ++ networkDataOutputStream.writeString(queryResponse.getMap()); ++ networkDataOutputStream.writeString(Integer.toString(queryResponse.getCurrentPlayers())); ++ networkDataOutputStream.writeString(Integer.toString(queryResponse.getMaxPlayers())); ++ networkDataOutputStream.writeShort((short) queryResponse.getPort()); ++ networkDataOutputStream.writeString(queryResponse.getHostname()); ++ // Paper end ++ this.sendTo(networkDataOutputStream.toByteArray(), packet); ++ LOGGER.debug("Status [{}]", (Object)socketAddress); ++ } ++ default: ++ return true; ++ case 9: ++ this.sendChallenge(packet); ++ LOGGER.debug("Challenge [{}]", (Object)socketAddress); ++ return true; + } + } else { + LOGGER.debug("Invalid packet [{}]", (Object)socketAddress); +@@ -0,0 +0,0 @@ public class QueryThreadGs4 extends GenericThread { + this.rulesResponse.writeString("splitnum"); + this.rulesResponse.write(128); + this.rulesResponse.write(0); ++ // Paper start ++ // Pack plugins ++ java.util.List plugins = java.util.Collections.emptyList(); ++ org.bukkit.plugin.Plugin[] bukkitPlugins; ++ if (((net.minecraft.server.dedicated.DedicatedServer) this.serverInterface).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.serverName) ++ .map(this.worldName) ++ .currentPlayers(this.serverInterface.getPlayerCount()) ++ .maxPlayers(this.maxPlayers) ++ .port(this.serverPort) ++ .hostname(this.hostIp) ++ .plugins(plugins) ++ .players(this.serverInterface.getPlayerNames()) ++ .gameVersion(this.serverInterface.getServerVersion()) ++ .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, packet.getAddress(), queryResponse); ++ queryEvent.callEvent(); ++ queryResponse = queryEvent.getResponse(); + this.rulesResponse.writeString("hostname"); +- this.rulesResponse.writeString(this.serverName); ++ this.rulesResponse.writeString(queryResponse.getMotd()); + this.rulesResponse.writeString("gametype"); + this.rulesResponse.writeString("SMP"); + this.rulesResponse.writeString("game_id"); + this.rulesResponse.writeString("MINECRAFT"); + this.rulesResponse.writeString("version"); +- this.rulesResponse.writeString(this.serverInterface.getServerVersion()); ++ this.rulesResponse.writeString(queryResponse.getGameVersion()); + this.rulesResponse.writeString("plugins"); +- this.rulesResponse.writeString(this.serverInterface.getPluginNames()); ++ 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.rulesResponse.writeString(pluginsString.toString()); + this.rulesResponse.writeString("map"); +- this.rulesResponse.writeString(this.worldName); ++ this.rulesResponse.writeString(queryResponse.getMap()); + this.rulesResponse.writeString("numplayers"); +- this.rulesResponse.writeString("" + this.serverInterface.getPlayerCount()); ++ this.rulesResponse.writeString(Integer.toString(queryResponse.getCurrentPlayers())); + this.rulesResponse.writeString("maxplayers"); +- this.rulesResponse.writeString("" + this.maxPlayers); ++ this.rulesResponse.writeString(Integer.toString(queryResponse.getMaxPlayers())); + this.rulesResponse.writeString("hostport"); +- this.rulesResponse.writeString("" + this.serverPort); ++ this.rulesResponse.writeString(Integer.toString(queryResponse.getPort())); + this.rulesResponse.writeString("hostip"); +- this.rulesResponse.writeString(this.hostIp); +- this.rulesResponse.write(0); +- this.rulesResponse.write(1); ++ this.rulesResponse.writeString(queryResponse.getHostname()); ++ // The "meaningless data" start, copied from above ++ this.rulesResponse.writeInt(0); ++ this.rulesResponse.writeInt(1); + this.rulesResponse.writeString("player_"); +- this.rulesResponse.write(0); +- String[] strings = this.serverInterface.getPlayerNames(); +- +- for(String string : strings) { +- this.rulesResponse.writeString(string); +- } +- +- this.rulesResponse.write(0); ++ this.rulesResponse.writeInt(0); ++ // "Meaningless data" end ++ queryResponse.getPlayers().forEach(this.rulesResponse::writeStringUnchecked); ++ this.rulesResponse.writeInt(0); ++ // Paper end + return this.rulesResponse.toByteArray(); + } + } diff --git a/patches/server/Firework-API-s.patch b/patches/server/Firework-API-s.patch new file mode 100644 index 0000000000..4fac7af404 --- /dev/null +++ b/patches/server/Firework-API-s.patch @@ -0,0 +1,97 @@ +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/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -0,0 +0,0 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + public int lifetime; + @Nullable + public LivingEntity attachedToEntity; ++ public java.util.UUID spawningEntity; // Paper + + public FireworkRocketEntity(EntityType type, Level world) { + super(type, world); +@@ -0,0 +0,0 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + } + + nbt.putBoolean("ShotAtAngle", (Boolean) this.entityData.get(FireworkRocketEntity.DATA_SHOT_AT_ANGLE)); ++ // Paper start ++ if (this.spawningEntity != null) { ++ nbt.putUUID("SpawningEntity", this.spawningEntity); ++ } ++ // Paper end + } + + @Override +@@ -0,0 +0,0 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + if (nbt.contains("ShotAtAngle")) { + this.entityData.set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, nbt.getBoolean("ShotAtAngle")); + } +- ++ // Paper start ++ if (nbt.hasUUID("SpawningEntity")) { ++ this.spawningEntity = nbt.getUUID("SpawningEntity"); ++ } ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -0,0 +0,0 @@ public class CrossbowItem extends ProjectileWeaponItem implements Vanishable { + + if (flag1) { + object = new FireworkRocketEntity(world, projectile, shooter, shooter.getX(), shooter.getEyeY() - 0.15000000596046448D, shooter.getZ(), true); ++ ((FireworkRocketEntity) object).spawningEntity = shooter.getUUID(); // Paper + } else { + object = CrossbowItem.getArrow(world, shooter, crossbow, projectile); + if (creative || simulated != 0.0F) { +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -0,0 +0,0 @@ public class FireworkRocketItem extends Item { + Vec3 vec3 = context.getClickLocation(); + Direction direction = context.getClickedFace(); + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(level, context.getPlayer(), vec3.x + (double)direction.getStepX() * 0.15D, vec3.y + (double)direction.getStepY() * 0.15D, vec3.z + (double)direction.getStepZ() * 0.15D, itemStack); ++ fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper + level.addFreshEntity(fireworkRocketEntity); + itemStack.shrink(1); + } +@@ -0,0 +0,0 @@ public class FireworkRocketItem extends Item { + ItemStack itemStack = user.getItemInHand(hand); + if (!world.isClientSide) { + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(world, itemStack, user); ++ fireworkRocketEntity.spawningEntity = user.getUUID(); // Paper + world.addFreshEntity(fireworkRocketEntity); + if (!user.getAbilities().instabuild) { + itemStack.shrink(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 @@ public class CraftFirework extends CraftProjectile implements Firework { + public void setShotAtAngle(boolean shotAtAngle) { + this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_SHOT_AT_ANGLE, shotAtAngle); + } ++ ++ // Paper start ++ @Override ++ public java.util.UUID getSpawningEntity() { ++ return getHandle().spawningEntity; ++ } ++ ++ @Override ++ public org.bukkit.entity.LivingEntity getBoostedEntity() { ++ net.minecraft.world.entity.LivingEntity boostedEntity = getHandle().attachedToEntity; ++ return boostedEntity != null ? (org.bukkit.entity.LivingEntity) boostedEntity.getBukkitEntity() : null; ++ } ++ // Paper end + } diff --git a/patches/server/Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch b/patches/server/Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch new file mode 100644 index 0000000000..c88cd68850 --- /dev/null +++ b/patches/server/Fix-AdvancementDataPlayer-leak-due-from-quitting-ear.patch @@ -0,0 +1,82 @@ +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/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java ++++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +@@ -0,0 +0,0 @@ import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.level.storage.loot.LootContext; + + public abstract class SimpleCriterionTrigger implements CriterionTrigger { +- private final Map>> players = Maps.newIdentityHashMap(); ++ //private final Map>> players = Maps.newIdentityHashMap(); // Paper - moved into AdvancementDataPlayer to fix memory leak ++ ++ public SimpleCriterionTrigger() {} + + @Override + public final void addPlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener conditions) { +- this.players.computeIfAbsent(manager, (managerx) -> { ++ manager.criterionData.computeIfAbsent(this, (managerx) -> { // Paper - fix AdvancementDataPlayer leak + return Sets.newHashSet(); + }).add(conditions); + } + + @Override + public final void removePlayerListener(PlayerAdvancements manager, CriterionTrigger.Listener conditions) { +- Set> set = this.players.get(manager); ++ Set> set = (Set) manager.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + if (set != null) { + set.remove(conditions); + if (set.isEmpty()) { +- this.players.remove(manager); ++ manager.criterionData.remove(this); // Paper - fix AdvancementDataPlayer leak + } + } + +@@ -0,0 +0,0 @@ public abstract class SimpleCriterionTrigger tester) { + PlayerAdvancements playerAdvancements = player.getAdvancements(); +- Set> set = this.players.get(playerAdvancements); ++ Set> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak + if (set != null && !set.isEmpty()) { + LootContext lootContext = EntityPredicate.createContext(player, player); + List> list = null; +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -0,0 +0,0 @@ import net.minecraft.advancements.Criterion; + import net.minecraft.advancements.CriterionProgress; + import net.minecraft.advancements.CriterionTrigger; + import net.minecraft.advancements.CriterionTriggerInstance; ++import net.minecraft.advancements.critereon.SimpleCriterionTrigger; + import net.minecraft.network.chat.ChatType; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundSelectAdvancementsTabPacket; +@@ -0,0 +0,0 @@ public class PlayerAdvancements { + private Advancement lastSelectedTab; + private boolean isFirstPacket = true; + ++ public final Map> criterionData = Maps.newIdentityHashMap(); // Paper - fix advancement data player leakage ++ + public PlayerAdvancements(DataFixer dataFixer, PlayerList playerManager, ServerAdvancementManager advancementLoader, File advancementFile, ServerPlayer owner) { + this.dataFixer = dataFixer; + this.playerList = playerManager; diff --git a/patches/server/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch new file mode 100644 index 0000000000..e9d858bd55 --- /dev/null +++ b/patches/server/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -0,0 +1,23 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 + return; + } ++ // Paper start ++ itemstack = this.player.getItemInHand(enumhand); ++ if (itemstack.isEmpty()) return; ++ // Paper end + InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); + + if (enuminteractionresult.shouldSwing()) { diff --git a/patches/server/Fix-CB-call-to-changed-postToMainThread-method.patch b/patches/server/Fix-CB-call-to-changed-postToMainThread-method.patch new file mode 100644 index 0000000000..5bf339f32c --- /dev/null +++ b/patches/server/Fix-CB-call-to-changed-postToMainThread-method.patch @@ -0,0 +1,19 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + Objects.requireNonNull(this.connection); + // CraftBukkit - Don't wait +- minecraftserver.wrapRunnable(networkmanager::handleDisconnection); ++ minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper + } + + private void filterTextPacket(T text, Consumer consumer, BiFunction> backingFilterer) { diff --git a/Spigot-Server-Patches/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch b/patches/server/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch similarity index 56% rename from Spigot-Server-Patches/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch rename to patches/server/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch index fdf6f5072d..d7d429bcf0 100644 --- a/Spigot-Server-Patches/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch +++ b/patches/server/Fix-CME-on-adding-a-passenger-in-CreatureSpawnEvent.patch @@ -8,12 +8,12 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - 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 + private Stream getIndirectPassengersStream() { +- return this.passengers.stream().flatMap(Entity::getSelfAndPassengers); ++ return ImmutableList.copyOf(this.passengers).stream().flatMap(Entity::getSelfAndPassengers); // Paper } - public boolean hasSinglePlayerPassenger() { + @Override diff --git a/patches/server/Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/patches/server/Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch new file mode 100644 index 0000000000..eccc29fc0e --- /dev/null +++ b/patches/server/Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch @@ -0,0 +1,18 @@ +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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public void setBlocksDirty(BlockPos pos, BlockState old, BlockState updated) {} + + public void updateNeighborsAt(BlockPos pos, Block block) { ++ if (captureBlockStates) { return; } // Paper - Cancel all physics during placement + this.neighborChanged(pos.west(), block, pos); + this.neighborChanged(pos.east(), block, pos); + this.neighborChanged(pos.below(), block, pos); diff --git a/Spigot-Server-Patches/Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/Fix-Chunk-Post-Processing-deadlock-risk.patch similarity index 52% rename from Spigot-Server-Patches/Fix-Chunk-Post-Processing-deadlock-risk.patch rename to patches/server/Fix-Chunk-Post-Processing-deadlock-risk.patch index d2e39d5cbc..5d0905388f 100644 --- a/Spigot-Server-Patches/Fix-Chunk-Post-Processing-deadlock-risk.patch +++ b/patches/server/Fix-Chunk-Post-Processing-deadlock-risk.patch @@ -24,37 +24,36 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 { +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider }; // 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 { + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); + // Paper start - no-tick view distance +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider 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. +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, () -> ChunkMap.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/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + return super.pollTask() || execChunkTask; // Paper + } + } finally { ++ chunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter + chunkMap.callbackExecutor.run(); + } + // CraftBukkit end diff --git a/patches/server/Fix-Concurrency-issue-in-WeightedList.patch b/patches/server/Fix-Concurrency-issue-in-WeightedList.patch new file mode 100644 index 0000000000..8727b94f66 --- /dev/null +++ b/patches/server/Fix-Concurrency-issue-in-WeightedList.patch @@ -0,0 +1,69 @@ +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/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +@@ -0,0 +0,0 @@ public class GateBehavior extends Behavior { + private final Set> exitErasedMemories; + private final GateBehavior.OrderPolicy orderPolicy; + private final GateBehavior.RunningPolicy runningPolicy; +- private final ShufflingList> behaviors = new ShufflingList<>(); ++ private final ShufflingList> behaviors = new ShufflingList<>(false); // Paper - don't use a clone + + public GateBehavior(Map, MemoryStatus> requiredMemoryState, Set> memoriesToForgetWhenStopped, GateBehavior.OrderPolicy order, GateBehavior.RunningPolicy runMode, List, Integer>> tasks) { + super(requiredMemoryState); +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java +@@ -0,0 +0,0 @@ import java.util.stream.Stream; + public class ShufflingList { + protected final List> entries; + private final Random random = new Random(); ++ private final boolean isUnsafe; // Paper + + public ShufflingList() { ++ // Paper start ++ this(true); ++ } ++ public ShufflingList(boolean isUnsafe) { ++ this.isUnsafe = isUnsafe; ++ // Paper end + this.entries = Lists.newArrayList(); + } + + private ShufflingList(List> list) { ++ // Paper start ++ this(list, true); ++ } ++ private ShufflingList(List> list, boolean isUnsafe) { ++ this.isUnsafe = isUnsafe; ++ // Paper end + this.entries = Lists.newArrayList(list); + } + +@@ -0,0 +0,0 @@ public class ShufflingList { + } + + public ShufflingList shuffle() { +- this.entries.forEach((entry) -> { +- entry.setRandom(this.random.nextFloat()); +- }); +- this.entries.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight)); +- return this; ++ // Paper start - make concurrent safe, work off a clone of the list ++ List> list = this.isUnsafe ? Lists.newArrayList(this.entries) : this.entries; ++ list.forEach(entry -> entry.setRandom(this.random.nextFloat())); ++ list.sort(Comparator.comparingDouble(ShufflingList.WeightedEntry::getRandWeight)); ++ return this.isUnsafe ? new ShufflingList<>(list, this.isUnsafe) : this; ++ // Paper end + } + + public Stream stream() { diff --git a/Spigot-Server-Patches/Fix-CraftEntity-hashCode.patch b/patches/server/Fix-CraftEntity-hashCode.patch similarity index 100% rename from Spigot-Server-Patches/Fix-CraftEntity-hashCode.patch rename to patches/server/Fix-CraftEntity-hashCode.patch diff --git a/Spigot-Server-Patches/Fix-CraftPotionBrewer-cache.patch b/patches/server/Fix-CraftPotionBrewer-cache.patch similarity index 69% rename from Spigot-Server-Patches/Fix-CraftPotionBrewer-cache.patch rename to patches/server/Fix-CraftPotionBrewer-cache.patch index 992a2bfb05..6dc8d06ff2 100644 --- a/Spigot-Server-Patches/Fix-CraftPotionBrewer-cache.patch +++ b/patches/server/Fix-CraftPotionBrewer-cache.patch @@ -17,28 +17,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Collection getEffects(PotionType damage, boolean upgraded, boolean extended) { -- if (cache.containsKey(damage)) -- return cache.get(damage); +- if (CraftPotionBrewer.cache.containsKey(damage)) +- return CraftPotionBrewer.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); ++ if (CraftPotionBrewer.cache.containsKey(key)) ++ return CraftPotionBrewer.cache.get(key); + // Paper end - List mcEffects = PotionRegistry.a(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).a(); + List mcEffects = Potion.byName(CraftPotionUtil.fromBukkit(new PotionData(damage, extended, upgraded))).getEffects(); @@ -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 +- CraftPotionBrewer.cache.put(damage, builder.build()); ++ CraftPotionBrewer.cache.put(key, builder.build()); // Paper -- return cache.get(damage); -+ return cache.get(key); // Paper +- return CraftPotionBrewer.cache.get(damage); ++ return CraftPotionBrewer.cache.get(key); // Paper } @Override diff --git a/Spigot-Server-Patches/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch b/patches/server/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch similarity index 84% rename from Spigot-Server-Patches/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch rename to patches/server/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch index 5c269af548..5bbcd4069f 100644 --- a/Spigot-Server-Patches/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch +++ b/patches/server/Fix-CraftScheduler-runTaskTimerAsynchronously-Plugin.patch @@ -14,8 +14,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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); +- this.runTaskTimerAsynchronously(plugin, (Object) task, delay, CraftTask.NO_REPEATING); ++ this.runTaskTimerAsynchronously(plugin, (Object) task, delay, period); } @Override diff --git a/Spigot-Server-Patches/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch b/patches/server/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch similarity index 83% rename from Spigot-Server-Patches/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch rename to patches/server/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch index dad391c30d..5f90d1d0b7 100644 --- a/Spigot-Server-Patches/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch +++ b/patches/server/Fix-CraftServer-isPrimaryThread-and-MinecraftServer-.patch @@ -19,12 +19,12 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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 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<>(); ++ 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); + for (int j = 0; j < inventory.getContainerSize(); ++j) { + ItemStack itemstack = inventory.getItem(j); if (!itemstack.isEmpty()) { - ++i; -- autorecipestackmanager.a(itemstack, 1); +- autorecipestackmanager.accountStack(itemstack, 1); + // Paper start -+ itemstack = itemstack.cloneItemStack(); ++ itemstack = itemstack.copy(); + providedItems.add(itemstack); -+ for (RecipeItemStack ingredient : ingredients) { ++ for (Ingredient ingredient : ingredients) { + if (ingredient.test(itemstack)) { + matchedProvided.increment(itemstack); + matchedIngredients.increment(ingredient); @@ -41,19 +41,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null); +- return i == this.ingredients.size() && autorecipestackmanager.canCraft(this, (IntList) null); + // Paper start + if (matchedProvided.isEmpty() || matchedIngredients.isEmpty()) { + return false; + } -+ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); ++ 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))); ++ ingredients.sort(java.util.Comparator.comparingInt((Ingredient c) -> (int) matchedIngredients.getCount(c))); + + PROVIDED: + for (ItemStack provided : providedItems) { -+ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { -+ RecipeItemStack ingredient = itIngredient.next(); ++ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { ++ Ingredient ingredient = itIngredient.next(); + if (ingredient.test(provided)) { + itIngredient.remove(); + continue PROVIDED; @@ -65,4 +65,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end } - public ItemStack a(InventoryCrafting inventorycrafting) { + public ItemStack assemble(CraftingContainer inventory) { diff --git a/patches/server/Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch b/patches/server/Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch new file mode 100644 index 0000000000..0c7be35d3b --- /dev/null +++ b/patches/server/Fix-Entity-Teleportation-and-cancel-velocity-if-tele.patch @@ -0,0 +1,83 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (packet.getId() == this.awaitingTeleport && this.awaitingPositionFromClient != null) { // CraftBukkit +- this.player.absMoveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); ++ this.player.moveTo(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); // Paper - use proper setPositionRotation for teleportation + this.lastGoodX = this.awaitingPositionFromClient.x; + this.lastGoodY = this.awaitingPositionFromClient.y; + this.lastGoodZ = this.awaitingPositionFromClient.z; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // CraftBukkit end + + this.awaitingTeleportTime = this.tickCount; +- this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.player.moveTo(d0, d1, d2, f, f1); // Paper - use proper setPositionRotation for teleportation + this.player.forceCheckHighPriority(); // Paper + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag)); + } +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 Nameable, EntityAccess, CommandSource, n + + // CraftBukkit start + private static final int CURRENT_LEVEL = 2; ++ public boolean preserveMotion = true; // Paper - keep initial motion on first setPositionRotation + static boolean isLevelAtLeast(CompoundTag tag, int level) { + return tag.contains("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; + } +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + + public void moveTo(double x, double y, double z, float yaw, float pitch) { ++ // Paper - cancel entity velocity if teleported ++ if (!preserveMotion) { ++ this.deltaMovement = Vec3.ZERO; ++ } else { ++ this.preserveMotion = false; ++ } ++ // Paper end + this.setPosRaw(x, y, z); + this.setYRot(yaw); + this.setXRot(pitch); +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + return; + } + ++ entity.preserveMotion = true; // Paper - preserve entity motion from tag + entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), world.random.nextFloat() * 360.0F, 0.0F); + if (entity instanceof Mob) { + Mob entityinsentient = (Mob) 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 +- this.entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); ++ entity.moveTo(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 + this.entity.setYHeadRot(location.getYaw()); + diff --git a/patches/server/Fix-Light-Command.patch b/patches/server/Fix-Light-Command.patch new file mode 100644 index 0000000000..ab5c6074fc --- /dev/null +++ b/patches/server/Fix-Light-Command.patch @@ -0,0 +1,166 @@ +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 net.minecraft.server.MinecraftServer; + import net.minecraft.server.level.ChunkHolder; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; +-import net.minecraft.world.entity.Entity; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.server.level.ThreadedLevelLightEngine; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.resources.ResourceLocation; +@@ -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; + 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").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight").build(); + + public PaperCommand(String name) { + super(name); +@@ -0,0 +0,0 @@ public class PaperCommand extends Command { + case "chunkinfo": + doChunkInfo(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 { + + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); + } ++ 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; ++ ServerPlayer handle = player.getHandle(); ++ ServerLevel world = (ServerLevel) handle.level; ++ ThreadedLevelLightEngine lightengine = world.getChunkSource().getLightEngine(); ++ ++ net.minecraft.core.BlockPos center = MCUtil.toBlockPosition(player.getLocation()); ++ Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); ++ updateLight(sender, world, lightengine, queue); ++ } ++ ++ private void updateLight(CommandSender sender, ServerLevel world, ThreadedLevelLightEngine lightengine, Deque queue) { ++ ChunkPos coord = queue.poll(); ++ if (coord == null) { ++ sender.sendMessage("All Chunks Light updated"); ++ return; ++ } ++ world.getChunkSource().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; ++ } ++ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); ++ if (chunk == null) { ++ updateLight(sender, world, lightengine, queue); ++ return; ++ } ++ lightengine.setTaskPerBatch(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++) { ++ net.minecraft.core.BlockPos pos = new net.minecraft.core.BlockPos(cx + x, y, cz + z); ++ lightengine.checkBlock(pos); ++ } ++ } ++ } ++ lightengine.tryScheduleUpdate(); ++ ChunkHolder visibleChunk = world.getChunkSource().chunkMap.getVisibleChunkIfPresent(chunk.coordinateKey); ++ if (visibleChunk != null) { ++ world.getChunkSource().chunkMap.addLightTask(visibleChunk, () -> { ++ MinecraftServer.getServer().processQueue.add(() -> { ++ visibleChunk.broadcast(new net.minecraft.network.protocol.game.ClientboundLightUpdatePacket(chunk.getPos(), lightengine, null, null, true), false); ++ updateLight(sender, world, lightengine, queue); ++ }); ++ }); ++ } else { ++ updateLight(sender, world, lightengine, queue); ++ } ++ lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize); ++ }, MinecraftServer.getServer()); ++ } + } +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; + private final ProcessorHandle> mainThreadMailbox; ++ // Paper start ++ final ProcessorHandle> mailboxLight; ++ public void addLightTask(ChunkHolder playerchunk, Runnable run) { ++ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); ++ } ++ // Paper end + public final ChunkProgressListener progressListener; + private final ChunkStatusUpdateListener chunkStatusListener; + public final ChunkMap.ChunkDistanceManager distanceManager; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + this.progressListener = worldGenerationProgressListener; + this.chunkStatusListener = chunkStatusChangeListener; +- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(executor, "light"); ++ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(executor, "light"); // Paper + + this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); + this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); + this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); ++ this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); + this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); + this.overworldDataStorage = persistentStateManagerFactory; diff --git a/Spigot-Server-Patches/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch b/patches/server/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch similarity index 50% rename from Spigot-Server-Patches/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch rename to patches/server/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch index 2b9771e2e0..a5a6926557 100644 --- a/Spigot-Server-Patches/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch +++ b/patches/server/Fix-Longstanding-Broken-behavior-of-PlayerJoinEvent.patch @@ -27,11 +27,23 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 { +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + .printStackTrace(); + return; + } ++ if (entity instanceof ServerPlayer && ((ServerPlayer) entity).supressTrackerForLogin) return; // Delay adding to tracker until after list packets + // Paper end + if (!(entity instanceof EnderDragonPart)) { + EntityType entitytypes = entity.getType(); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { public double maxHealthCache; public boolean joining = true; public boolean sentListPacket = false; @@ -39,64 +51,43 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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.playersByUUID.put(player.getUUID(), player); // 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); ++ player.supressTrackerForLogin = true; ++ worldserver1.addNewPlayer(player); ++ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below worldserver.addPlayerJoin(entityplayer); ++ mountSavedVehicle(player, 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); + PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(this.cserver.getPlayer(player), PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure + this.cserver.getPluginManager().callEvent(playerJoinEvent); @@ -0,0 +0,0 @@ public abstract class PlayerList { - entityplayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, new EntityPlayer[] { entityplayer1})); + player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, new ServerPlayer[] { entityplayer1})); } - entityplayer.sentListPacket = true; -+ entityplayer.supressTrackerForLogin = false; // Paper -+ ((WorldServer)entityplayer.world).getChunkProvider().playerChunkMap.addEntity(entityplayer); // Paper - track entity now + player.sentListPacket = true; ++ player.supressTrackerForLogin = false; // Paper ++ ((ServerLevel)player.level).getChunkSource().chunkMap.addEntity(player); // 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 + player.connection.send(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), 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)); + playerconnection.send(new ClientboundUpdateMobEffectPacket(player.getId(), mobeffect)); } + // Paper start - move vehicle into method so it can be called above - short circuit around that code -+ onPlayerJoinFinish(entityplayer, worldserver1, s1); ++ onPlayerJoinFinish(player, worldserver1, s1); + } -+ private void mountSavedVehicle(EntityPlayer entityplayer, WorldServer worldserver1, NBTTagCompound nbttagcompound) { ++ private void mountSavedVehicle(ServerPlayer player, ServerLevel worldserver1, CompoundTag nbttagcompound) { + // Paper end - if (nbttagcompound != null && nbttagcompound.hasKeyOfType("RootVehicle", 10)) { - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); + if (nbttagcompound != null && nbttagcompound.contains("RootVehicle", 10)) { + CompoundTag nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); // CraftBukkit start @@ -0,0 +0,0 @@ public abstract class PlayerList { } @@ -104,8 +95,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + } -+ public void onPlayerJoinFinish(EntityPlayer entityplayer, WorldServer worldserver1, String s1) { ++ public void onPlayerJoinFinish(ServerPlayer player, ServerLevel worldserver1, String s1) { + // Paper end - entityplayer.syncInventory(); + player.initInventoryMenu(); + // CraftBukkit - Moved from above, added world // Paper start - Add to collideRule team if needed - final Scoreboard scoreboard = this.getServer().getWorldServer(World.OVERWORLD).getScoreboard(); +@@ -0,0 +0,0 @@ public abstract class PlayerList { + scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); + } + // Paper end ++ // CraftBukkit - Moved from above, added world + PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), s1, player.getId(), worldserver1.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ()); + } + diff --git a/patches/server/Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server/Fix-MC-117075-TE-Unload-Lag-Spike.patch new file mode 100644 index 0000000000..215029b650 --- /dev/null +++ b/patches/server/Fix-MC-117075-TE-Unload-Lag-Spike.patch @@ -0,0 +1,42 @@ +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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Spigot start + // Iterator iterator = this.blockEntityTickers.iterator(); + int tilesThisCycle = 0; ++ var toRemove = new it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet(net.minecraft.Util.identityStrategy()); // Paper - use removeAll ++ toRemove.add(null); + for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters + this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0; + TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(tileTickPosition); +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (tickingblockentity == null) { + this.getCraftServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash"); + tilesThisCycle--; +- this.blockEntityTickers.remove(this.tileTickPosition--); + continue; + } + // Spigot end +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (tickingblockentity.isRemoved()) { + // Spigot start + tilesThisCycle--; +- this.blockEntityTickers.remove(this.tileTickPosition--); ++ toRemove.add(tickingblockentity); // Paper - use removeAll + // Spigot end + } else { + tickingblockentity.tick(); + } + } ++ this.blockEntityTickers.removeAll(toRemove); + + timings.tileEntityTick.stopTiming(); // Spigot + this.tickingBlockEntities = false; diff --git a/Spigot-Server-Patches/Fix-MC-158900.patch b/patches/server/Fix-MC-158900.patch similarity index 63% rename from Spigot-Server-Patches/Fix-MC-158900.patch rename to patches/server/Fix-MC-158900.patch index 3fa552211c..20f82d1173 100644 --- a/Spigot-Server-Patches/Fix-MC-158900.patch +++ b/patches/server/Fix-MC-158900.patch @@ -12,14 +12,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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()); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); -- if (getProfileBans().isBanned(gameprofile) && !getProfileBans().get(gameprofile).hasExpired()) { -- GameProfileBanEntry gameprofilebanentry = (GameProfileBanEntry) this.k.get(gameprofile); +- if (this.getBans().isBanned(gameprofile) && !this.getBans().get(gameprofile).hasExpired()) { +- UserBanListEntry gameprofilebanentry = (UserBanListEntry) this.bans.get(gameprofile); + // Paper start - Fix MC-158900 -+ GameProfileBanEntry gameprofilebanentry; -+ if (getProfileBans().isBanned(gameprofile) && (gameprofilebanentry = getProfileBans().get(gameprofile)) != null) { ++ UserBanListEntry gameprofilebanentry; ++ if (getBans().isBanned(gameprofile) && (gameprofilebanentry = getBans().get(gameprofile)) != null) { + // Paper end - chatmessage = new ChatMessage("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); + chatmessage = new TranslatableComponent("multiplayer.disconnect.banned.reason", new Object[]{gameprofilebanentry.getReason()}); if (gameprofilebanentry.getExpires() != null) { diff --git a/patches/server/Fix-MC-161754.patch b/patches/server/Fix-MC-161754.patch new file mode 100644 index 0000000000..aa5fb94774 --- /dev/null +++ b/patches/server/Fix-MC-161754.patch @@ -0,0 +1,23 @@ +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/HorseInventoryMenu.java b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/HorseInventoryMenu.java +@@ -0,0 +0,0 @@ public class HorseInventoryMenu extends AbstractContainerMenu { + + @Override + public boolean stillValid(Player player) { +- return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; ++ return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 + } + + private boolean hasChest(AbstractHorse entityhorseabstract) { diff --git a/patches/server/Fix-MC-187716-Use-configured-height.patch b/patches/server/Fix-MC-187716-Use-configured-height.patch new file mode 100644 index 0000000000..bae9244160 --- /dev/null +++ b/patches/server/Fix-MC-187716-Use-configured-height.patch @@ -0,0 +1,50 @@ +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/NetherCappedSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherCappedSurfaceBuilder.java +@@ -0,0 +0,0 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder= i; --p) { ++ for(int p = height; p >= i; --p) { // Paper - fix MC-187716 - use configured height + mutableBlockPos.set(k, p, m); + BlockState blockState4 = chunk.getBlockState(mutableBlockPos); + if (blockState3.is(defaultBlock.getBlock()) && (blockState4.isAir() || blockState4 == defaultFluid)) { +@@ -0,0 +0,0 @@ public abstract class NetherCappedSurfaceBuilder extends SurfaceBuilder= i; --p) { ++ for(int p = height; p >= i; --p) { // Paper - fix MC-187716 - use configured height + mutableBlockPos.set(k, p, m); + BlockState blockState2 = surfaceBuilderBaseConfiguration.getTopMaterial(); + BlockState blockState3 = chunk.getBlockState(mutableBlockPos); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/surfacebuilders/NetherSurfaceBuilder.java +@@ -0,0 +0,0 @@ public class NetherSurfaceBuilder extends SurfaceBuilder= i; --p) { ++ for(int p = height; p >= i; --p) { // Paper - fix MC-187716 - use configured height + mutableBlockPos.set(k, p, m); + BlockState blockState3 = chunk.getBlockState(mutableBlockPos); + if (blockState3.isAir()) { diff --git a/patches/server/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch new file mode 100644 index 0000000000..e4009f1419 --- /dev/null +++ b/patches/server/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch @@ -0,0 +1,99 @@ +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/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.LongArrayTag; + import net.minecraft.nbt.ShortTag; ++import net.minecraft.nbt.Tag; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ThreadedLevelLightEngine; +@@ -0,0 +0,0 @@ public class ChunkSerializer { + object2 = protochunkticklist1; + } + +- object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, k, achunksection, (chunk) -> { +- ChunkSerializer.postLoadChunk(world, nbttagcompound1, chunk); +- // CraftBukkit start - load chunk persistent data from nbt +- net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); +- if (persistentBase instanceof CompoundTag) { +- chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); +- } +- // CraftBukkit end +- }); ++ object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, k, 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(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level + +@@ -0,0 +0,0 @@ public class ChunkSerializer { + 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 CompoundTag { ++ private final java.util.Set keys = new java.util.HashSet(); ++ public SafeNBTCopy(CompoundTag base, String... keys) { ++ for (String key : keys) { ++ this.keys.add(key); ++ final Tag nbtBase = base.get(key); ++ if (nbtBase != null) { ++ this.put(key, nbtBase); ++ } ++ } ++ } ++ ++ @Override ++ public boolean contains(String key) { ++ if (super.contains(key)) { ++ return true; ++ } else if (keys.contains(key)) { ++ return false; ++ } ++ throw new IllegalStateException("Missing Key " + key + " in SafeNBTCopy"); ++ } ++ ++ @Override ++ public boolean contains(String key, int type) { ++ return contains(key) && super.contains(key, type); ++ } ++ } ++ private static java.util.function.Consumer createLoadEntitiesConsumer(CompoundTag nbt) { ++ return (chunk) -> { ++ postLoadChunk(chunk.level, nbt, chunk); ++ // CraftBukkit start - load chunk persistent data from nbt ++ Tag persistentBase = nbt.get("ChunkBukkitValues"); ++ if (persistentBase instanceof CompoundTag) { ++ chunk.persistentDataContainer.putAll((CompoundTag) persistentBase); ++ } ++ // CraftBukkit end ++ }; ++ } ++ // Paper end + + // Paper start - async chunk save for unload + public static final class AsyncSaveData { diff --git a/patches/server/Fix-Not-a-string-Map-Conversion-spam.patch b/patches/server/Fix-Not-a-string-Map-Conversion-spam.patch new file mode 100644 index 0000000000..dddea1b07f --- /dev/null +++ b/patches/server/Fix-Not-a-string-Map-Conversion-spam.patch @@ -0,0 +1,54 @@ +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. + +Track spigot issue to see when fixed: https://hub.spigotmc.org/jira/browse/SPIGOT-6181 + +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.NumericTag; ++import net.minecraft.nbt.StringTag; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.Packet; +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { + } + + public static MapItemSavedData load(CompoundTag nbt) { +- DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbt.get("dimension"))); ++ // Paper start - fix "Not a string" spam ++ Tag dimension = nbt.get("dimension"); ++ if (dimension instanceof NumericTag && ((NumericTag) dimension).getAsInt() >= CraftWorld.CUSTOM_DIMENSION_OFFSET) { ++ long least = nbt.getLong("UUIDLeast"); ++ long most = nbt.getLong("UUIDMost"); ++ ++ if (least != 0L && most != 0L) { ++ UUID uuid = new UUID(most, least); ++ CraftWorld world = (CraftWorld) Bukkit.getWorld(uuid); ++ if (world != null) { ++ dimension = StringTag.valueOf("minecraft:" + world.getName().toLowerCase(java.util.Locale.ENGLISH)); ++ } else { ++ dimension = StringTag.valueOf("bukkit:_invalidworld_"); ++ } ++ } else { ++ dimension = StringTag.valueOf("bukkit:_invalidworld_"); ++ } ++ } ++ DataResult> dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, dimension)); // CraftBukkit - decompile error ++ // Paper end - fix "Not a string" spam + Logger logger = MapItemSavedData.LOGGER; + + Objects.requireNonNull(logger); diff --git a/patches/server/Fix-Old-Sign-Conversion.patch b/patches/server/Fix-Old-Sign-Conversion.patch new file mode 100644 index 0000000000..522623fbbe --- /dev/null +++ b/patches/server/Fix-Old-Sign-Conversion.patch @@ -0,0 +1,49 @@ +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/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + public CraftPersistentDataContainer persistentDataContainer; + // CraftBukkit end + private static final Logger LOGGER = LogManager.getLogger(); ++ public boolean isLoadingStructure = false; // Paper + private final BlockEntityType type; + @Nullable + protected Level level; +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java +@@ -0,0 +0,0 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C + s = "\"\""; + } + +- if (oldSign) { ++ if (oldSign && !this.isLoadingStructure) { // Paper - saved structures will be in the new format, but will not have isConverted + this.messages[i] = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(s)[0]; + continue; + } +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java +@@ -0,0 +0,0 @@ public class StructureTemplate { + definedstructure_blockinfo.nbt.putLong("LootTableSeed", random.nextLong()); + } + ++ tileentity.isLoadingStructure = true; // Paper + tileentity.load(definedstructure_blockinfo.nbt); ++ tileentity.isLoadingStructure = false; // Paper + } + } + diff --git a/patches/server/Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/Fix-Per-World-Difficulty-Remembering-Difficulty.patch new file mode 100644 index 0000000000..b4a7117522 --- /dev/null +++ b/patches/server/Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -0,0 +1,77 @@ +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 ReentrantBlockableEventLoop +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/BucketItem.java b/src/main/java/net/minecraft/world/item/BucketItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/BucketItem.java ++++ b/src/main/java/net/minecraft/world/item/BucketItem.java +@@ -0,0 +0,0 @@ import org.bukkit.event.player.PlayerBucketFillEvent; + + public class BucketItem extends Item implements DispensibleContainerItem { + ++ private static ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper ++ + public final Fluid content; + + public BucketItem(Fluid fluid, Item.Properties settings) { +@@ -0,0 +0,0 @@ public class BucketItem extends Item implements DispensibleContainerItem { + } + + public static ItemStack getEmptySuccessItem(ItemStack stack, Player player) { ++ // Paper start ++ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) { ++ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent; ++ itemLeftInHandAfterPlayerBucketEmptyEvent = null; ++ return itemInHand; ++ } ++ // Paper end + return !player.getAbilities().instabuild ? new ItemStack(Items.BUCKET) : stack; + } + +@@ -0,0 +0,0 @@ public class BucketItem extends Item implements DispensibleContainerItem { + ((ServerPlayer) 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/patches/server/Fix-PlayerItemConsumeEvent-cancelling-properly.patch similarity index 51% rename from Spigot-Server-Patches/Fix-PlayerItemConsumeEvent-cancelling-properly.patch rename to patches/server/Fix-PlayerItemConsumeEvent-cancelling-properly.patch index 18910e1d39..e7beb44886 100644 --- a/Spigot-Server-Patches/Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ b/patches/server/Fix-PlayerItemConsumeEvent-cancelling-properly.patch @@ -8,15 +8,15 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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); +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { -+ this.clearActiveItem(); // Paper - event is using an item, clear active item to reset its use ++ this.stopUsingItem(); // Paper - event is using an item, clear active item to reset its use // Update client - ((EntityPlayer) this).getBukkitEntity().updateInventory(); - ((EntityPlayer) this).getBukkitEntity().updateScaledHealth(); + ((ServerPlayer) this).getBukkitEntity().updateInventory(); + ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); diff --git a/Spigot-Server-Patches/Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/Fix-PotionEffect-ignores-icon-flag.patch similarity index 61% rename from Spigot-Server-Patches/Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server/Fix-PotionEffect-ignores-icon-flag.patch index 22b56184fa..175faa193d 100644 --- a/Spigot-Server-Patches/Fix-PotionEffect-ignores-icon-flag.patch +++ b/patches/server/Fix-PotionEffect-ignores-icon-flag.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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 +- this.getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); ++ this.getHandle().addEffect(new MobEffectInstance(MobEffect.byId(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/patches/server/Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/Fix-PotionSplashEvent-for-water-splash-potions.patch new file mode 100644 index 0000000000..88b9363181 --- /dev/null +++ b/patches/server/Fix-PotionSplashEvent-for-water-splash-potions.patch @@ -0,0 +1,52 @@ +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/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie + private void applyWater() { + AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); + List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE); ++ Map affected = new HashMap<>(); // Paper + + if (!list.isEmpty()) { + Iterator iterator = list.iterator(); +@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie + double d0 = this.distanceToSqr(entityliving); + + if (d0 < 16.0D && entityliving.isSensitiveToWater()) { +- entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 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()) { ++ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); ++ entityliving.hurt(DamageSource.indirectMagic(entityliving, this.getOwner()), 1.0F); ++ } ++ } ++ // Paper end ++ + List list1 = this.level.getEntitiesOfClass(Axolotl.class, axisalignedbb); + Iterator iterator1 = list1.iterator(); + +@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie + double d0 = this.distanceToSqr(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/patches/server/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch similarity index 73% rename from Spigot-Server-Patches/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch rename to patches/server/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch index bef3ff597c..5821fea817 100644 --- a/Spigot-Server-Patches/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch +++ b/patches/server/Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch @@ -26,8 +26,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +- GameProfileCache usercache = new GameProfileCache(gameprofilerepository, new File(file, MinecraftServer.USERID_CACHE_FILE.getName())); ++ GameProfileCache usercache = new GameProfileCache(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()); + String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); + LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); diff --git a/Spigot-Server-Patches/Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/Fix-SPIGOT-5885-Unable-to-disable-advancements.patch similarity index 100% rename from Spigot-Server-Patches/Fix-SPIGOT-5885-Unable-to-disable-advancements.patch rename to patches/server/Fix-SPIGOT-5885-Unable-to-disable-advancements.patch diff --git a/Spigot-Server-Patches/Fix-SPIGOT-5989.patch b/patches/server/Fix-SPIGOT-5989.patch similarity index 62% rename from Spigot-Server-Patches/Fix-SPIGOT-5989.patch rename to patches/server/Fix-SPIGOT-5989.patch index 08e39e54ad..e6bc6385cc 100644 --- a/Spigot-Server-Patches/Fix-SPIGOT-5989.patch +++ b/patches/server/Fix-SPIGOT-5989.patch @@ -13,14 +13,14 @@ diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/ma 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; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; 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; ++import net.minecraft.world.level.block.RespawnAnchorBlock; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.border.BorderChangeListener; + import net.minecraft.world.level.border.WorldBorder; @@ -0,0 +0,0 @@ public abstract class PlayerList { // Paper start boolean isBedSpawn = false; @@ -33,8 +33,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +- optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, flag); ++ optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(worldserver1, blockposition, f, flag1, true); // Paper - Fix SPIGOT-5989 } else { optional = Optional.empty(); } @@ -57,13 +57,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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)); +- entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.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)); ++ BlockState data = worldserver1.getBlockState(blockposition); ++ worldserver1.setBlock(blockposition, data.setValue(RespawnAnchorBlock.CHARGE, data.getValue(RespawnAnchorBlock.CHARGE) - 1), 3); ++ entityplayer1.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) location.getX(), (double) location.getY(), (double) location.getZ(), 1.0F, 1.0F)); + // Paper end } // Added from changeDimension - updateClient(entityplayer); // Update health, etc... + this.sendAllPlayerInfo(entityplayer); // Update health, etc... diff --git a/Spigot-Server-Patches/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch b/patches/server/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch similarity index 63% rename from Spigot-Server-Patches/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch rename to patches/server/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch index 0b95d61e3a..37d56dfc09 100644 --- a/Spigot-Server-Patches/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch +++ b/patches/server/Fix-SpawnChangeEvent-not-firing-for-all-use-cases.patch @@ -4,21 +4,14 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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(); +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl //ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(new BlockPosition(this.worldData.a(), 0, this.worldData.c())); - this.worldData.setSpawn(blockposition, f); + this.levelData.setSpawn(pos, angle); + 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 @@ -30,14 +23,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 + Location previousLocation = this.getSpawnLocation(); +- world.levelData.setSpawn(new BlockPos(x, y, z), angle); ++ world.setDefaultSpawnPos(new BlockPos(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); +- this.server.getPluginManager().callEvent(event); + // SpawnChangeEvent event = new SpawnChangeEvent(this, previousLocation); + // server.getPluginManager().callEvent(event); + // Paper end diff --git a/patches/server/Fix-SpongeAbsortEvent-handling.patch b/patches/server/Fix-SpongeAbsortEvent-handling.patch new file mode 100644 index 0000000000..75ca22f6a8 --- /dev/null +++ b/patches/server/Fix-SpongeAbsortEvent-handling.patch @@ -0,0 +1,25 @@ +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/SpongeBlock.java b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/SpongeBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SpongeBlock.java +@@ -0,0 +0,0 @@ public class SpongeBlock extends Block { + // NOP + } else if (material == Material.WATER_PLANT || material == Material.REPLACEABLE_WATER_PLANT) { + BlockEntity tileentity = iblockdata.hasBlockEntity() ? world.getBlockEntity(blockposition2) : null; +- +- dropResources(iblockdata, world, blockposition2, tileentity); ++ // Paper start ++ if (block.getHandle().getMaterial() == Material.AIR) { ++ dropResources(iblockdata, world, blockposition2, tileentity); ++ } ++ // Paper end + } + } + world.setBlock(blockposition2, block.getHandle(), block.getFlag()); diff --git a/patches/server/Fix-World-isChunkGenerated-calls.patch b/patches/server/Fix-World-isChunkGenerated-calls.patch new file mode 100644 index 0000000000..4445132f02 --- /dev/null +++ b/patches/server/Fix-World-isChunkGenerated-calls.patch @@ -0,0 +1,331 @@ +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/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + Either either = (Either) statusFuture.getNow(null); + return (either == null) ? null : (LevelChunk) either.left().orElse(null); + } ++ ++ public ChunkAccess getAvailableChunkNow() { ++ // TODO can we just getStatusFuture(EMPTY)? ++ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getParent(); curr != next; curr = next, next = next.getParent()) { ++ CompletableFuture> future = this.getFutureIfPresentUnchecked(curr); ++ Either either = future.getNow(null); ++ if (either == null || !either.left().isPresent()) { ++ continue; ++ } ++ return either.left().get(); ++ } ++ return null; ++ } + // CraftBukkit end + + public CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus leastStatus) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ProtoChunk; + import net.minecraft.world.level.chunk.UpgradeData; + import net.minecraft.world.level.chunk.storage.ChunkSerializer; + import net.minecraft.world.level.chunk.storage.ChunkStorage; ++import net.minecraft.world.level.chunk.storage.RegionFile; + import net.minecraft.world.level.entity.ChunkStatusUpdateListener; + import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + + @Nullable +- private CompoundTag readChunk(ChunkPos pos) throws IOException { ++ public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public + CompoundTag nbttagcompound = this.read(pos); ++ // Paper start - Cache chunk status on disk ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ nbttagcompound = this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ if (nbttagcompound == null) { ++ return null; ++ } ++ ++ this.updateChunkStatusOnDisk(pos, nbttagcompound); ++ ++ return nbttagcompound; ++ // Paper end ++ } ++ ++ // Paper start - chunk status cache "api" ++ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkPos chunkPos) { ++ RegionFile regionFile = regionFileCache.getRegionFileIfLoaded(chunkPos); + +- return nbttagcompound == null ? null : this.getChunkData(this.level.getTypeKey(), this.overworldDataStorage, nbttagcompound, pos, level); // CraftBukkit ++ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + } + ++ public ChunkStatus getChunkStatusOnDisk(ChunkPos chunkPos) throws IOException { ++ RegionFile regionFile = regionFileCache.getFile(chunkPos, true); ++ ++ if (regionFile == null || !regionFileCache.chunkExists(chunkPos)) { ++ return null; ++ } ++ ++ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ ++ if (status != null) { ++ return status; ++ } ++ ++ this.readChunk(chunkPos); ++ ++ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); ++ } ++ ++ public void updateChunkStatusOnDisk(ChunkPos chunkPos, @Nullable CompoundTag compound) throws IOException { ++ RegionFile regionFile = regionFileCache.getFile(chunkPos, false); ++ ++ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); ++ } ++ ++ public ChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { ++ ChunkHolder chunkHolder = this.pendingUnloads.get(ChunkPos.asLong(chunkX, chunkZ)); ++ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); ++ } ++ // Paper end ++ + boolean noPlayersCloseForSpawning(ChunkPos chunkPos) { + // Spigot start + return this.isOutsideOfRange(chunkPos, false); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + } + // Paper end + // Paper start - async chunk io ++ @Nullable + public ChunkAccess getChunkAtImmediately(int x, int z) { + ChunkHolder holder = this.chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); + if (holder == null) { +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.chunkType; + } + ++ // Paper start ++ public static ChunkStatus getStatus(String name) { ++ try { ++ // We need this otherwise we return EMPTY for invalid names ++ ResourceLocation key = new ResourceLocation(name); ++ return Registry.CHUNK_STATUS.getOptional(key).orElse(null); ++ } catch (Exception ex) { ++ return null; // invalid name ++ } ++ } ++ // Paper end + public static ChunkStatus byName(String id) { + return (ChunkStatus) Registry.CHUNK_STATUS.get(ResourceLocation.tryParse(id)); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { + return nbttagcompound; + } + ++ // Paper start ++ public static ChunkStatus getStatus(CompoundTag compound) { ++ if (compound == null) { ++ return null; ++ } ++ ++ // Note: Copied from below ++ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); ++ } ++ // Paper end ++ + public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag nbt) { + if (nbt != null) { + ChunkStatus chunkstatus = ChunkStatus.byName(nbt.getCompound("Level").getString("Status")); +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.Util; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtIo; + import net.minecraft.world.level.ChunkPos; ++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 { + public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper + public final File regionFile; // 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 directory, boolean dsync) throws IOException { + this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); + } +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + return this.getOffset(pos) != 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 getOffsetIndex(ChunkPos pos) { + return pos.getRegionLocalX() + pos.getRegionLocalZ() * 32; + } +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + synchronized (this) { + try { + // Paper end ++ this.closed = true; // Paper + try { + this.padToFullSector(); + } finally { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + + try { + NbtIo.write(nbt, (DataOutput) dataoutputstream); ++ regionfile.setStatus(pos.x, pos.z, ChunkSerializer.getStatus(nbt)); // Paper - cache status on disk + regionfile.setOversized(pos.x, pos.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 throwable) { + if (dataoutputstream != 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 @@ 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.BlockPos; +@@ -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.getChunkSource().mainThreadProcessor).join(); ++ } ++ ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); ++ if (chunk == null) { ++ chunk = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); ++ } ++ if (chunk != null) { ++ return chunk instanceof ImposterProtoChunk || chunk instanceof net.minecraft.world.level.chunk.LevelChunk; ++ } + try { +- return this.world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) ++ return world.getChunkSource().chunkMap.getChunkStatusOnDisk(new ChunkPos(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 +- ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper ++ // Paper start - Optimize this method ++ ChunkPos chunkPos = new ChunkPos(x, z); + +- // If generate = false, but the chunk already exists, we will get this back. +- if (chunk instanceof ImposterProtoChunk) { +- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition +- chunk = this.world.getChunkSource().getChunk(x, z, ChunkStatus.FULL, true); +- } ++ if (!generate) { ++ ChunkAccess immediate = world.getChunkSource().getChunkAtImmediately(x, z); ++ if (immediate == null) { ++ immediate = world.getChunkSource().chunkMap.getUnloadingChunk(x, z); ++ } ++ if (immediate != null) { ++ if (!(immediate instanceof ImposterProtoChunk) && !(immediate instanceof net.minecraft.world.level.chunk.LevelChunk)) { ++ return false; // not full status ++ } ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunk(x, z); // make sure we're at ticket level 32 or lower ++ return true; ++ } + +- if (chunk instanceof net.minecraft.world.level.chunk.LevelChunk) { +- this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 1, Unit.INSTANCE); +- return true; ++ net.minecraft.world.level.chunk.storage.RegionFile file; ++ try { ++ file = world.getChunkSource().chunkMap.regionFileCache.getFile(chunkPos, false); ++ } catch (IOException ex) { ++ throw new RuntimeException(ex); ++ } ++ ++ ChunkStatus status = file.getStatusIfCached(x, z); ++ if (!file.hasChunk(chunkPos) || (status != null && status != ChunkStatus.FULL)) { ++ return false; ++ } ++ ++ ChunkAccess chunk = world.getChunkSource().getChunk(x, z, ChunkStatus.EMPTY, true); ++ if (!(chunk instanceof ImposterProtoChunk) && !(chunk instanceof net.minecraft.world.level.chunk.LevelChunk)) { ++ return false; ++ } ++ ++ // fall through to load ++ // we do this so we do not re-read the chunk data on disk + } + +- return false; ++ world.getChunkSource().addRegionTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); ++ world.getChunkSource().getChunk(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/patches/server/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch similarity index 78% rename from Spigot-Server-Patches/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch rename to patches/server/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch index c8795f5323..bf294523a7 100644 --- a/Spigot-Server-Patches/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch +++ b/patches/server/Fix-anchor-respawn-acting-as-a-bed-respawn-from-the-.patch @@ -19,18 +19,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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); + BlockState iblockdata = worldserver1.getBlockState(blockposition); + boolean flag3 = iblockdata.is(Blocks.RESPAWN_ANCHOR); + isAnchorSpawn = flag3; // Paper - Fix anchor respawn acting as a bed respawn from the end portal - Vec3D vec3d = (Vec3D) optional.get(); + Vec3 vec3d = (Vec3) optional.get(); float f1; @@ -0,0 +0,0 @@ public abstract class PlayerList { } - Player respawnPlayer = cserver.getPlayer(entityplayer1); + Player respawnPlayer = this.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); + this.cserver.getPluginManager().callEvent(respawnEvent); // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { + if (entityplayer.connection.isDisconnected()) { diff --git a/Spigot-Server-Patches/Fix-and-optimise-world-force-upgrading.patch b/patches/server/Fix-and-optimise-world-force-upgrading.patch similarity index 58% rename from Spigot-Server-Patches/Fix-and-optimise-world-force-upgrading.patch rename to patches/server/Fix-and-optimise-world-force-upgrading.patch index 81796c6cef..a1ed63431f 100644 --- a/Spigot-Server-Patches/Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/Fix-and-optimise-world-force-upgrading.patch @@ -38,16 +38,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import com.mojang.datafixers.DataFixer; +import net.minecraft.SharedConstants; -+import net.minecraft.nbt.NBTTagCompound; ++import net.minecraft.nbt.CompoundTag; +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 net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.chunk.storage.ChunkStorage; ++import net.minecraft.world.level.chunk.storage.RegionFileStorage; ++import net.minecraft.world.level.dimension.DimensionType; ++import net.minecraft.world.level.dimension.LevelStem; ++import net.minecraft.world.level.storage.DimensionDataStorage; ++import net.minecraft.world.level.storage.LevelStorageSource; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import java.io.File; @@ -64,14 +64,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final Logger LOGGER = LogManager.getLogger(); + -+ private final ResourceKey dimensionType; -+ private final ResourceKey worldKey; ++ 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, ++ 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; @@ -96,15 +96,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + 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 worldFolder = LevelStorageSource.getFolder(new File(this.worldName), this.dimensionType); ++ final DimensionDataStorage worldPersistentData = new DimensionDataStorage(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(); ++ return WorldUpgrader.REGEX.matcher(name).matches(); + }); + if (regionFiles == null) { + LOGGER.info("Found no regionfiles to convert for world " + this.worldName); @@ -114,12 +114,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ new ChunkStorage(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); ++ final ChunkPos regionPos = RegionFileStorage.getRegionFileCoordinates(regionFile); + if (regionPos == null) { + expectedChunks -= (32L * 32L); + continue; @@ -156,15 +156,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final class WorldInfo { + -+ public final Supplier persistentDataSupplier; -+ public final IChunkLoader loader; ++ public final Supplier persistentDataSupplier; ++ public final ChunkStorage loader; + public final boolean removeCaches; -+ public final ResourceKey worldKey; ++ 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) { ++ private WorldInfo(final Supplier persistentDataSupplier, final ChunkStorage loader, final boolean removeCaches, ++ final ResourceKey worldKey) { + this.persistentDataSupplier = persistentDataSupplier; + this.loader = loader; + this.removeCaches = removeCaches; @@ -189,34 +189,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 Supplier persistentDataSupplier = this.worldInfo.persistentDataSupplier; ++ final ChunkStorage loader = this.worldInfo.loader; + final boolean removeCaches = this.worldInfo.removeCaches; -+ final ResourceKey worldKey = this.worldInfo.worldKey; ++ 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); ++ final ChunkPos chunkPos = new ChunkPos(cx, cz); + try { + // no need to check the coordinate of the chunk, the regionfilecache does that for us + -+ NBTTagCompound chunkNBT = loader.read(chunkPos); ++ CompoundTag chunkNBT = loader.read(chunkPos); + + if (chunkNBT == null) { + continue; + } + -+ final int versionBefore = IChunkLoader.getVersion(chunkNBT); ++ final int versionBefore = ChunkStorage.getVersion(chunkNBT); + + chunkNBT = loader.getChunkData(worldKey, persistentDataSupplier, chunkNBT, chunkPos, null); + -+ boolean modified = versionBefore < SharedConstants.getGameVersion().getWorldVersion(); ++ boolean modified = versionBefore < SharedConstants.getCurrentVersion().getWorldVersion(); + + if (removeCaches) { -+ final NBTTagCompound level = chunkNBT.getCompound("Level"); -+ modified |= level.hasKey("Heightmaps"); ++ final CompoundTag level = chunkNBT.getCompound("Level"); ++ modified |= level.contains("Heightmaps"); + level.remove("Heightmaps"); -+ modified |= level.hasKey("isLightOn"); ++ modified |= level.contains("isLightOn"); + level.remove("isLightOn"); + } + @@ -251,7 +251,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper end + // Paper start - fix and optimise world upgrading -+ public static void convertWorldButItWorks(ResourceKey dimensionType, ResourceKey worldKey, String worldName, ++ 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); @@ -259,97 +259,72 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // 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); + public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); 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 { +- if (this.options.has("forceUpgrade")) { +- net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), this.options.has("eraseCache"), () -> { - return true; -- }, worlddata.getGeneratorSettings().d().d().stream().map((entry1) -> { -- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry1.getKey()).a()); +- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry1) -> { +- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry1.getKey()).location()); - }).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()); + ResourceKey worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, dimensionKey.location()); - 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 + if (dimensionKey == LevelStem.OVERWORLD) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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; - } +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions + public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here + // 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(() -> { ++ public static ResourceKey getDimensionKey(DimensionType manager) { ++ return ((org.bukkit.craftbukkit.CraftServer)org.bukkit.Bukkit.getServer()).getHandle().getServer().registryHolder.ownedRegistryOrThrow(net.minecraft.core.Registry.DIMENSION_TYPE_REGISTRY).getResourceKey(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 CraftWorld getWorld() { + return this.world; } - -+ 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.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 - +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { + } // Paper start -+ public static ChunkCoordIntPair getRegionFileCoordinates(File file) { ++ public static ChunkPos getRegionFileCoordinates(File file) { + String fileName = file.getName(); + if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) { + return null; @@ -365,14 +340,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + int x = Integer.parseInt(split[1]); + int z = Integer.parseInt(split[2]); + -+ return new ChunkCoordIntPair(x << 5, z << 5); ++ return new ChunkPos(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())); + public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { + return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(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 @@ -381,31 +356,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public final class CraftServer implements Server { } worlddata.checkName(name); - worlddata.a(console.getServerModName(), console.getModded().isPresent()); + worlddata.setModdedInfo(this.console.getServerModName(), this.console.getModdedStatus().isPresent()); - - if (console.options.has("forceUpgrade")) { -- net.minecraft.server.Main.convertWorld(worldSession, DataConverterRegistry.a(), console.options.has("eraseCache"), () -> { +- net.minecraft.server.Main.forceUpgrade(worldSession, DataFixers.getDataFixer(), console.options.has("eraseCache"), () -> { - return true; -- }, worlddata.getGeneratorSettings().d().d().stream().map((entry) -> { -- return ResourceKey.a(IRegistry.K, ((ResourceKey) entry.getKey()).a()); +- }, worlddata.worldGenSettings().dimensions().entrySet().stream().map((entry) -> { +- return ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, ((ResourceKey) entry.getKey()).location()); - }).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)); + long j = BiomeManager.obfuscateSeed(creator.seed()); + List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); @@ -0,0 +0,0 @@ public final class CraftServer implements Server { - chunkgenerator = worlddimension.c(); + chunkgenerator = worlddimension.generator(); } + // 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") ++ actualDimension, net.minecraft.world.level.Level.getDimensionKey(dimensionmanager), worldSession.getLevelId(), DataFixers.getDataFixer(), console.options.has("eraseCache") + ); + } + // Paper end - fix and optimise world upgrading + - ResourceKey worldKey; - String levelName = this.getServer().getDedicatedServerProperties().levelName; + ResourceKey worldKey; + String levelName = this.getServer().getProperties().levelName; if (name.equals(levelName + "_nether")) { diff --git a/patches/server/Fix-arrows-never-despawning-MC-125757.patch b/patches/server/Fix-arrows-never-despawning-MC-125757.patch new file mode 100644 index 0000000000..d8dc426942 --- /dev/null +++ b/patches/server/Fix-arrows-never-despawning-MC-125757.patch @@ -0,0 +1,22 @@ +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/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -0,0 +0,0 @@ public abstract class AbstractArrow extends Projectile { + + ++this.inGroundTime; + } else { ++ if (tickCount > 200) this.tickDespawn(); // Paper - tick despawnCounter regardless after 10 seconds + this.inGroundTime = 0; + Vec3 vec3d2 = this.position(); + diff --git a/patches/server/Fix-checkReach-check-for-Shulker-boxes.patch b/patches/server/Fix-checkReach-check-for-Shulker-boxes.patch new file mode 100644 index 0000000000..3038e2a4a3 --- /dev/null +++ b/patches/server/Fix-checkReach-check-for-Shulker-boxes.patch @@ -0,0 +1,18 @@ +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/ShulkerBoxMenu.java b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/ShulkerBoxMenu.java +@@ -0,0 +0,0 @@ public class ShulkerBoxMenu extends AbstractContainerMenu { + + @Override + public boolean stillValid(Player player) { ++ if (!this.checkReachable) return true; // Paper - Add reachable override for ContainerShulkerBox + return this.container.stillValid(player); + } + diff --git a/Spigot-Server-Patches/Fix-client-lag-on-advancement-loading.patch b/patches/server/Fix-client-lag-on-advancement-loading.patch similarity index 59% rename from Spigot-Server-Patches/Fix-client-lag-on-advancement-loading.patch rename to patches/server/Fix-client-lag-on-advancement-loading.patch index acd39431de..5a6d5ed3aa 100644 --- a/Spigot-Server-Patches/Fix-client-lag-on-advancement-loading.patch +++ b/patches/server/Fix-client-lag-on-advancement-loading.patch @@ -14,26 +14,6 @@ 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 @@ -42,12 +22,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); } -- MinecraftServer.getServer().getPlayerList().reload(); +- MinecraftServer.getServer().getPlayerList().reloadResources(); + // Paper start + //MinecraftServer.getServer().getPlayerList().reload(); + MinecraftServer.getServer().getPlayerList().getPlayers().forEach(player -> { -+ player.getAdvancementData().reload(MinecraftServer.getServer().getAdvancementData()); -+ player.getAdvancementData().sendUpdateIfNeeded(player); ++ player.getAdvancements().reload(MinecraftServer.getServer().getAdvancements()); ++ player.getAdvancements().flushDirty(player); + }); + // Paper end diff --git a/patches/server/Fix-client-rendering-skulls-from-same-user.patch b/patches/server/Fix-client-rendering-skulls-from-same-user.patch new file mode 100644 index 0000000000..75b51b8650 --- /dev/null +++ b/patches/server/Fix-client-rendering-skulls-from-same-user.patch @@ -0,0 +1,118 @@ +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/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -0,0 +0,0 @@ public class FriendlyByteBuf extends ByteBuf { + if (item.canBeDepleted() || item.shouldOverrideMultiplayerNbt()) { + // Spigot start - filter + stack = stack.copy(); +- CraftItemStack.setItemMeta(stack, CraftItemStack.getItemMeta(stack)); ++ // CraftItemStack.setItemMeta(stack, CraftItemStack.getItemMeta(stack)); // Paper - This is no longer needed due to NBT being supported + // Spigot end + nbttagcompound = stack.getTag(); ++ // Paper start ++ if (nbttagcompound != null && nbttagcompound.contains("SkullOwner", 10)) { ++ CompoundTag owner = nbttagcompound.getCompound("SkullOwner"); ++ if (owner.hasUUID("Id")) { ++ nbttagcompound.putUUID("SkullOwnerOrig", owner.getUUID("Id")); ++ net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeUUID(owner); ++ } ++ } ++ // Paper end + } + + this.writeNbt(nbttagcompound); +@@ -0,0 +0,0 @@ public class FriendlyByteBuf extends ByteBuf { + itemstack.setTag(this.readNbt()); + // 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.contains("SkullOwnerOrig")) { ++ CompoundTag owner = itemstack.tag.getCompound("SkullOwner"); ++ if (itemstack.tag.contains("SkullOwnerOrig")) { ++ owner.tags.put("Id", itemstack.tag.tags.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/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet entry2 : chunk.getBlockEntities().entrySet()) { + BlockEntity blockEntity = entry2.getValue(); + CompoundTag compoundTag = blockEntity.getUpdateTag(); ++ if (blockEntity instanceof net.minecraft.world.level.block.entity.SkullBlockEntity) { net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeTileEntityUUID(compoundTag); } // Paper + this.blockEntitiesTags.add(compoundTag); + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +@@ -0,0 +0,0 @@ import java.util.function.Consumer; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; + import net.minecraft.server.players.GameProfileCache; +@@ -0,0 +0,0 @@ public class SkullBlockEntity extends BlockEntity { + @Nullable + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { +- return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, this.getUpdateTag()); ++ return new ClientboundBlockEntityDataPacket(this.worldPosition, 4, sanitizeTileEntityUUID(this.getUpdateTag())); // Paper + } + ++ // Paper start ++ public static CompoundTag sanitizeTileEntityUUID(CompoundTag cmp) { ++ CompoundTag owner = cmp.getCompound("Owner"); ++ if (!owner.isEmpty()) { ++ sanitizeUUID(owner); ++ } ++ return cmp; ++ } ++ ++ public static void sanitizeUUID(CompoundTag owner) { ++ CompoundTag properties = owner.getCompound("Properties"); ++ ListTag list = null; ++ if (!properties.isEmpty()) { ++ list = properties.getList("textures", 10); ++ } ++ ++ if (list != null && !list.isEmpty()) { ++ String textures = ((CompoundTag)list.get(0)).getString("Value"); ++ if (textures != null && textures.length() > 3) { ++ UUID uuid = UUID.nameUUIDFromBytes(textures.getBytes()); ++ owner.putUUID("Id", uuid); ++ return; ++ } ++ } ++ owner.putUUID("Id", UUID.randomUUID()); ++ } ++ // Paper end ++ + @Override + public CompoundTag getUpdateTag() { + return this.save(new CompoundTag()); diff --git a/patches/server/Fix-console-spam-when-removing-chests-in-water.patch b/patches/server/Fix-console-spam-when-removing-chests-in-water.patch new file mode 100644 index 0000000000..4351253a29 --- /dev/null +++ b/patches/server/Fix-console-spam-when-removing-chests-in-water.patch @@ -0,0 +1,19 @@ +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/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java +@@ -0,0 +0,0 @@ public class ChestBlock extends AbstractChestBlock implements + @Override + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) { + if (!state.is(newState.getBlock())) { +- BlockEntity tileentity = world.getBlockEntity(pos); ++ BlockEntity tileentity = world.getTileEntity(pos, false); // Paper - Don't validate TE - Fix console spam when removing chests in water + + if (tileentity instanceof Container) { + Containers.dropContents(world, pos, (Container) tileentity); diff --git a/patches/server/Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/Fix-curing-zombie-villager-discount-exploit.patch new file mode 100644 index 0000000000..62d54fdbf6 --- /dev/null +++ b/patches/server/Fix-curing-zombie-villager-discount-exploit.patch @@ -0,0 +1,45 @@ +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 { + 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); ++ } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void onReputationEventFrom(ReputationEventType interaction, Entity entity) { + if (interaction == ReputationEventType.ZOMBIE_VILLAGER_CURED) { ++ // Paper start - fix MC-181190 ++ if (level.paperConfig.fixCuringZombieVillagerDiscountExploit) { ++ final GossipContainer.EntityGossips playerReputation = this.getGossips().getReputations().get(entity.getUUID()); ++ if (playerReputation != null) { ++ playerReputation.remove(GossipType.MAJOR_POSITIVE); ++ playerReputation.remove(GossipType.MINOR_POSITIVE); ++ } ++ } ++ // Paper end + this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20); + this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25); + } else if (interaction == ReputationEventType.TRADE) { diff --git a/patches/server/Fix-dangerous-end-portal-logic.patch b/patches/server/Fix-dangerous-end-portal-logic.patch new file mode 100644 index 0000000000..96dbe3d64e --- /dev/null +++ b/patches/server/Fix-dangerous-end-portal-logic.patch @@ -0,0 +1,87 @@ +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/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 Nameable, EntityAccess, CommandSource, n + } + // Paper end - optimise entity tracking + ++ // Paper start - make end portalling safe ++ public BlockPos portalBlock; ++ public ServerLevel portalWorld; ++ public void tickEndPortal() { ++ BlockPos pos = this.portalBlock; ++ ServerLevel world = this.portalWorld; ++ this.portalBlock = null; ++ this.portalWorld = null; ++ ++ if (pos == null || world == null || world != this.level) { ++ return; ++ } ++ ++ if (this.isPassenger() || this.isVehicle() || !this.canChangeDimensions() || this.isRemoved() || !this.valid || !this.isAlive()) { ++ return; ++ } ++ ++ ResourceKey resourcekey = world.getTypeKey() == DimensionType.END_LOCATION ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends ++ ServerLevel worldserver = world.getServer().getLevel(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 ServerPlayer) { ++ ((ServerPlayer)this).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); ++ return; ++ } ++ this.teleportTo(worldserver, null); ++ } ++ // Paper end - make end portalling safe ++ + public Entity(EntityType type, Level world) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = ImmutableList.of(); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + } + + this.processPortalCooldown(); ++ this.tickEndPortal(); // Paper - make end portalling safe + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +@@ -0,0 +0,0 @@ public class EndPortalBlock extends BaseEntityBlock { + // 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(), pos.getX(), pos.getY(), pos.getZ())); +- world.getCraftServer().getPluginManager().callEvent(event); +- +- if (entity instanceof ServerPlayer) { +- ((ServerPlayer) entity).changeDimension(worldserver, PlayerTeleportEvent.TeleportCause.END_PORTAL); +- return; +- } +- // CraftBukkit end +- entity.changeDimension(worldserver); ++ // Paper start - move all of this logic into portal tick ++ entity.portalWorld = ((ServerLevel)world); ++ entity.portalBlock = pos.immutable(); ++ // 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/patches/server/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch similarity index 58% rename from Spigot-Server-Patches/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch rename to patches/server/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch index 62d1af6029..7651dcd769 100644 --- a/Spigot-Server-Patches/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch +++ b/patches/server/Fix-deop-kicking-non-whitelisted-player-when-white-l.patch @@ -9,11 +9,11 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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()); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 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/patches/server/Fix-duplicating-give-items-on-item-drop-cancel.patch similarity index 56% rename from Spigot-Server-Patches/Fix-duplicating-give-items-on-item-drop-cancel.patch rename to patches/server/Fix-duplicating-give-items-on-item-drop-cancel.patch index ef4ced2b1d..9044440a08 100644 --- a/Spigot-Server-Patches/Fix-duplicating-give-items-on-item-drop-cancel.patch +++ b/patches/server/Fix-duplicating-give-items-on-item-drop-cancel.patch @@ -28,43 +28,43 @@ 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 +diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.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 +--- a/src/main/java/net/minecraft/server/commands/GiveCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java +@@ -0,0 +0,0 @@ public class GiveCommand { + boolean bl = serverPlayer.getInventory().add(itemStack); + if (bl && itemStack.isEmpty()) { + itemStack.setCount(1); +- ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false); ++ ItemEntity itemEntity2 = serverPlayer.drop(itemStack, false, false, true); // Paper - Fix duplicating /give items on item drop cancel + if (itemEntity2 != null) { + itemEntity2.makeFakeItem(); + } +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.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 { +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { @Nullable - public EntityItem a(ItemStack itemstack, boolean flag, boolean flag1) { + public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) { + // Paper start - Fix duplicating /give items on item drop cancel -+ return this.drop(itemstack, flag, flag1, false); ++ return this.drop(stack, throwRandomly, retainOwnership, false); + } + + @Nullable -+ public EntityItem drop(ItemStack itemstack, boolean flag, boolean flag1, boolean alwaysSucceed) { ++ public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership, boolean alwaysSucceed) { + // Paper end - if (itemstack.isEmpty()) { + if (stack.isEmpty()) { return null; } else { -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); - this.world.getServer().getPluginManager().callEvent(event); + this.level.getCraftServer().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)) { + if (retainOwnership && (cur == null || cur.getAmount() == 0)) { // The complete stack was dropped diff --git a/patches/server/Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server/Fix-exploit-that-allowed-colored-signs-to-be-created.patch new file mode 100644 index 0000000000..22843cfba5 --- /dev/null +++ b/patches/server/Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -0,0 +1,22 @@ +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/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + for (int i = 0; i < list.size(); ++i) { + if (this.player.isTextFilteringEnabled()) { +- lines.add(net.kyori.adventure.text.Component.text(list.get(i).getFiltered())); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getFiltered()))); + } else { +- lines.add(net.kyori.adventure.text.Component.text(list.get(i).getRaw())); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getRaw()))); + } + } + SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.cserver.getPlayer(this.player), lines); diff --git a/patches/server/Fix-for-large-move-vectors-crashing-server.patch b/patches/server/Fix-for-large-move-vectors-crashing-server.patch new file mode 100644 index 0000000000..f3b1587e94 --- /dev/null +++ b/patches/server/Fix-for-large-move-vectors-crashing-server.patch @@ -0,0 +1,65 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { + ServerLevel worldserver = this.player.getLevel(); +- double d0 = entity.getX(); +- double d1 = entity.getY(); +- double d2 = entity.getZ(); +- double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX()); +- double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY()); +- double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ()); ++ double d0 = entity.getX();final double fromX = d0; // Paper - OBFHELPER ++ double d1 = entity.getY();final double fromY = d1; // Paper - OBFHELPER ++ double d2 = entity.getZ();final double fromZ = d2; // Paper - OBFHELPER ++ double d3 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX());final double toX = d3; // Paper - OBFHELPER ++ double d4 = ServerGamePacketListenerImpl.clampVertical(packet.getY());final double toY = d4; // Paper - OBFHELPER ++ double d5 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ());final double toZ = d5; // Paper - OBFHELPER + float f = Mth.wrapDegrees(packet.getYRot()); + float f1 = Mth.wrapDegrees(packet.getXRot()); + double d6 = d3 - this.vehicleFirstGoodX; + double d7 = d4 - this.vehicleFirstGoodY; + double d8 = d5 - this.vehicleFirstGoodZ; + double d9 = entity.getDeltaMovement().lengthSqr(); +- double d10 = d6 * d6 + d7 * d7 + d8 * d8; ++ // 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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + float prevPitch = this.player.getXRot(); + // CraftBukkit end + double d3 = this.player.getX(); final double toX = d3; // Paper - OBFHELPER +- double d4 = this.player.getY(); ++ double d4 = this.player.getY(); final double toY = d4; // Paper - OBFHELPER + double d5 = this.player.getZ(); final double toZ = d5; // Paper - OBFHELPER + double d6 = this.player.getY(); + double d7 = d0 - this.firstGoodX; + double d8 = d1 - this.firstGoodY; + double d9 = d2 - this.firstGoodZ; + double d10 = this.player.getDeltaMovement().lengthSqr(); +- 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/patches/server/Fix-harming-potion-dupe.patch b/patches/server/Fix-harming-potion-dupe.patch new file mode 100644 index 0000000000..c8b00beca3 --- /dev/null +++ b/patches/server/Fix-harming-potion-dupe.patch @@ -0,0 +1,49 @@ +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/PotionItem.java b/src/main/java/net/minecraft/world/item/PotionItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/PotionItem.java ++++ b/src/main/java/net/minecraft/world/item/PotionItem.java +@@ -0,0 +0,0 @@ public class PotionItem extends Item { + CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) entityhuman, stack); + } + ++ List instantLater = new java.util.ArrayList<>(); // Paper - Fix harming potion dupe + if (!world.isClientSide) { + List list = PotionUtils.getMobEffects(stack); + Iterator iterator = list.iterator(); +@@ -0,0 +0,0 @@ public class PotionItem extends Item { + MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); + + if (mobeffect.getEffect().isInstantenous()) { +- mobeffect.getEffect().applyInstantenousEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); ++ instantLater.add(mobeffect); // Paper - Fix harming potion dupe + } else { + user.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.POTION_DRINK); // CraftBukkit + } +@@ -0,0 +0,0 @@ public class PotionItem extends Item { + } + } + ++ // Paper start - Fix harming potion dupe ++ for (MobEffectInstance mobeffect : instantLater) { ++ mobeffect.getEffect().applyInstantenousEffect(entityhuman, entityhuman, user, mobeffect.getAmplifier(), 1.0D); ++ } ++ // Paper end + if (entityhuman == null || !entityhuman.getAbilities().instabuild) { ++ // Paper start - Fix harming potion dupe ++ if (user.getHealth() <= 0 && !user.level.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_KEEPINVENTORY)) { ++ user.spawnAtLocation(new ItemStack(Items.GLASS_BOTTLE), 0); ++ return ItemStack.EMPTY; ++ } ++ // Paper end + if (stack.isEmpty()) { + return new ItemStack(Items.GLASS_BOTTLE); + } diff --git a/patches/server/Fix-hex-colors-not-working-in-some-kick-messages.patch b/patches/server/Fix-hex-colors-not-working-in-some-kick-messages.patch new file mode 100644 index 0000000000..8d9ea9e548 --- /dev/null +++ b/patches/server/Fix-hex-colors-not-working-in-some-kick-messages.patch @@ -0,0 +1,64 @@ +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/ServerHandshakePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + synchronized (ServerHandshakePacketListenerImpl.throttleTracker) { + if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) { + ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime); +- TranslatableComponent chatmessage = new TranslatableComponent(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message ++ Component 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.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + } + // CraftBukkit end + if (packet.getProtocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { +- TranslatableComponent chatmessage; ++ Component chatmessage; // Paper - Fix hex colors not working in some kick messages + + if (packet.getProtocolVersion() < 754) { +- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } else { +- chatmessage = new TranslatableComponent( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) ); // Spigot ++ chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName() ) , true )[0]; // Spigot // Paper - Fix hex colors not working in some kick messages + } + + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); +@@ -0,0 +0,0 @@ public class ServerHandshakePacketListenerImpl implements ServerHandshakePacketL + if (event.callEvent()) { + // If we've failed somehow, let the client know so and go no further. + if (event.isFailed()) { +- TranslatableComponent chatmessage = new TranslatableComponent(event.getFailMessage()); ++ Component chatmessage = org.bukkit.craftbukkit.util.CraftChatMessage.fromString(event.getFailMessage(), true)[0]; // Paper - Fix hex colors not working in some kick messages + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; +diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + // CraftBukkit start + @Deprecated + public void disconnect(String s) { +- try { +- Component ichatbasecomponent = new TextComponent(s); +- ServerLoginPacketListenerImpl.LOGGER.info("Disconnecting {}: {}", this.getUserName(), s); +- this.connection.send(new ClientboundLoginDisconnectPacket(ichatbasecomponent)); +- this.connection.disconnect(ichatbasecomponent); +- } catch (Exception exception) { +- ServerLoginPacketListenerImpl.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/patches/server/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch similarity index 55% rename from Spigot-Server-Patches/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch rename to patches/server/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch index f777c9c767..f115e487fc 100644 --- a/Spigot-Server-Patches/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch +++ b/patches/server/Fix-incorrect-status-dataconverter-for-pre-1.13-chun.patch @@ -34,17 +34,24 @@ 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 +diff --git a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.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(); +--- a/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java ++++ b/src/main/java/net/minecraft/util/datafix/fixes/ChunkToProtochunkFix.java +@@ -0,0 +0,0 @@ public class ChunkToProtochunkFix extends DataFix { + OpticFinder opticFinder2 = DSL.fieldFinder("TileTicks", type5); + return TypeRewriteRule.seq(this.fixTypeEverywhereTyped("ChunkToProtoChunkFix", type, this.getOutputSchema().getType(References.CHUNK), (typed) -> { + return typed.updateTyped(opticFinder, type4, (typedx) -> { +- Optional>> optional = typedx.getOptionalTyped(opticFinder2).flatMap((typed) -> { +- return typed.write().result(); ++ Optional>> optional = typedx.getOptionalTyped(opticFinder2).flatMap((it) -> { // Paper - remap fix ++ return it.write().result(); // Paper - remap fix + }).flatMap((dynamicx) -> { + return dynamicx.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")); + Dynamic dynamic = typedx.get(DSL.remainderFinder()); +- boolean bl = dynamic.get("TerrainPopulated").asBoolean(false) && (!dynamic.get("LightPopulated").asNumber().result().isPresent() || dynamic.get("LightPopulated").asBoolean(false)); +- dynamic = dynamic.set("Status", dynamic.createString(bl ? "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 @@ -55,37 +62,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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) { + dynamic = dynamic.set("hasLegacyStructureData", dynamic.createBoolean(true)); + Dynamic dynamic3; +- if (bl) { + 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)); - }))); - } - + Optional optional2 = dynamic.get("Biomes").asByteBufferOpt().result(); + if (optional2.isPresent()) { + ByteBuffer byteBuffer = optional2.get(); diff --git a/patches/server/Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/Fix-interact-event-not-being-called-in-adventure.patch new file mode 100644 index 0000000000..2dfb556a32 --- /dev/null +++ b/patches/server/Fix-interact-event-not-being-called-in-adventure.patch @@ -0,0 +1,29 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + MutableComponent ichatmutablecomponent = (new TranslatableComponent("build.tooHigh", new Object[]{i - 1})).withStyle(ChatFormatting.RED); + + this.player.sendMessage((Component) ichatmutablecomponent, ChatType.GAME_INFO, Util.NIL_UUID); +- } else if (enuminteractionresult.shouldSwing()) { ++ } else if (enuminteractionresult.shouldSwing() && !this.player.gameMode.interactResult) { + this.player.swing(enumhand, true); + } + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); + HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); + +- if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { ++ if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK || this.player.gameMode.getGameModeForPlayer() == GameType.ADVENTURE) { // Paper - call PlayerInteractEvent when left-clicking on a block in adventure mode + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_AIR, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); + } + diff --git a/patches/server/Fix-invulnerable-end-crystals.patch b/patches/server/Fix-invulnerable-end-crystals.patch new file mode 100644 index 0000000000..5deaf9cda9 --- /dev/null +++ b/patches/server/Fix-invulnerable-end-crystals.patch @@ -0,0 +1,80 @@ +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/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +@@ -0,0 +0,0 @@ public class EndCrystal extends Entity { + private static final EntityDataAccessor> DATA_BEAM_TARGET = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.OPTIONAL_BLOCK_POS); + private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); + public int time; ++ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals + + public EndCrystal(EntityType type, Level world) { + super(type, world); +@@ -0,0 +0,0 @@ public class EndCrystal extends Entity { + } + // CraftBukkit end + } ++ // Paper start - Fix invulnerable end crystals ++ if (this.level.paperConfig.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) { ++ if (!java.util.Objects.equals(((ServerLevel) this.level).uuid, this.getOriginWorld()) ++ || ((ServerLevel) this.level).dragonFight() == null ++ || ((ServerLevel) this.level).dragonFight().respawnStage == null ++ || ((ServerLevel) this.level).dragonFight().respawnStage.ordinal() > net.minecraft.world.level.dimension.end.DragonRespawnAnimation.SUMMONING_DRAGON.ordinal()) { ++ this.setInvulnerable(false); ++ this.setBeamTarget(null); ++ } ++ } ++ // Paper end + } + + } +@@ -0,0 +0,0 @@ public class EndCrystal extends Entity { + } + + nbt.putBoolean("ShowBottom", this.showsBottom()); ++ if (this.generatedByDragonFight) nbt.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals + } + + @Override +@@ -0,0 +0,0 @@ public class EndCrystal extends Entity { + if (nbt.contains("ShowBottom", 1)) { + this.setShowBottom(nbt.getBoolean("ShowBottom")); + } ++ if (nbt.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = nbt.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals + + } + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/SpikeFeature.java +@@ -0,0 +0,0 @@ public class SpikeFeature extends Feature { + endCrystal.setBeamTarget(config.getCrystalBeamTarget()); + endCrystal.setInvulnerable(config.isCrystalInvulnerable()); + endCrystal.moveTo((double)spike.getCenterX() + 0.5D, (double)(spike.getHeight() + 1), (double)spike.getCenterZ() + 0.5D, random.nextFloat() * 360.0F, 0.0F); ++ endCrystal.generatedByDragonFight = true; // Paper + world.addFreshEntity(endCrystal); + this.setBlock(world, new BlockPos(spike.getCenterX(), spike.getHeight(), spike.getCenterZ()), Blocks.BEDROCK.defaultBlockState()); + } diff --git a/patches/server/Fix-item-locations-dropped-from-campfires.patch b/patches/server/Fix-item-locations-dropped-from-campfires.patch new file mode 100644 index 0000000000..52ce91bafa --- /dev/null +++ b/patches/server/Fix-item-locations-dropped-from-campfires.patch @@ -0,0 +1,24 @@ +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/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +@@ -0,0 +0,0 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { + result = blockCookEvent.getResult(); + itemstack1 = CraftItemStack.asNMSCopy(result); + // CraftBukkit end +- Containers.dropItemStack(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1); ++ // Paper start ++ net.minecraft.world.entity.item.ItemEntity droppedItem = new net.minecraft.world.entity.item.ItemEntity(world, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, itemstack1.split(world.random.nextInt(21) + 10)); ++ droppedItem.setDeltaMovement(world.random.nextGaussian() * 0.05D, world.random.nextGaussian() * 0.05D + 0.2D, world.random.nextGaussian() * 0.05D); ++ world.addFreshEntity(droppedItem); ++ // Paper end + campfire.items.set(i, ItemStack.EMPTY); + world.sendBlockUpdated(pos, state, state, 3); + } diff --git a/Spigot-Server-Patches/Fix-items-not-falling-correctly.patch b/patches/server/Fix-items-not-falling-correctly.patch similarity index 52% rename from Spigot-Server-Patches/Fix-items-not-falling-correctly.patch rename to patches/server/Fix-items-not-falling-correctly.patch index 69bff970cc..fc55d33746 100644 --- a/Spigot-Server-Patches/Fix-items-not-falling-correctly.patch +++ b/patches/server/Fix-items-not-falling-correctly.patch @@ -14,16 +14,16 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ public class ItemEntity 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()); +- if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { ++ if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check + this.move(MoverType.SELF, this.getDeltaMovement()); float f1 = 0.98F; diff --git a/Spigot-Server-Patches/Fix-items-vanishing-through-end-portal.patch b/patches/server/Fix-items-vanishing-through-end-portal.patch similarity index 73% rename from Spigot-Server-Patches/Fix-items-vanishing-through-end-portal.patch rename to patches/server/Fix-items-vanishing-through-end-portal.patch index 0ed2564cc5..04b7e40849 100644 --- a/Spigot-Server-Patches/Fix-items-vanishing-through-end-portal.patch +++ b/patches/server/Fix-items-vanishing-through-end-portal.patch @@ -16,13 +16,13 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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; +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + BlockPos blockposition1; if (flag1) { + // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate -+ this.world.getChunkAtWorldCoords(this.world.getSpawn()); ++ this.level.getChunkAt(this.level.getSharedSpawnPos()); + // Paper end - blockposition1 = WorldServer.a; + blockposition1 = ServerLevel.END_SPAWN_POINT; } else { - blockposition1 = worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn()); + blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos()); diff --git a/patches/server/Fix-lag-from-explosions-processing-dead-entities.patch b/patches/server/Fix-lag-from-explosions-processing-dead-entities.patch new file mode 100644 index 0000000000..1bb8d79ce9 --- /dev/null +++ b/patches/server/Fix-lag-from-explosions-processing-dead-entities.patch @@ -0,0 +1,19 @@ +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 = Mth.floor(this.y + (double) f2 + 1.0D); + int j1 = Mth.floor(this.z - (double) f2 - 1.0D); + int k1 = Mth.floor(this.z + (double) f2 + 1.0D); +- List list = this.level.getEntities(this.source, new AABB((double) i, (double) l, (double) j1, (double) j, (double) i1, (double) k1)); ++ List list = this.level.getEntities(this.source, new AABB((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 + Vec3 vec3d = new Vec3(this.x, this.y, this.z); + + for (int l1 = 0; l1 < list.size(); ++l1) { diff --git a/patches/server/Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server/Fix-last-firework-in-stack-not-having-effects-when-d.patch new file mode 100644 index 0000000000..a2eef4eeca --- /dev/null +++ b/patches/server/Fix-last-firework-in-stack-not-having-effects-when-d.patch @@ -0,0 +1,23 @@ +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/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +@@ -0,0 +0,0 @@ public interface DispenseItemBehavior { + } + + itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); +- FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), stack, pointer.x(), pointer.y(), pointer.x(), true); ++ FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), itemstack1, pointer.x(), pointer.y(), pointer.x(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed + + DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection); + entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); diff --git a/Spigot-Server-Patches/Fix-missing-chunks-due-to-integer-overflow.patch b/patches/server/Fix-missing-chunks-due-to-integer-overflow.patch similarity index 53% rename from Spigot-Server-Patches/Fix-missing-chunks-due-to-integer-overflow.patch rename to patches/server/Fix-missing-chunks-due-to-integer-overflow.patch index a02a965a2c..83c39000f2 100644 --- a/Spigot-Server-Patches/Fix-missing-chunks-due-to-integer-overflow.patch +++ b/patches/server/Fix-missing-chunks-due-to-integer-overflow.patch @@ -12,18 +12,16 @@ is a few hundred thousand block gap before end land resuming to generate at 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 +diff --git a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.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 { +--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java ++++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +@@ -0,0 +0,0 @@ public class TheEndBiomeSource extends BiomeSource { 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); + int m = i % 2; + int n = j % 2; +- float f = 100.0F - Mth.sqrt((float)(i * i + j * j)) * 8.0F; ++ float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; // Paper - cast ints to long to avoid integer overflow + f = Mth.clamp(f, -100.0F, 80.0F); + for(int o = -12; o <= 12; ++o) { diff --git a/Spigot-Server-Patches/Fix-nerfed-slime-when-splitting.patch b/patches/server/Fix-nerfed-slime-when-splitting.patch similarity index 52% rename from Spigot-Server-Patches/Fix-nerfed-slime-when-splitting.patch rename to patches/server/Fix-nerfed-slime-when-splitting.patch index 807a2ce72c..c98748875e 100644 --- a/Spigot-Server-Patches/Fix-nerfed-slime-when-splitting.patch +++ b/patches/server/Fix-nerfed-slime-when-splitting.patch @@ -4,15 +4,15 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.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(); +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + entityslime.setPersistenceRequired(); } + entityslime.aware = this.aware; // Paper entityslime.setCustomName(ichatbasecomponent); - entityslime.setNoAI(flag); + entityslime.setNoAi(flag); entityslime.setInvulnerable(this.isInvulnerable()); diff --git a/Spigot-Server-Patches/Fix-numerous-item-duplication-issues-and-teleport-is.patch b/patches/server/Fix-numerous-item-duplication-issues-and-teleport-is.patch similarity index 61% rename from Spigot-Server-Patches/Fix-numerous-item-duplication-issues-and-teleport-is.patch rename to patches/server/Fix-numerous-item-duplication-issues-and-teleport-is.patch index 86cbe8626a..ec34effcbe 100644 --- a/Spigot-Server-Patches/Fix-numerous-item-duplication-issues-and-teleport-is.patch +++ b/patches/server/Fix-numerous-item-duplication-issues-and-teleport-is.patch @@ -19,24 +19,24 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } 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 + if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) { +- ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(stack)); ++ ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); // 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 +- ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack); ++ ItemEntity entityitem = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), stack.copy()); // Paper - clone so we can destroy original ++ stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe - entityitem.defaultPickupDelay(); + entityitem.setDefaultPickUpDelay(); // CraftBukkit start -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n @Nullable - public Entity teleportTo(WorldServer worldserver, BlockPosition location) { + public Entity teleportTo(ServerLevel worldserver, BlockPos location) { // CraftBukkit end + // Paper start - fix bad state entities causing dupes + if (!isAlive() || !valid) { @@ -44,61 +44,61 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + // Paper end - if (this.world instanceof WorldServer && !this.dead) { - this.world.getMethodProfiler().enter("changeDimension"); + if (this.level instanceof ServerLevel && !this.isRemoved()) { + this.level.getProfiler().push("changeDimension"); // CraftBukkit start -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n // CraftBukkit end - this.world.getMethodProfiler().exitEnter("reloading"); + this.level.getProfiler().popPush("reloading"); + // Paper start - Change lead drop timing to prevent dupe -+ if (this instanceof EntityInsentient) { -+ ((EntityInsentient) this).unleash(true, true); // Paper drop lead ++ if (this instanceof Mob) { ++ ((Mob) this).dropLeash(true, true); // Paper drop lead + } + // Paper end - Entity entity = this.getEntityType().a((World) worldserver); + Entity entity = this.getType().create((Level) worldserver); if (entity != null) { -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n // 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. +- if (this instanceof Mob) { +- ((Mob) this).dropLeash(true, false); // Unleash to prevent duping of leads. - } // CraftBukkit end } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - public boolean canPortal() { + public boolean canChangeDimensions() { - 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 + public float getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState, float max) { +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.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 { +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { 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); + this.handItems.set(i, ItemStack.EMPTY); } } -@@ -0,0 +0,0 @@ public class EntityArmorStand extends EntityLiving { +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { 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); + this.armorItems.set(i, ItemStack.EMPTY); } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java diff --git a/Spigot-Server-Patches/Fix-piston-physics-inconsistency-MC-188840.patch b/patches/server/Fix-piston-physics-inconsistency-MC-188840.patch similarity index 57% rename from Spigot-Server-Patches/Fix-piston-physics-inconsistency-MC-188840.patch rename to patches/server/Fix-piston-physics-inconsistency-MC-188840.patch index 6ced3c8536..a9fbc01d90 100644 --- a/Spigot-Server-Patches/Fix-piston-physics-inconsistency-MC-188840.patch +++ b/patches/server/Fix-piston-physics-inconsistency-MC-188840.patch @@ -46,48 +46,50 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.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 { +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { } for (k = list.size() - 1; k >= 0; --k) { -- blockposition3 = (BlockPosition) list.get(k); -- iblockdata1 = world.getType(blockposition3); +- blockposition3 = (BlockPos) list.get(k); +- iblockdata1 = world.getBlockState(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; ++ BlockPos oldPos = blockposition3 = (BlockPos) list.get(k); ++ iblockdata1 = allowDesync ? world.getBlockState(oldPos) : null; + // Paper end - fix a variety of piston desync dupes - blockposition3 = blockposition3.shift(enumdirection1); + blockposition3 = blockposition3.relative(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)); + BlockState iblockdata2 = (BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(PistonBaseBlock.FACING, dir); + + world.setBlock(blockposition3, iblockdata2, 68); +- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition3, iblockdata2, (BlockState) list1.get(k), dir, retract, false)); + // Paper start - fix a variety of piston desync dupes + if (!allowDesync) { -+ iblockdata1 = world.getType(oldPos); ++ iblockdata1 = world.getBlockState(oldPos); + map.replace(oldPos, iblockdata1); + } -+ world.setTileEntity(blockposition3, BlockPistonMoving.a(allowDesync ? list1.get(k) : iblockdata1, enumdirection, flag, false)); ++ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(blockposition3, iblockdata2, allowDesync ? list1.get(k) : iblockdata1, dir, retract, false)); + if (!allowDesync) { -+ world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 2 | 4 | 16 | 1024); // set air to prevent later physics updates from seeing this block ++ world.setBlock(oldPos, Blocks.AIR.defaultBlockState(), 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 +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.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); +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -0,0 +0,0 @@ public class PistonMovingBlockEntity extends BlockEntity { + if (blockEntity.movedState != null && world.getBlockState(pos).is(Blocks.MOVING_PISTON)) { + BlockState blockState = Block.updateFromNeighbourShapes(blockEntity.movedState, world, pos); + if (blockState.isAir()) { +- world.setBlock(pos, blockEntity.movedState, 84); ++ world.setBlock(pos, blockEntity.movedState, 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.updateOrDestroy(blockEntity.movedState, blockState, world, pos, 3); } else { - if (iblockdata.b(BlockProperties.C) && (Boolean) iblockdata.get(BlockProperties.C)) { + if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED)) { diff --git a/patches/server/Fix-reducedDebugInfo-not-initialized-on-client.patch b/patches/server/Fix-reducedDebugInfo-not-initialized-on-client.patch new file mode 100644 index 0000000000..c9389be3fd --- /dev/null +++ b/patches/server/Fix-reducedDebugInfo-not-initialized-on-client.patch @@ -0,0 +1,18 @@ +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.send(new ClientboundSetCarriedItemPacket(player.getInventory().selected)); + playerconnection.send(new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes())); + playerconnection.send(new ClientboundUpdateTagsPacket(this.server.getTags().serializeToNetwork((RegistryAccess) this.registryHolder))); ++ playerconnection.send(new ClientboundEntityEventPacket(player, (byte) (worldserver1.getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23))); // Paper - fix this rule not being initialized on the client + this.sendPlayerPermissionLevel(player); + player.getStats().markAllDirty(); + player.getRecipeBook().sendInitialRecipeBook(player); diff --git a/Spigot-Server-Patches/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch b/patches/server/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch similarity index 90% rename from Spigot-Server-Patches/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch rename to patches/server/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch index 2a81479287..2be4ea33cd 100644 --- a/Spigot-Server-Patches/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch +++ b/patches/server/Fix-regex-mistake-in-CB-NBT-int-deserialization.patch @@ -16,12 +16,12 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNBTTagConfigSerializ 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; +@@ -0,0 +0,0 @@ import net.minecraft.nbt.TagParser; 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("")); + private static final TagParser MOJANGSON_PARSER = new TagParser(new StringReader("")); diff --git a/patches/server/Fix-sand-duping.patch b/patches/server/Fix-sand-duping.patch new file mode 100644 index 0000000000..8a8245a06d --- /dev/null +++ b/patches/server/Fix-sand-duping.patch @@ -0,0 +1,37 @@ +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/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity { + + @Override + public void tick() { ++ // Paper start - fix sand duping ++ if (this.isRemoved()) { ++ return; ++ } ++ // Paper end - fix sand duping + if (this.blockState.isAir()) { + this.discard(); + } else { +@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity { + + this.move(MoverType.SELF, this.getDeltaMovement()); + ++ // Paper start - fix sand duping ++ if (this.isRemoved()) { ++ return; ++ } ++ // Paper end - fix sand duping ++ + // Paper start - Configurable EntityFallingBlock height nerf + if (this.level.paperConfig.fallingBlockHeightNerf != 0 && this.getY() > this.level.paperConfig.fallingBlockHeightNerf) { + if (this.dropItem && this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { diff --git a/patches/server/Fix-some-rails-connecting-improperly.patch b/patches/server/Fix-some-rails-connecting-improperly.patch new file mode 100644 index 0000000000..b020b21597 --- /dev/null +++ b/patches/server/Fix-some-rails-connecting-improperly.patch @@ -0,0 +1,84 @@ +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/BaseRailBlock.java b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseRailBlock.java +@@ -0,0 +0,0 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl + state = this.updateDir(world, pos, state, true); + if (this.isStraight) { + state.neighborChanged(world, pos, this, pos, notify); ++ state = world.getBlockState(pos); // Paper - don't desync, update again + } + + return state; +diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +@@ -0,0 +0,0 @@ public class DetectorRailBlock extends BaseRailBlock { + + private void checkPressed(Level world, BlockPos pos, BlockState state) { + if (this.canSurvive(state, world, pos)) { ++ if (state.getBlock() != this) { return; } // Paper - not our block, don't do anything + boolean flag = (Boolean) state.getValue(DetectorRailBlock.POWERED); + boolean flag1 = false; + List list = this.getInteractingMinecartOfType(world, pos, AbstractMinecart.class, (entity) -> { +diff --git a/src/main/java/net/minecraft/world/level/block/RailState.java b/src/main/java/net/minecraft/world/level/block/RailState.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/RailState.java ++++ b/src/main/java/net/minecraft/world/level/block/RailState.java +@@ -0,0 +0,0 @@ public class RailState { + private final boolean isStraight; + private final List connections = Lists.newArrayList(); + ++ // Paper start - prevent desync ++ public boolean isValid() { ++ return this.level.getBlockState(this.pos).getBlock() == this.state.getBlock(); ++ } ++ // Paper end - prevent desync ++ + public RailState(Level world, BlockPos pos, BlockState state) { + this.level = world; + this.pos = pos; +@@ -0,0 +0,0 @@ public class RailState { + } + + private void connectTo(RailState placementHelper) { ++ // Paper start - prevent desync ++ if (!this.isValid() || !placementHelper.isValid()) { ++ return; ++ } ++ // Paper end - prevent desync + this.connections.add(placementHelper.pos); + BlockPos blockPos = this.pos.north(); + BlockPos blockPos2 = this.pos.south(); +@@ -0,0 +0,0 @@ public class RailState { + this.state = this.state.setValue(this.block.getShapeProperty(), railShape2); + if (forceUpdate || this.level.getBlockState(this.pos) != this.state) { + this.level.setBlock(this.pos, this.state, 3); ++ // Paper start - prevent desync ++ if (!this.isValid()) { ++ return this; ++ } ++ // Paper end - prevent desync + + for(int i = 0; i < this.connections.size(); ++i) { + RailState railState = this.getRail(this.connections.get(i)); +- if (railState != null) { ++ if (railState != null && railState.isValid()) { // Paper - prevent desync + railState.removeSoftConnections(); + if (railState.canConnectTo(this)) { + railState.connectTo(this); +@@ -0,0 +0,0 @@ public class RailState { + } + + public BlockState getState() { +- return this.state; ++ return this.level.getBlockState(this.pos); // Paper - prevent desync + } + } diff --git a/Spigot-Server-Patches/Fix-sounds-when-item-frames-are-modified-MC-123450.patch b/patches/server/Fix-sounds-when-item-frames-are-modified-MC-123450.patch similarity index 58% rename from Spigot-Server-Patches/Fix-sounds-when-item-frames-are-modified-MC-123450.patch rename to patches/server/Fix-sounds-when-item-frames-are-modified-MC-123450.patch index aac7b63a1a..a6ecbf58c5 100644 --- a/Spigot-Server-Patches/Fix-sounds-when-item-frames-are-modified-MC-123450.patch +++ b/patches/server/Fix-sounds-when-item-frames-are-modified-MC-123450.patch @@ -5,16 +5,16 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.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 { +--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +@@ -0,0 +0,0 @@ public class ItemFrame extends HangingEntity { } - this.getDataWatcher().set(EntityItemFrame.ITEM, itemstack); + this.getEntityData().set(ItemFrame.DATA_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); + this.playSound(this.getAddItemSound(), 1.0F, 1.0F); } diff --git a/Spigot-Server-Patches/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 87% rename from Spigot-Server-Patches/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to patches/server/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch index 05a729bd3c..631d1177ab 100644 --- a/Spigot-Server-Patches/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ b/patches/server/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -20,6 +20,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ? 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); + final BlockPos pos = new BlockPos(x, y, z); for (BlockFace dir : faces) { - IBlockData nmsBlock = world.getType(pos.shift(CraftBlock.blockFaceToNotch(dir))); + net.minecraft.world.level.block.state.BlockState nmsBlock = this.world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); diff --git a/Spigot-Server-Patches/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 53% rename from Spigot-Server-Patches/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to patches/server/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch index db9f230d16..1f2351fb8b 100644 --- a/Spigot-Server-Patches/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ b/patches/server/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -4,29 +4,29 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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; +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.lastSentHealth = -1.0F; + this.lastSentFood = -1; -+ setSneaking(false); // Paper - fix MC-10657 ++ setShiftKeyDown(false); // Paper - fix MC-10657 + // CraftBukkit start PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); - this.world.getServer().getPluginManager().callEvent(changeEvent); + this.level.getCraftServer().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.connection.send(new ClientboundUpdateMobEffectPacket(entityplayer.getId(), mobEffect)); } -+ entityplayer.setSneaking(false); // Paper - fix MC-10657 ++ entityplayer.setShiftKeyDown(false); // Paper - fix MC-10657 + // Fire advancement trigger - entityplayer.triggerDimensionAdvancements(((CraftWorld) fromWorld).getHandle()); + entityplayer.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); diff --git a/Spigot-Server-Patches/Fix-this-stupid-bullshit.patch b/patches/server/Fix-this-stupid-bullshit.patch similarity index 55% rename from Spigot-Server-Patches/Fix-this-stupid-bullshit.patch rename to patches/server/Fix-this-stupid-bullshit.patch index dbed0057de..25c7fdd43f 100644 --- a/Spigot-Server-Patches/Fix-this-stupid-bullshit.patch +++ b/patches/server/Fix-this-stupid-bullshit.patch @@ -8,13 +8,35 @@ Disable the 15 second sleep when the server jar hasn't been rebuilt within a per 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/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Bootstrap.java ++++ b/src/main/java/net/minecraft/server/Bootstrap.java +@@ -0,0 +0,0 @@ public class Bootstrap { + public static void bootStrap() { + if (!Bootstrap.isBootstrapped) { + // CraftBukkit start +- String name = Bootstrap.class.getSimpleName(); ++ /*String name = Bootstrap.class.getSimpleName(); // Paper - actually, I don't think this class should ever have been called DispenserRegistry, that's a stupid name, bootstrap is waaay better + switch (name) { + case "DispenserRegistry": + break; +@@ -0,0 +0,0 @@ public class Bootstrap { + System.err.println("*** WARNING: This server jar is unsupported, use at your own risk. ***"); + System.err.println("**********************************************************************"); + break; +- } ++ }*/ // Paper + // CraftBukkit end + Bootstrap.isBootstrapped = true; + if (Registry.REGISTRY.keySet().isEmpty()) { 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); + deadline.add(Calendar.DAY_OF_YEAR, -7); if (buildDate.before(deadline.getTime())) { - System.err.println("*** Error, this build is outdated ***"); + // Paper start - This is some stupid bullshit diff --git a/patches/server/Fix-villager-boat-exploit.patch b/patches/server/Fix-villager-boat-exploit.patch new file mode 100644 index 0000000000..2ab1f737b3 --- /dev/null +++ b/patches/server/Fix-villager-boat-exploit.patch @@ -0,0 +1,26 @@ +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 @@ public abstract class PlayerList { + PlayerList.LOGGER.debug("Removing player mount"); + entityplayer.stopRiding(); + entity.getPassengersAndSelf().forEach((entity1) -> { ++ // Paper start ++ if (entity1 instanceof net.minecraft.world.entity.npc.AbstractVillager) { ++ final net.minecraft.world.entity.npc.AbstractVillager villager = (net.minecraft.world.entity.npc.AbstractVillager) entity1; ++ final net.minecraft.world.entity.player.Player human = villager.getTradingPlayer(); ++ if (human != null) { ++ villager.setTradingPlayer(null); ++ } ++ } ++ // Paper end + entity1.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER); + }); + } diff --git a/Spigot-Server-Patches/Fix-villager-trading-demand-MC-163962.patch b/patches/server/Fix-villager-trading-demand-MC-163962.patch similarity index 64% rename from Spigot-Server-Patches/Fix-villager-trading-demand-MC-163962.patch rename to patches/server/Fix-villager-trading-demand-MC-163962.patch index f0a985f29b..f1b2d790d5 100644 --- a/Spigot-Server-Patches/Fix-villager-trading-demand-MC-163962.patch +++ b/patches/server/Fix-villager-trading-demand-MC-163962.patch @@ -5,16 +5,16 @@ 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 +diff --git a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.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 { +--- a/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java ++++ b/src/main/java/net/minecraft/world/item/trading/MerchantOffer.java +@@ -0,0 +0,0 @@ public class MerchantOffer { } - public void e() { + public void updateDemand() { - 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() { + public ItemStack assemble() { diff --git a/patches/server/Fixed-TileEntityBell-memory-leak.patch b/patches/server/Fixed-TileEntityBell-memory-leak.patch new file mode 100644 index 0000000000..bbda4937fb --- /dev/null +++ b/patches/server/Fixed-TileEntityBell-memory-leak.patch @@ -0,0 +1,39 @@ +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/BellBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -0,0 +0,0 @@ public class BellBlockEntity extends BlockEntity { + + if (blockEntity.ticks >= 50) { + blockEntity.shaking = false; ++ // Paper start ++ if (!blockEntity.resonating) { ++ blockEntity.nearbyEntities.clear(); ++ } ++ // Paper end + blockEntity.ticks = 0; + } + +@@ -0,0 +0,0 @@ public class BellBlockEntity extends BlockEntity { + ++blockEntity.resonationTicks; + } else { + bellEffect.run(world, pos, blockEntity.nearbyEntities); ++ blockEntity.nearbyEntities.clear(); // Paper + blockEntity.resonating = false; + } + } +@@ -0,0 +0,0 @@ public class BellBlockEntity extends BlockEntity { + } + } + ++ this.nearbyEntities.removeIf(e -> !e.isAlive()); // Paper + } + + private static boolean areRaidersNearby(BlockPos pos, List hearingEntities) { diff --git a/Spigot-Server-Patches/Flag-to-disable-the-channel-limit.patch b/patches/server/Flag-to-disable-the-channel-limit.patch similarity index 77% rename from Spigot-Server-Patches/Flag-to-disable-the-channel-limit.patch rename to patches/server/Flag-to-disable-the-channel-limit.patch index 32a02c51e3..e73ce09e34 100644 --- a/Spigot-Server-Patches/Flag-to-disable-the-channel-limit.patch +++ b/patches/server/Flag-to-disable-the-channel-limit.patch @@ -19,13 +19,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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) { + public CraftPlayer(CraftServer server, ServerPlayer 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 +- Preconditions.checkState(this.channels.size() < 128, "Cannot register channel '%s'. Too many channels registered!", channel); ++ Preconditions.checkState(DISABLE_CHANNEL_LIMIT || this.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)) { + if (this.channels.add(channel)) { server.getPluginManager().callEvent(new PlayerRegisterChannelEvent(this, channel)); diff --git a/Spigot-Server-Patches/Further-improve-server-tick-loop.patch b/patches/server/Further-improve-server-tick-loop.patch similarity index 79% rename from Spigot-Server-Patches/Further-improve-server-tick-loop.patch rename to patches/server/Further-improve-server-tick-loop.patch index 3d8fe2a992..587a39567c 100644 --- a/Spigot-Server-Patches/Further-improve-server-tick-loop.patch +++ b/patches/server/Further-improve-server-tick-loop.patch @@ -15,7 +15,7 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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 + if (i > 5000L && this.nextTickTime - this.lastOverloadWarning >= 30000L) { // CraftBukkit long j = i / 50L; - if (server.getWarnOnOverload()) // CraftBukkit + if (this.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; + this.nextTickTime += j * 50L; + this.lastOverloadWarning = this.nextTickTime; } -- if ( tickCount++ % SAMPLE_INTERVAL == 0 ) -+ if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 ) +- if ( tickCount++ % MinecraftServer.SAMPLE_INTERVAL == 0 ) ++ if ( ++MinecraftServer.currentTick % MinecraftServer.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) +- double currentTps = 1E3 / ( curTime - tickSection ) * MinecraftServer.SAMPLE_INTERVAL; +- this.recentTps[0] = MinecraftServer.calcTps( this.recentTps[0], 0.92, currentTps ); // 1/exp(5sec/1min) +- this.recentTps[1] = MinecraftServer.calcTps( this.recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) +- this.recentTps[2] = MinecraftServer.calcTps( this.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(); ++ this.recentTps[0] = tps1.getAverage(); ++ this.recentTps[1] = tps5.getAverage(); ++ this.recentTps[2] = tps15.getAverage(); + // Paper end tickSection = curTime; } // Spigot end +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { diff --git a/patches/server/Generator-Settings.patch b/patches/server/Generator-Settings.patch new file mode 100644 index 0000000000..797b08595d --- /dev/null +++ b/patches/server/Generator-Settings.patch @@ -0,0 +1,165 @@ +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 disableRelativeProjectileVelocity() { + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + } ++ ++ public boolean generateFlatBedrock; ++ private void generatorSettings() { ++ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); ++ } + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + this.markPositionReplaceable(pos); +- return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); ++ return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level)); // Paper - add level + // Paper start - Async chunk io + }; + CompletableFuture> ret = new CompletableFuture<>(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -0,0 +0,0 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + return GameEventDispatcher.NOOP; + } + ++ // Paper start ++ default boolean generateFlatBedrock() { ++ if (this instanceof ProtoChunk) { ++ return ((ProtoChunk)this).level.paperConfig.generateFlatBedrock; ++ } else if (this instanceof LevelChunk) { ++ return ((LevelChunk)this).level.paperConfig.generateFlatBedrock; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -0,0 +0,0 @@ public class ImposterProtoChunk extends ProtoChunk { + private final LevelChunk wrapped; + + public ImposterProtoChunk(LevelChunk wrapped) { +- super(wrapped.getPos(), UpgradeData.EMPTY, wrapped); ++ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped, wrapped.level); // Paper - add level + this.wrapped = wrapped; + } + +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 ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks = new Object2ObjectArrayMap<>(); + private volatile boolean isLightCorrect; ++ final net.minecraft.world.level.Level level; // Paper - Add level + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { ++ // Paper start - add level ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); } ++ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) { ++ // Paper end + this(pos, upgradeData, (LevelChunkSection[])null, new ProtoTickList<>((block) -> { + return block == null || block.defaultBlockState().isAir(); + }, pos, world), new ProtoTickList<>((fluid) -> { + return fluid == null || fluid == Fluids.EMPTY; +- }, pos, world), world); ++ }, pos, world), world, level); // Paper - add level + } + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world) { ++ // Paper start - add level ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world) { this(pos, upgradeData, levelChunkSections, blockTickScheduler, fluidTickScheduler, world, null); } ++ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) { ++ this.level = level; ++ // Paper end + this.chunkPos = pos; + this.upgradeData = upgradeData; + this.blockTicks = blockTickScheduler; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); ++ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level + + protochunk.setBiomes(biomestorage); + object = protochunk; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + int j = chunk.getPos().getMinBlockZ(); + NoiseGeneratorSettings noiseGeneratorSettings = this.settings.get(); + int k = noiseGeneratorSettings.noiseSettings().minY(); +- int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); +- int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); ++ int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); final int floorHeight = k; // Paper ++ int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); final int roofHeight = l; // Paper + int n = 5; + int o = chunk.getMinBuildHeight(); + int p = chunk.getMaxBuildHeight(); +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + for(BlockPos blockPos : BlockPos.betweenClosed(i, 0, j, i + 15, 0, j + 15)) { + if (bl) { + for(int q = 0; q < 5; ++q) { +- if (q <= random.nextInt(5)) { ++ if (q <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof + chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), m - q, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + if (bl2) { + for(int r = 4; r >= 0; --r) { +- if (r <= random.nextInt(5)) { ++ if (r <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor + chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), l + r, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + if (l <= 0) { + return CompletableFuture.completedFuture(chunk); + } else { +- int m = chunk.getSectionIndex(l * this.cellHeight - 1 + i); ++ int mStart = chunk.getSectionIndex(l * this.cellHeight - 1 + i); // Paper - decompile fix + int n = chunk.getSectionIndex(i); + return CompletableFuture.supplyAsync(() -> { + Set set = Sets.newHashSet(); + + ChunkAccess var16; + try { +- for(int m = m; m >= n; --m) { ++ for(int m = mStart; m >= n; --m) { // Paper - decompile fix + LevelChunkSection levelChunkSection = chunk.getOrCreateSection(m); + levelChunkSection.acquire(); + set.add(levelChunkSection); diff --git a/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch new file mode 100644 index 0000000000..f9dcb477ab --- /dev/null +++ b/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch @@ -0,0 +1,54 @@ +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/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { + + public ChunkSerializer() {} + ++ // Paper start - guard against serializing mismatching coordinates ++ // TODO Note: This needs to be re-checked each update ++ public static ChunkPos getChunkCoordinate(CompoundTag chunkData) { ++ CompoundTag levelData = chunkData.getCompound("Level"); ++ return new ChunkPos(levelData.getInt("xPos"), levelData.getInt("zPos")); ++ } ++ // Paper end + // Paper start + public static final class InProgressChunkHolder { + +@@ -0,0 +0,0 @@ public class ChunkSerializer { + // Paper end + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); +- CompoundTag nbttagcompound1 = nbt.getCompound("Level"); +- ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); ++ CompoundTag nbttagcompound1 = nbt.getCompound("Level"); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate + + if (!Objects.equals(pos, chunkcoordintpair1)) { + ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1); +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +@@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { + + // Paper start - async chunk io + public void write(ChunkPos chunkPos, CompoundTag nbt) throws IOException { ++ // Paper start ++ if (!chunkPos.equals(ChunkSerializer.getChunkCoordinate(nbt))) { ++ String world = (this instanceof net.minecraft.server.level.ChunkMap) ? ((net.minecraft.server.level.ChunkMap)this).level.getWorld().getName() : null; ++ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkPos.toString() ++ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbt).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); ++ } ++ // Paper end + this.regionFileCache.write(chunkPos, nbt); + // Paper end - Async chunk loading + if (this.legacyStructureHandler != null) { diff --git a/patches/server/Guardian-beam-workaround.patch b/patches/server/Guardian-beam-workaround.patch new file mode 100644 index 0000000000..0ef9e00956 --- /dev/null +++ b/patches/server/Guardian-beam-workaround.patch @@ -0,0 +1,20 @@ +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/ClientboundSetTimePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTimePacket.java +@@ -0,0 +0,0 @@ public class ClientboundSetTimePacket implements Packet enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); -+ private void processEnchantOrder(NBTTagCompound tag) { -+ if (tag == null || !tag.hasKeyOfType("Enchantments", 9)) { ++ private static final java.util.Comparator enchantSorter = java.util.Comparator.comparing(o -> o.getString("id")); ++ private void processEnchantOrder(CompoundTag tag) { ++ if (tag == null || !tag.contains("Enchantments", 9)) { + return; + } -+ NBTTagList list = tag.getList("Enchantments", 10); ++ ListTag list = tag.getList("Enchantments", 10); + if (list.size() < 2) { + return; + } + try { + //noinspection unchecked -+ list.sort((Comparator) enchantSorter); // Paper ++ list.sort((Comparator) enchantSorter); // Paper + } catch (Exception ignored) {} + } + // Paper end + - public ItemStack(IMaterial imaterial) { - this(imaterial, 1); + public ItemStack(ItemLike item) { + this(item, 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); + this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); // CraftBukkit end ++ this.processEnchantOrder(this.tag); // Paper + this.getItem().verifyTagAfterLoad(this.tag); } + @@ -0,0 +0,0 @@ public final class ItemStack { // Paper end - public void setTag(@Nullable NBTTagCompound nbttagcompound) { - this.tag = nbttagcompound; + public void setTag(@Nullable CompoundTag tag) { + this.tag = tag; + processEnchantOrder(this.tag); // Paper - if (this.getItem().usesDurability()) { - this.setDamage(this.getDamage()); + if (this.getItem().canBeDepleted()) { + this.setDamageValue(this.getDamageValue()); } @@ -0,0 +0,0 @@ public final class ItemStack { - nbttagcompound.setString("id", String.valueOf(IRegistry.ENCHANTMENT.getKey(enchantment))); - nbttagcompound.setShort("lvl", (short) ((byte) i)); + nbttagcompound.putString("id", String.valueOf(Registry.ENCHANTMENT.getKey(enchantment))); + nbttagcompound.putShort("lvl", (short) ((byte) level)); nbttaglist.add(nbttagcompound); + processEnchantOrder(nbttagcompound); // Paper } - public boolean hasEnchantments() { + public boolean isEnchanted() { 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 @@ import java.util.Map; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.ListTag; + import net.minecraft.world.item.Item; +-import net.minecraft.world.item.enchantment.EnchantmentHelper; + import org.apache.commons.lang.Validate; + import org.bukkit.Material; + import org.bukkit.configuration.serialization.DelegateDeserialization; @@ -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)) { +- if (!CraftItemStack.makeTag(this.handle)) { - return; - } -- NBTTagList list = getEnchantmentList(handle); +- ListTag list = CraftItemStack.getEnchantmentList(this.handle); - if (list == null) { -- list = new NBTTagList(); -- handle.getTag().set(ENCHANTMENTS.NBT, list); +- list = new ListTag(); +- this.handle.getTag().put(ENCHANTMENTS.NBT, list); - } - int size = list.size(); - - for (int i = 0; i < size; i++) { -- NBTTagCompound tag = (NBTTagCompound) list.get(i); +- CompoundTag tag = (CompoundTag) list.get(i); - String id = tag.getString(ENCHANTMENTS_ID.NBT); - if (id.equals(ench.getKey().toString())) { -- tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level); +- tag.putShort(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); +- CompoundTag tag = new CompoundTag(); +- tag.putString(ENCHANTMENTS_ID.NBT, ench.getKey().toString()); +- tag.putShort(ENCHANTMENTS_LVL.NBT, (short) level); - list.add(tag); + // Paper start - Replace whole method -+ final ItemMeta itemMeta = getItemMeta(); ++ final ItemMeta itemMeta = this.getItemMeta(); + itemMeta.addEnchant(ench, level, true); -+ setItemMeta(itemMeta); ++ this.setItemMeta(itemMeta); + // Paper end } @@ -120,25 +128,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean containsEnchantment(Enchantment ench) { -- return getEnchantmentLevel(ench) > 0; -+ return hasItemMeta() && getItemMeta().hasEnchant(ench); // Paper - use meta +- return this.getEnchantmentLevel(ench) > 0; ++ return this.hasItemMeta() && this.getItemMeta().hasEnchant(ench); // Paper - use meta } @Override public int getEnchantmentLevel(Enchantment ench) { - Validate.notNull(ench, "Cannot find null enchantment"); -- if (handle == null) { +- if (this.handle == null) { - return 0; - } -- return EnchantmentManager.getEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); -+ return hasItemMeta() ? getItemMeta().getEnchantLevel(ench) : 0; // Paper - replace entire method with meta +- return EnchantmentHelper.getItemEnchantmentLevel(CraftEnchantment.getRaw(ench), handle); ++ return this.hasItemMeta() ? this.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; +- ListTag list = CraftItemStack.getEnchantmentList(this.handle), listCopy; - if (list == null) { - return 0; - } @@ -147,7 +155,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - int size = list.size(); - - for (int i = 0; i < size; i++) { -- NBTTagCompound enchantment = (NBTTagCompound) list.get(i); +- CompoundTag enchantment = (CompoundTag) list.get(i); - String id = enchantment.getString(ENCHANTMENTS_ID.NBT); - if (id.equals(ench.getKey().toString())) { - index = i; @@ -160,27 +168,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - return 0; - } - if (size == 1) { -- handle.getTag().remove(ENCHANTMENTS.NBT); -- if (handle.getTag().isEmpty()) { -- handle.setTag(null); +- this.handle.getTag().remove(ENCHANTMENTS.NBT); +- if (this.handle.getTag().isEmpty()) { +- this.handle.setTag(null); - } - return level; - } - - // This is workaround for not having an index removal -- listCopy = new NBTTagList(); +- listCopy = new ListTag(); - for (int i = 0; i < size; i++) { - if (i != index) { - listCopy.add(list.get(i)); - } + // Paper start - replace entire method -+ final ItemMeta itemMeta = getItemMeta(); ++ final ItemMeta itemMeta = this.getItemMeta(); + int level = itemMeta.getEnchantLevel(ench); + if (level > 0) { + itemMeta.removeEnchant(ench); -+ setItemMeta(itemMeta); ++ this.setItemMeta(itemMeta); } -- handle.getTag().set(ENCHANTMENTS.NBT, listCopy); +- this.handle.getTag().put(ENCHANTMENTS.NBT, listCopy); + // Paper end return level; @@ -188,8 +196,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Map getEnchantments() { -- return getEnchantments(handle); -+ return hasItemMeta() ? getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta +- return CraftItemStack.getEnchantments(this.handle); ++ return this.hasItemMeta() ? this.getItemMeta().getEnchants() : ImmutableMap.of(); // Paper - use Item Meta } static Map getEnchantments(net.minecraft.world.item.ItemStack item) { @@ -224,7 +232,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 CompoundTag blockData; - private Map enchantments; + private EnchantmentMap enchantments; // Paper private Multimap attributeModifiers; @@ -233,10 +241,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 CompoundTag internalTag; +- private final Map unhandledTags = new HashMap(); ++ private final Map unhandledTags = new TreeMap<>(); // Paper + private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftMetaItem.DATA_TYPE_REGISTRY); private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @@ -252,18 +260,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -- static Map buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { -+ static EnchantmentMap buildEnchantments(NBTTagCompound tag, ItemMetaKey key) { // Paper - if (!tag.hasKey(key.NBT)) { +- static Map buildEnchantments(CompoundTag tag, ItemMetaKey key) { ++ static EnchantmentMap buildEnchantments(CompoundTag tag, ItemMetaKey key) { // Paper + if (!tag.contains(key.NBT)) { return null; } - NBTTagList ench = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); + ListTag 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); + String id = ((CompoundTag) ench.get(i)).getString(ENCHANTMENTS_ID.NBT); @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } } @@ -284,16 +292,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Map getEnchants() { -- return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); -+ return hasEnchants() ? ImmutableSortedMap.copyOfSorted(enchantments) : ImmutableMap.of(); // Paper +- return this.hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.of(); ++ return this.hasEnchants() ? ImmutableSortedMap.copyOfSorted(this.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 (this.enchantments == null) { +- this.enchantments = new LinkedHashMap(4); ++ this.enchantments = new EnchantmentMap(); // Paper } if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { @@ -307,7 +315,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.hasAttributeModifiers()) { clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return HANDLED_TAGS; + return CraftMetaItem.HANDLED_TAGS; } } + diff --git a/patches/server/Handle-Large-Packets-disconnecting-client.patch b/patches/server/Handle-Large-Packets-disconnecting-client.patch new file mode 100644 index 0000000000..6924db6030 --- /dev/null +++ b/patches/server/Handle-Large-Packets-disconnecting-client.patch @@ -0,0 +1,115 @@ +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/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { ++ // Paper start ++ if (throwable instanceof io.netty.handler.codec.EncoderException && throwable.getCause() instanceof PacketEncoder.PacketTooLargeException) { ++ if (((PacketEncoder.PacketTooLargeException) throwable.getCause()).getPacket().packetTooLarge(this)) { ++ return; ++ } else { ++ throwable = throwable.getCause(); ++ } ++ } ++ // Paper end + if (throwable instanceof SkipPacketException) { + Connection.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 var9; + } + } ++ ++ // Paper start ++ int packetLength = friendlyByteBuf.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 handle(T listener); + ++ // Paper start ++ default boolean packetTooLarge(net.minecraft.network.Connection manager) { ++ return false; ++ } ++ // Paper end ++ + default boolean isSkippable() { + return false; + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundContainerSetContentPacket.java +@@ -0,0 +0,0 @@ public class ClientboundContainerSetContentPacket implements Packet items; + ++ //Paper start ++ @Override ++ public boolean packetTooLarge(net.minecraft.network.Connection manager) { ++ for (int i = 0 ; i < this.items.size() ; i++) { ++ manager.send(new ClientboundContainerSetSlotPacket(this.containerId, i, this.items.get(i))); ++ } ++ return true; ++ } ++ // Paper end ++ + public ClientboundContainerSetContentPacket(int syncId, NonNullList contents) { + this.containerId = syncId; + this.items = NonNullList.withSize(contents.size(), ItemStack.EMPTY); +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet 2097152) { ++ if (i > 2097152) { // Paper - diff on change - if this changes, update PacketEncoder + throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); + } else { + this.buffer = new byte[i]; diff --git a/patches/server/Handle-Oversized-Tile-Entities-in-chunks.patch b/patches/server/Handle-Oversized-Tile-Entities-in-chunks.patch new file mode 100644 index 0000000000..080cde99cd --- /dev/null +++ b/patches/server/Handle-Oversized-Tile-Entities-in-chunks.patch @@ -0,0 +1,50 @@ +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/ClientboundLevelChunkPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLevelChunkPacket.java +@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet blockEntitiesTags; ++ // 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 ClientboundLevelChunkPacket(LevelChunk chunk) { + ChunkPos chunkPos = chunk.getPos(); +@@ -0,0 +0,0 @@ public class ClientboundLevelChunkPacket implements Packet entry2 : chunk.getBlockEntities().entrySet()) { + BlockEntity blockEntity = entry2.getValue(); ++ // Paper start - improve oversized chunk data packet handling ++ if (++totalTileEntities > TE_LIMIT) { ++ ClientboundBlockEntityDataPacket updatePacket = blockEntity.getUpdatePacket(); ++ if (updatePacket != null) { ++ this.extraPackets.add(updatePacket); ++ continue; ++ } ++ } ++ // Paper end + CompoundTag compoundTag = blockEntity.getUpdateTag(); + if (blockEntity instanceof net.minecraft.world.level.block.entity.SkullBlockEntity) { net.minecraft.world.level.block.entity.SkullBlockEntity.sanitizeTileEntityUUID(compoundTag); } // Paper + this.blockEntitiesTags.add(compoundTag); diff --git a/Spigot-Server-Patches/Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch similarity index 82% rename from Spigot-Server-Patches/Handle-plugin-prefixes-using-Log4J-configuration.patch rename to patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch index 67a82a57ab..708e0afffa 100644 --- a/Spigot-Server-Patches/Handle-plugin-prefixes-using-Log4J-configuration.patch +++ b/patches/server/Handle-plugin-prefixes-using-Log4J-configuration.patch @@ -14,19 +14,19 @@ 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 +diff --git a/build.gradle.kts b/build.gradle.kts 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 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + all its classes to check if they are plugins. + Scanning takes about 1-2 seconds so adding this speeds up the server start. + */ +- runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1") ++ implementation("org.apache.logging.log4j:log4j-core:2.14.1") // Paper - implementation + // Paper end + implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper + implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper 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 @@ -34,8 +34,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 ); + SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 ); +- System.out.println( "Server Ping Player Sample Count: " + SpigotConfig.playerSample ); + Bukkit.getLogger().log( Level.INFO, "Server Ping Player Sample Count: {0}", playerSample ); // Paper - Use logger } diff --git a/Spigot-Server-Patches/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch b/patches/server/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch similarity index 61% rename from Spigot-Server-Patches/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch rename to patches/server/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch index 804a77eb7c..456703fca0 100644 --- a/Spigot-Server-Patches/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch +++ b/patches/server/Have-CraftMerchantCustom-emit-PlayerPurchaseEvent.patch @@ -4,19 +4,6 @@ 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 @@ -24,14 +11,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftMerchantCustom extends CraftMerchant { @Override - public void a(MerchantRecipe merchantrecipe) { + public void notifyTrade(MerchantOffer offer) { + // 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(); ++ if (getTradingPlayer() instanceof net.minecraft.server.level.ServerPlayer) { ++ final net.minecraft.server.level.ServerPlayer trader = (net.minecraft.server.level.ServerPlayer) getTradingPlayer(); + final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent( + trader.getBukkitEntity(), -+ merchantrecipe.asBukkit(), ++ offer.asBukkit(), + false, // reward xp? + true); // should increase uses? + event.callEvent(); @@ -45,9 +32,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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, ++ final Level world = trader.getCommandSenderWorld(); ++ world.addFreshEntity(new net.minecraft.world.entity.ExperienceOrb( ++ world, trader.getX(), trader.getY() + 0.5d, trader.getZ(), xp, + org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null)); + } + return; @@ -55,5 +42,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + // increase recipe's uses - merchantrecipe.increaseUses(); + offer.increaseUses(); } diff --git a/patches/server/Here-s-Johnny.patch b/patches/server/Here-s-Johnny.patch new file mode 100644 index 0000000000..5e3ddcbacc --- /dev/null +++ b/patches/server/Here-s-Johnny.patch @@ -0,0 +1,25 @@ +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/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().isJohnny = johnny; ++ } ++ // Paper end + } diff --git a/Spigot-Server-Patches/Hide-sync-chunk-writes-behind-flag.patch b/patches/server/Hide-sync-chunk-writes-behind-flag.patch similarity index 52% rename from Spigot-Server-Patches/Hide-sync-chunk-writes-behind-flag.patch rename to patches/server/Hide-sync-chunk-writes-behind-flag.patch index 6c68bfef29..b828a45af7 100644 --- a/Spigot-Server-Patches/Hide-sync-chunk-writes-behind-flag.patch +++ b/patches/server/Hide-sync-chunk-writes-behind-flag.patch @@ -12,12 +12,12 @@ diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServerPropert 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); +@@ -0,0 +0,0 @@ public class DedicatedServerProperties extends Settings { + return Mth.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) -> { +- this.syncChunkWrites = this.get("sync-chunk-writes", true); ++ this.syncChunkWrites = this.get("sync-chunk-writes", true) && Boolean.getBoolean("Paper.enable-sync-chunk-writes"); // Paper - hide behind flag + this.enableJmxMonitoring = this.get("enable-jmx-monitoring", false); + this.enableStatus = this.get("enable-status", true); + this.entityBroadcastRangePercentage = this.get("entity-broadcast-range-percentage", (integer) -> { diff --git a/Spigot-Server-Patches/Honor-EntityAgeable.ageLock.patch b/patches/server/Honor-EntityAgeable.ageLock.patch similarity index 51% rename from Spigot-Server-Patches/Honor-EntityAgeable.ageLock.patch rename to patches/server/Honor-EntityAgeable.ageLock.patch index 3074961968..63591cda09 100644 --- a/Spigot-Server-Patches/Honor-EntityAgeable.ageLock.patch +++ b/patches/server/Honor-EntityAgeable.ageLock.patch @@ -4,14 +4,14 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/AgeableMob.java b/src/main/java/net/minecraft/world/entity/AgeableMob.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 { +--- a/src/main/java/net/minecraft/world/entity/AgeableMob.java ++++ b/src/main/java/net/minecraft/world/entity/AgeableMob.java +@@ -0,0 +0,0 @@ public abstract class AgeableMob extends PathfinderMob { } - public void setAge(int i, boolean flag) { + public void ageUp(int age, boolean overGrow) { + 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/patches/server/Hook-into-CB-plugin-rewrites.patch similarity index 100% rename from Spigot-Server-Patches/Hook-into-CB-plugin-rewrites.patch rename to patches/server/Hook-into-CB-plugin-rewrites.patch diff --git a/Spigot-Server-Patches/Implement-API-to-expose-exact-interaction-point.patch b/patches/server/Implement-API-to-expose-exact-interaction-point.patch similarity index 53% rename from Spigot-Server-Patches/Implement-API-to-expose-exact-interaction-point.patch rename to patches/server/Implement-API-to-expose-exact-interaction-point.patch index 3b18238515..5571d60ecc 100644 --- a/Spigot-Server-Patches/Implement-API-to-expose-exact-interaction-point.patch +++ b/patches/server/Implement-API-to-expose-exact-interaction-point.patch @@ -4,43 +4,43 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.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 { +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { 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(); +- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand); ++ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation()); // Paper + this.firedInteract = true; + this.interactResult = event.useItemInHand() == Event.Result.DENY; + this.interactPosition = blockposition.immutable(); 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; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.EntityHitResult; + import net.minecraft.world.phys.HitResult; ++import net.minecraft.world.phys.Vec3; import 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); + return CraftEventFactory.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) { + public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand 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) { ++ public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand, Vec3 hitVec) { + // Paper end Player player = (who == null) ? null : (Player) who.getBukkitEntity(); CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); @@ -49,10 +49,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 itemInHand = null; } -- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == EnumHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); +- PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.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); ++ PlayerInteractEvent event = new PlayerInteractEvent(player, action, itemInHand, blockClicked, blockFace, (hand == null) ? null : ((hand == InteractionHand.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/patches/server/Implement-API-to-get-Material-from-Boats-and-Minecar.patch similarity index 64% rename from Spigot-Server-Patches/Implement-API-to-get-Material-from-Boats-and-Minecar.patch rename to patches/server/Implement-API-to-get-Material-from-Boats-and-Minecar.patch index ac3f58e31b..1d915b84ee 100644 --- a/Spigot-Server-Patches/Implement-API-to-get-Material-from-Boats-and-Minecar.patch +++ b/patches/server/Implement-API-to-get-Material-from-Boats-and-Minecar.patch @@ -4,47 +4,24 @@ 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; + this.getHandle().landBoats = workOnLand; } + // Paper start + @Override -+ public Material getBoatMaterial() { -+ return CraftMagicNumbers.getMaterial(getHandle().getBoatItem()); ++ public org.bukkit.Material getBoatMaterial() { ++ return org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(getHandle().getDropItem()); + } + // Paper end + @Override - public EntityBoat getHandle() { - return (EntityBoat) entity; + public net.minecraft.world.entity.vehicle.Boat getHandle() { + return (net.minecraft.world.entity.vehicle.Boat) 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 @@ -52,16 +29,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ package org.bukkit.craftbukkit.entity; - import net.minecraft.world.entity.vehicle.EntityMinecartAbstract; + import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.item.Items; // Paper import net.minecraft.world.level.block.Blocks; - import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.block.state.BlockState; +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); + this.getHandle().setDerailedVelocityMod(derailed); } + // Paper start @@ -97,5 +74,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + @Override - public EntityMinecartAbstract getHandle() { - return (EntityMinecartAbstract) entity; + public AbstractMinecart getHandle() { + return (AbstractMinecart) entity; diff --git a/patches/server/Implement-BlockPreDispenseEvent.patch b/patches/server/Implement-BlockPreDispenseEvent.patch new file mode 100644 index 0000000000..1d8c2cfee7 --- /dev/null +++ b/patches/server/Implement-BlockPreDispenseEvent.patch @@ -0,0 +1,34 @@ +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/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +@@ -0,0 +0,0 @@ public class DispenserBlock extends BaseEntityBlock { + DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); + + if (idispensebehavior != DispenseItemBehavior.NOOP) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here + DispenserBlock.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 @@ public class CraftEventFactory { + io.papermc.paper.event.block.BlockFailedDispenseEvent event = new io.papermc.paper.event.block.BlockFailedDispenseEvent(block); + return event.callEvent(); + } ++ ++ public static boolean handleBlockPreDispenseEvent(ServerLevel serverLevel, BlockPos pos, ItemStack itemStack, int slot) { ++ org.bukkit.block.Block block = serverLevel.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); ++ io.papermc.paper.event.block.BlockPreDispenseEvent event = new io.papermc.paper.event.block.BlockPreDispenseEvent(block, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), slot); ++ return event.callEvent(); ++ } + // Paper end + } diff --git a/patches/server/Implement-Brigadier-Mojang-API.patch b/patches/server/Implement-Brigadier-Mojang-API.patch new file mode 100644 index 0000000000..42ad6c4c98 --- /dev/null +++ b/patches/server/Implement-Brigadier-Mojang-API.patch @@ -0,0 +1,151 @@ +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/build.gradle.kts b/build.gradle.kts +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ repositories { + + dependencies { + implementation(project(":Paper-API")) ++ implementation(project(":Paper-MojangAPI")) + // Paper start + implementation("org.jline:jline-terminal-jansi:3.12.1") + implementation("net.minecrell:terminalconsoleappender:1.2.0") +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -0,0 +0,0 @@ import net.minecraft.world.phys.Vec2; + import net.minecraft.world.phys.Vec3; + import com.mojang.brigadier.tree.CommandNode; // CraftBukkit + +-public class CommandSourceStack implements SharedSuggestionProvider { ++public class CommandSourceStack implements SharedSuggestionProvider, com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource { // Paper + + public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.player")); + public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(new TranslatableComponent("permissions.requires.entity")); +@@ -0,0 +0,0 @@ public class CommandSourceStack implements SharedSuggestionProvider { + return this.textName; + } + ++ // Paper start ++ @Override ++ public org.bukkit.entity.Entity getBukkitEntity() { ++ return getEntity() != null ? getEntity().getBukkitEntity() : null; ++ } ++ ++ @Override ++ public org.bukkit.World getBukkitWorld() { ++ return getLevel() != null ? getLevel().getWorld() : null; ++ } ++ ++ @Override ++ public org.bukkit.Location getBukkitLocation() { ++ Vec3 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 level) { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -0,0 +0,0 @@ public class Commands { + 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 Commands { + + private void runSync(ServerPlayer 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/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + + this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); ++ // Paper start ++ com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), (com.mojang.brigadier.suggestion.Suggestions) suggestEvent.getSuggestions())); // CraftBukkit - decompile error // Paper ++ // Paper end + }); + }); + } +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + 1); + completions.forEach(builder::suggest); +- player.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), 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.getCraftPlayer(), suggestions, buffer); ++ suggestEvent.setCancelled(suggestions.isEmpty()); ++ if (!suggestEvent.callEvent()) return; ++ this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), 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.CommandSourceStack; + 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/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch b/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch new file mode 100644 index 0000000000..361a411e76 --- /dev/null +++ b/patches/server/Implement-Chunk-Priority-Urgency-System-for-Chunks.patch @@ -0,0 +1,1196 @@ +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, ChunkHolder chunkHolder, int x, int z) { +- dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 1); ++ dumpChunkInfo(seenChunks, chunkHolder, x, z, 0, 4); // Paper - 1->4 + } + + static void dumpChunkInfo(Set seenChunks, ChunkHolder 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.getStatus().toString())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Ticket Status - " + ChunkHolder.getStatus(chunkHolder.getTicketLevel())); + PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Status - " + ((holderStatus == null) ? "null" : holderStatus.toString())); ++ // Paper start ++ PaperFileIOThread.LOGGER.log(Level.ERROR, indentStr + "Chunk Holder Priority - " + chunkHolder.queueLevel); ++ ++ 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 (ChunkHolder neighbor : chunkHolder.neighbors.keySet()) { ++ ChunkStatus status = neighbor.getChunkHolderStatus(); ++ if (status != null && status.isOrAfter(ChunkHolder.getStatus(neighbor.getTicketLevel()))) { ++ continue; ++ } ++ int nx = neighbor.pos.x; ++ int nz = neighbor.pos.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); ++ } ++ } ++ // Paper end + } + } + +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.pos.x); + chunkData.addProperty("z", playerChunk.pos.z); + chunkData.addProperty("ticket-level", playerChunk.getTicketLevel()); ++ chunkData.addProperty("priority", playerChunk.queueLevel); // Paper - priority + chunkData.addProperty("state", ChunkHolder.getFullChunkStatus(playerChunk.getTicketLevel()).toString()); + chunkData.addProperty("queued-for-unload", chunkMap.toDrop.contains(playerChunk.pos.longKey)); + chunkData.addProperty("status", status == null ? "unloaded" : status.toString()); +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + private final DebugBuffer chunkToSaveHistory; + public int oldTicketLevel; + private int ticketLevel; +- private int queueLevel; ++ public volatile int queueLevel; // Paper - private->public, make volatile since this is concurrently accessed + public final ChunkPos pos; + private boolean hasChangedSections; + private final ShortSet[] changedBlocksPerSection; +@@ -0,0 +0,0 @@ public class ChunkHolder { + + boolean isUpdateQueued = false; // Paper + private final ChunkMap chunkMap; // Paper ++ public ServerLevel getWorld() { return chunkMap.level; } // Paper + // Paper start - no-tick view distance + public final LevelChunk getSendingChunk() { + // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used +@@ -0,0 +0,0 @@ public class ChunkHolder { + } + // Paper end + ++ // 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 it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap neighborPriorities = new it.unimi.dsi.fastutil.longs.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, ChunkMap.MAX_CHUNK_DISTANCE), priority)); ++ } ++ ++ private int getMyPriority() { ++ if (priorityBoost == DistanceManager.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(ChunkHolder neighbor, ChunkStatus status) { ++ neighbor.setNeighborPriority(this, getNeighborsPriority()); ++ this.neighbors.compute(neighbor, (playerChunk, currentWantedStatus) -> { ++ if (currentWantedStatus == null || !currentWantedStatus.isOrAfter(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(ChunkHolder neighbor, ChunkStatus chunkstatus, ChunkAccess chunk) { ++ this.neighbors.compute(neighbor, (playerChunk, wantedStatus) -> { ++ if (wantedStatus != null && chunkstatus.isOrAfter(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(ChunkHolder requester) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.remove(requester.pos.toLong()); ++ recalcNeighborPriority(); ++ } ++ checkPriority(); ++ } ++ ++ ++ private void setNeighborPriority(ChunkHolder requester, int priority) { ++ synchronized (neighborPriorities) { ++ neighborPriorities.put(requester.pos.toLong(), 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 (queueLevel != getDemandedPriority()) this.chunkMap.queueHolderUpdate(this); ++ } ++ ++ public final double getDistance(ServerPlayer player) { ++ return getDistance(player.getX(), player.getZ()); ++ } ++ public final double getDistance(double blockX, double blockZ) { ++ int cx = net.minecraft.server.MCUtil.fastFloor(blockX) >> 4; ++ int cz = net.minecraft.server.MCUtil.fastFloor(blockZ) >> 4; ++ final double x = pos.x - cx; ++ final double z = pos.z - cz; ++ return (x * x) + (z * z); ++ } ++ ++ public final double getDistanceFrom(BlockPos pos) { ++ return getDistance(pos.getX(), pos.getZ()); ++ } ++ ++ public static ChunkStatus getNextStatus(ChunkStatus status) { ++ if (status == ChunkStatus.FULL) { ++ return status; ++ } ++ return CHUNK_STATUSES.get(status.getIndex() + 1); ++ } ++ public CompletableFuture> getStatusFutureUncheckedMain(ChunkStatus chunkstatus) { ++ return ensureMain(getFutureIfPresentUnchecked(chunkstatus)); ++ } ++ public CompletableFuture ensureMain(CompletableFuture future) { ++ return future.thenApplyAsync(r -> r, chunkMap.mainInvokingExecutor); ++ } ++ ++ @Override ++ public String toString() { ++ return "PlayerChunk{" + ++ "location=" + pos + ++ ", ticketLevel=" + ticketLevel + "/" + getStatus(this.ticketLevel) + ++ ", chunkHolderStatus=" + getChunkHolderStatus() + ++ ", neighborPriority=" + getNeighborsPriority() + ++ ", priority=(" + ticketLevel + " - " + priorityBoost +" vs N " + neighborPriority + ") = " + getDemandedPriority() + " A " + queueLevel + ++ '}'; ++ } ++ // Paper end ++ + // Paper start - optimise isOutsideOfRange + // cached here to avoid a map lookup + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet playersInMobSpawnRange; +@@ -0,0 +0,0 @@ public class ChunkHolder { + // CraftBukkit start + // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins. + if (playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { +- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + LevelChunk chunk = (LevelChunk)either.left().orElse(null); + if (chunk != null) { + chunkStorage.callbackExecutor.execute(() -> { +@@ -0,0 +0,0 @@ public class ChunkHolder { + this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.fullChunkFuture, executor, ChunkHolder.FullChunkStatus.BORDER); + // Paper start - cache ticking ready status +- this.fullChunkFuture.thenAccept(either -> { ++ ensureMain(this.fullChunkFuture).thenAccept(either -> { // Paper - ensure main + final Optional left = either.left(); + if (left.isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { + // note: Here is a very good place to add callbacks to logic waiting on this. + LevelChunk fullChunk = either.left().get(); + ChunkHolder.this.isFullChunkReady = true; + fullChunk.playerChunk = ChunkHolder.this; ++ this.chunkMap.distanceManager.clearPriorityTickets(pos); + } + }); + this.updateChunkToSave(this.fullChunkFuture, "full"); +@@ -0,0 +0,0 @@ public class ChunkHolder { + this.tickingChunkFuture = chunkStorage.prepareTickingChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.tickingChunkFuture, executor, ChunkHolder.FullChunkStatus.TICKING); + // Paper start - cache ticking ready status +- this.tickingChunkFuture.thenAccept(either -> { ++ ensureMain(this.tickingChunkFuture).thenAccept(either -> { // Paper - ensure main + either.ifLeft(chunk -> { + // note: Here is a very good place to add callbacks to logic waiting on this. + ChunkHolder.this.isTickingReady = true; +@@ -0,0 +0,0 @@ public class ChunkHolder { + this.entityTickingChunkFuture = chunkStorage.prepareEntityTickingChunk(this.pos); + this.scheduleFullChunkPromotion(chunkStorage, this.entityTickingChunkFuture, executor, ChunkHolder.FullChunkStatus.ENTITY_TICKING); + // Paper start - cache ticking ready status +- this.entityTickingChunkFuture.thenAccept(either -> { ++ ensureMain(this.entityTickingChunkFuture).thenAccept(either -> { // Paper ensureMain + either.ifLeft(chunk -> { + ChunkHolder.this.isEntityTickingReady = true; + }); +@@ -0,0 +0,0 @@ public class ChunkHolder { + this.demoteFullChunk(chunkStorage, playerchunk_state1); + } + +- this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); ++ //this.onLevelChange.onLevelChange(this.pos, this::getQueueLevel, this.ticketLevel, this::setQueueLevel); ++ // Paper start - raise IO/load priority if priority changes, use our preferred priority ++ priorityBoost = chunkMap.distanceManager.getChunkPriority(pos); ++ int priority = getDemandedPriority(); ++ if (this.queueLevel > 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.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, ioPriority); ++ } ++ if (this.queueLevel != priority) { ++ this.onLevelChange.onLevelChange(this.pos, () -> this.queueLevel, priority, p -> this.queueLevel = p); // 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.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) { +- this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { ++ this.getStatusFutureUncheckedMain(ChunkStatus.FULL).thenAccept((either) -> { // Paper - ensure main + LevelChunk chunk = (LevelChunk)either.left().orElse(null); + if (chunk != null) { + chunkStorage.callbackExecutor.execute(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final ServerLevel level; + private final ThreadedLevelLightEngine lightEngine; + private final BlockableEventLoop mainThreadExecutor; ++ final java.util.concurrent.Executor mainInvokingExecutor; // Paper + public final ChunkGenerator generator; + public final Supplier overworldDataStorage; + private final PoiManager poiManager; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public void execute(Runnable runnable) { ++ org.spigotmc.AsyncCatcher.catchOp("Callback Executor execute"); + if (this.queue == null) { + this.queue = new java.util.ArrayDeque<>(); + } +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public void run() { ++ org.spigotmc.AsyncCatcher.catchOp("Callback Executor run"); + if (this.queue == null) { + return; + } +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.level = world; + this.generator = chunkGenerator; + this.mainThreadExecutor = mainThreadExecutor; ++ // Paper start ++ this.mainInvokingExecutor = (run) -> { ++ if (MCUtil.isMainThread()) { ++ run.run(); ++ } else { ++ mainThreadExecutor.execute(run); ++ } ++ }; ++ // Paper end + ProcessorMailbox threadedmailbox = ProcessorMailbox.create(executor, "worldgen"); + + Objects.requireNonNull(mainThreadExecutor); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (ServerPlayer 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 ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); + ChunkMap.this.level.getChunkSource().removeTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update +- }); ++ // Paper start ++ ChunkMap.this.level.getChunkSource().clearPriorityTickets(chunkPos); ++ }, ++ (player, prevPos, newPos) -> { ++ player.lastHighPriorityChecked = -1; // reset and recheck ++ checkHighPriorityChunks(player); ++ }); ++ // Paper end + this.playerViewDistanceNoTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + this.playerViewDistanceBroadcastMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, + (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end - no-tick view distance + } + ++ // Paper start - Chunk Prioritization ++ public void queueHolderUpdate(ChunkHolder playerchunk) { ++ Runnable runnable = () -> { ++ if (isUnloading(playerchunk)) { ++ return; // unloaded ++ } ++ distanceManager.pendingChunkUpdates.add(playerchunk); ++ if (!distanceManager.pollingPendingChunkUpdates) { ++ level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ }; ++ 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 { ++ mainThreadExecutor.execute(runnable); ++ } ++ } ++ ++ private boolean isUnloading(ChunkHolder playerchunk) { ++ return playerchunk == null || toDrop.contains(playerchunk.pos.toLong()); ++ } ++ ++ private void updateChunkPriorityMap(it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap map, long chunk, int level) { ++ int prev = map.getOrDefault(chunk, -1); ++ if (level > prev) { ++ map.put(chunk, level); ++ } ++ } ++ ++ public void checkHighPriorityChunks(ServerPlayer player) { ++ int currentTick = MinecraftServer.currentTick; ++ if (currentTick - player.lastHighPriorityChecked < 20 || !player.isRealPlayer) { // weed out fake players ++ return; ++ } ++ player.lastHighPriorityChecked = currentTick; ++ it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap priorities = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(); ++ ++ int viewDistance = getEffectiveNoTickViewDistance(); ++ net.minecraft.core.BlockPos.MutableBlockPos pos = new net.minecraft.core.BlockPos.MutableBlockPos(); ++ ++ // Prioritize circular near ++ double playerChunkX = Mth.floor(player.getX()) >> 4; ++ double playerChunkZ = Mth.floor(player.getZ()) >> 4; ++ pos.set(player.getX(), 0, player.getZ()); ++ 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.toLong(), (int) (27 - dist)); ++ return; ++ } ++ ++ // Prioritize nearby chunks ++ updateChunkPriorityMap(priorities, coord.toLong(), (int) (20 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 3 ++ ChunkPos front3 = player.getChunkInFront(3); ++ pos.set(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.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ ++ // Prioritize Frustum near 5 ++ if (viewDistance > 4) { ++ ChunkPos front5 = player.getChunkInFront(5); ++ pos.set(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.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ // Prioritize Frustum far 7 ++ if (viewDistance > 6) { ++ ChunkPos front7 = player.getChunkInFront(7); ++ pos.set(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.toLong(), (int) (25 - dist * twoThirdModifier)); ++ }); ++ } ++ ++ if (priorities.isEmpty()) return; ++ distanceManager.delayDistanceManagerTick = true; ++ priorities.long2IntEntrySet().fastForEach(entry -> distanceManager.markHighPriority(new ChunkPos(entry.getLongKey()), entry.getIntValue())); ++ distanceManager.delayDistanceManagerTick = false; ++ level.getChunkSource().runDistanceManagerUpdates(); ++ ++ } ++ ++ private boolean shouldSkipPrioritization(ChunkPos coord) { ++ if (playerViewDistanceNoTickMap.getObjectsInRange(coord.toLong()) == null) return true; ++ ChunkHolder chunk = getUpdatingChunkIfPresent(coord.toLong()); ++ return chunk != null && (chunk.isFullChunkReady()); ++ } ++ // Paper end ++ + // Paper start + public void updatePlayerMobTypeMap(Entity entity) { + if (!this.level.paperConfig.perPlayerMobSpawns) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + List>> list = Lists.newArrayList(); + int j = centerChunk.x; + int k = centerChunk.z; ++ ChunkHolder requestingNeighbor = getUpdatingChunkIfPresent(centerChunk.toLong()); // Paper + + for (int l = -margin; l <= margin; ++l) { + for (int i1 = -margin; i1 <= margin; ++i1) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + ChunkStatus chunkstatus = (ChunkStatus) distanceToStatus.apply(j1); + CompletableFuture> completablefuture = playerchunk.getOrScheduleFuture(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 ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + + CompletableFuture chunkSaveFuture = this.level.asyncChunkTaskManager.getChunkSaveFuture(pos.x, pos.z); ++ // Paper start ++ ChunkHolder playerChunk = getUpdatingChunkIfPresent(pos.toLong()); ++ int chunkPriority = playerChunk != null ? playerChunk.queueLevel : 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; ++ // Paper end + if (chunkSaveFuture != null) { +- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY, chunkHolderConsumer, false, chunkSaveFuture); +- this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY); ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority, chunkSaveFuture); // Paper + } else { +- this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, +- com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY, chunkHolderConsumer, false); ++ this.level.asyncChunkTaskManager.scheduleChunkLoad(pos.x, pos.z, priority, chunkHolderConsumer, isHighestPriority); // Paper + } ++ this.level.asyncChunkTaskManager.raisePriority(pos.x, pos.z, priority); // Paper + return ret; + // Paper end + } +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + long i = playerchunk.getPos().toLong(); + + Objects.requireNonNull(playerchunk); +- mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, playerchunk::getTicketLevel)); ++ mailbox.tell(ChunkTaskPriorityQueueSorter.message(runnable, i, () -> 1)); // Paper - final loads are always urgent! + }); + } + +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + } + + private static int getTicketLevelAt(SortedArraySet> arraysetsorted) { ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::getLowestTicketLevel"); // Paper + return !arraysetsorted.isEmpty() ? ((Ticket) arraysetsorted.first()).getTicketLevel() : ChunkMap.MAX_CHUNK_DISTANCE + 1; + } + +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + + public boolean runAllUpdates(ChunkMap playerchunkmap) { + //this.f.a(); // Paper - no longer used ++ org.spigotmc.AsyncCatcher.catchOp("DistanceManagerTick"); // Paper + this.playerTicketManager.runAllUpdates(); + int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + + // Paper start + if (!this.pendingChunkUpdates.isEmpty()) { ++ this.pollingPendingChunkUpdates = true; try { // Paper - Chunk priority + while(!this.pendingChunkUpdates.isEmpty()) { + ChunkHolder remove = this.pendingChunkUpdates.remove(); + remove.isUpdateQueued = false; + remove.updateFutures(playerchunkmap, this.mainThreadExecutor); + } ++ } finally { this.pollingPendingChunkUpdates = false; } // Paper - Chunk priority + // Paper end + return true; + } else { +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + return flag; + } + } ++ boolean pollingPendingChunkUpdates = false; // Paper - Chunk priority + + boolean addTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::addTicket"); // Paper + SortedArraySet> arraysetsorted = this.getTickets(i); + int j = DistanceManager.getTicketLevelAt(arraysetsorted); + Ticket ticket1 = (Ticket) arraysetsorted.addOrGet(ticket); // CraftBukkit - decompile error +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + } + + boolean removeTicket(long i, Ticket ticket) { // CraftBukkit - void -> boolean ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::removeTicket"); // Paper + SortedArraySet> arraysetsorted = this.getTickets(i); ++ int oldLevel = getTicketLevelAt(arraysetsorted); // Paper + + boolean removed = false; // CraftBukkit + if (arraysetsorted.remove(ticket)) { +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + this.tickets.remove(i); + } + +- this.ticketTracker.update(i, DistanceManager.getTicketLevelAt(arraysetsorted), false); ++ // Paper start - Chunk priority ++ int newLevel = getTicketLevelAt(arraysetsorted); ++ if (newLevel > oldLevel) { ++ this.ticketTracker.update(i, newLevel, false); ++ } ++ // Paper end + return removed; // CraftBukkit + } + +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + }); + } + ++ // Paper start - Chunk priority ++ public static final int PRIORITY_TICKET_LEVEL = ChunkMap.MAX_CHUNK_DISTANCE; ++ public static final int URGENT_PRIORITY = 29; ++ public boolean delayDistanceManagerTick = false; ++ public boolean markUrgent(ChunkPos coords) { ++ return addPriorityTicket(coords, TicketType.URGENT, URGENT_PRIORITY); ++ } ++ public boolean markHighPriority(ChunkPos coords, int priority) { ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ return addPriorityTicket(coords, TicketType.PRIORITY, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { ++ delayDistanceManagerTick = true; ++ priority = Math.min(URGENT_PRIORITY - 1, Math.max(1, priority)); ++ int finalPriority = priority; ++ net.minecraft.server.MCUtil.getSpiralOutChunks(center.getWorldPosition(), radius).forEach(coords -> { ++ addPriorityTicket(coords, TicketType.PRIORITY, finalPriority); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkPos center, int radius) { ++ delayDistanceManagerTick = true; ++ net.minecraft.server.MCUtil.getSpiralOutChunks(center.getWorldPosition(), radius).forEach(coords -> { ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ }); ++ delayDistanceManagerTick = false; ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ ++ private boolean hasPlayerTicket(ChunkPos coords, int level) { ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null || tickets.isEmpty()) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.PLAYER && ticket.getTicketLevel() == level) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ private boolean addPriorityTicket(ChunkPos coords, TicketType ticketType, int priority) { ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::addPriorityTicket"); ++ long pair = coords.toLong(); ++ ChunkHolder chunk = chunkMap.getUpdatingChunkIfPresent(pair); ++ boolean needsTicket = chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(pair) != null && !hasPlayerTicket(coords, 33); ++ ++ if (needsTicket) { ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); ++ this.ticketsToRelease.add(pair); ++ addTicket(pair, ticket); ++ } ++ if ((chunk != null && chunk.isFullChunkReady())) { ++ if (needsTicket) { ++ chunkMap.level.getChunkSource().runDistanceManagerUpdates(); ++ } ++ 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.getUpdatingChunkIfPresent(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.level.getChunkSource().runDistanceManagerUpdates(); ++ ++ return success; ++ } ++ ++ private boolean updatePriorityTicket(ChunkPos coords, TicketType type, int priority) { ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null) { ++ return false; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == type) { ++ // We only support increasing, not decreasing, too complicated ++ ticket.setCreatedTick(this.ticketTickCounter); ++ ticket.priority = Math.max(ticket.priority, priority); ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ ++ public int getChunkPriority(ChunkPos coords) { ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::getChunkPriority"); ++ SortedArraySet> tickets = this.tickets.get(coords.toLong()); ++ if (tickets == null) { ++ return 0; ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.URGENT) { ++ return URGENT_PRIORITY; ++ } ++ } ++ for (Ticket ticket : tickets) { ++ if (ticket.getType() == TicketType.PRIORITY && ticket.priority > 0) { ++ return ticket.priority; ++ } ++ } ++ return 0; ++ } ++ ++ public void clearPriorityTickets(ChunkPos coords) { ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::clearPriority"); ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.PRIORITY, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ ++ public void clearUrgent(ChunkPos coords) { ++ org.spigotmc.AsyncCatcher.catchOp("ChunkMapDistance::clearUrgent"); ++ this.removeTicket(coords.toLong(), new Ticket(TicketType.URGENT, PRIORITY_TICKET_LEVEL, coords)); ++ } ++ // Paper end ++ + protected void updateChunkForced(ChunkPos pos, boolean forced) { + Ticket ticket = new Ticket<>(TicketType.FORCED, 31, pos); + +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + + public void updateViewDistance(int watchDistance) { + ObjectIterator objectiterator = this.chunks.long2ByteEntrySet().iterator(); ++ // Paper start - set the view distance before scheduling chunk loads/unloads ++ int lastViewDistance = this.viewDistance; ++ this.viewDistance = watchDistance; ++ // Paper end + + while (objectiterator.hasNext()) { + it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry it_unimi_dsi_fastutil_longs_long2bytemap_entry = (it.unimi.dsi.fastutil.longs.Long2ByteMap.Entry) objectiterator.next(); + byte b0 = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getByteValue(); + long j = it_unimi_dsi_fastutil_longs_long2bytemap_entry.getLongKey(); + +- this.onLevelChange(j, b0, this.haveTicketFor(b0), b0 <= watchDistance - 2); ++ this.onLevelChange(j, b0, b0 <= lastViewDistance - 2, this.haveTicketFor(b0)); // Paper + } + +- this.viewDistance = watchDistance; ++ // this.viewDistance = watchDistance; // Paper - view distance is now set further up + } + + private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { + if (oldWithinViewDistance != withinViewDistance) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance ++ ChunkPos coords = new ChunkPos(pos); // Paper - reuse variable ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, coords); // Paper - no-tick view distance + + if (withinViewDistance) { ++ scheduleChunkLoad(pos, net.minecraft.server.MinecraftServer.currentTick, distance, (priority) -> { // Paper - smarter ticket delay based on frustum and distance ++ // Paper start - recheck its still valid if not cancel ++ if (!isChunkInRange(pos)) { ++ DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { ++ DistanceManager.this.mainThreadExecutor.execute(() -> { ++ DistanceManager.this.removeTicket(pos, ticket); ++ DistanceManager.this.clearPriorityTickets(coords); ++ }); ++ }, pos, 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) { ++ DistanceManager.this.addTicket(pos, ticket); ++ DistanceManager.this.ticketsToRelease.add(pos); ++ return; ++ } ++ // Paper end + DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { + DistanceManager.this.mainThreadExecutor.execute(() -> { +- if (this.haveTicketFor(this.getLevel(pos))) { ++ if (isChunkInRange(pos)) { if (!hasPlayerTicket(coords, 33)) { // Paper - high priority might of already added it + DistanceManager.this.addTicket(pos, ticket); + DistanceManager.this.ticketsToRelease.add(pos); +- } else { ++ }} else { // Paper + DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { + }, pos, false)); + } + + }); + }, pos, () -> { +- return distance; ++ return Math.min(ChunkMap.MAX_CHUNK_DISTANCE, priority); // Paper - Chunk priority + })); ++ }); // Paper + } else { + DistanceManager.this.ticketThrottlerReleaser.tell(ChunkTaskPriorityQueueSorter.release(() -> { + DistanceManager.this.mainThreadExecutor.execute(() -> { + DistanceManager.this.removeTicket(pos, ticket); ++ DistanceManager.this.clearPriorityTickets(coords); // Paper - Chunk priority + }); + }, pos, true)); + } +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + private boolean haveTicketFor(int distance) { + return distance <= this.viewDistance - 2; + } ++ ++ // Paper start - smart scheduling of player tickets ++ private boolean isChunkInRange(long i) { ++ return this.haveTicketFor(this.getLevel(i)); ++ } ++ public void scheduleChunkLoad(long i, long startTick, int initialDistance, java.util.function.Consumer task) { ++ long elapsed = net.minecraft.server.MinecraftServer.currentTick - startTick; ++ ChunkPos chunkPos = new ChunkPos(i); ++ ChunkHolder updatingChunk = chunkMap.getUpdatingChunkIfPresent(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(); ++ ++ net.minecraft.core.BlockPos blockPos = chunkPos.getWorldPosition(); ++ ++ boolean isFront = false; ++ net.minecraft.core.BlockPos.MutableBlockPos pos = new net.minecraft.core.BlockPos.MutableBlockPos(); ++ for (int index = 0, len = backingSet.length; index < len; ++index) { ++ if (!(backingSet[index] instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) backingSet[index]; ++ ++ ChunkPos pointInFront = player.getChunkInFront(5); ++ pos.set(pointInFront.x << 4, 0, pointInFront.z << 4); ++ double frontDist = net.minecraft.server.MCUtil.distanceSq(pos, blockPos); ++ ++ pos.set(player.getX(), 0, player.getZ()); ++ double center = net.minecraft.server.MCUtil.distanceSq(pos, blockPos); ++ ++ double dist = Math.min(frontDist, center); ++ if (!isFront) { ++ ChunkPos pointInBack = player.getChunkInFront(-7); ++ pos.set(pointInBack.x << 4, 0, pointInBack.z << 4); ++ double backDist = net.minecraft.server.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 = ChunkPos.asLong(chunkPos.x + x, chunkPos.z + z); ++ ChunkHolder neighbor = chunkMap.getUpdatingChunkIfPresent(pair); ++ ChunkStatus current = neighbor != null ? neighbor.getChunkHolderStatus() : null; ++ if (current != null && current.isOrAfter(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)); ++ net.minecraft.server.MCUtil.scheduleTask(taskDelay, () -> scheduleChunkLoad(i, startTick, initialDistance, task), "Player Ticket Delayer"); ++ } ++ } ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + public void removeTicketAtLevel(TicketType ticketType, ChunkPos chunkPos, int ticketLevel, T identifier) { + this.distanceManager.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier); + } ++ ++ public boolean markUrgent(ChunkPos coords) { ++ return this.distanceManager.markUrgent(coords); ++ } ++ ++ public boolean markHighPriority(ChunkPos coords, int priority) { ++ return this.distanceManager.markHighPriority(coords, priority); ++ } ++ ++ public void markAreaHighPriority(ChunkPos center, int priority, int radius) { ++ this.distanceManager.markAreaHighPriority(center, priority, radius); ++ } ++ ++ public void clearAreaPriorityTickets(ChunkPos center, int radius) { ++ this.distanceManager.clearAreaPriorityTickets(center, radius); ++ } ++ ++ public void clearPriorityTickets(ChunkPos coords) { ++ this.distanceManager.clearPriorityTickets(coords); ++ } + // Paper end - async chunk io + + @Nullable +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + Objects.requireNonNull(completablefuture); + if (!completablefuture.isDone()) { // Paper + // Paper start - async chunk io/loading ++ ChunkPos pair = new ChunkPos(x1, z1); // Paper - Chunk priority ++ this.distanceManager.markUrgent(pair); // Paper - Chunk priority + this.level.asyncChunkTaskManager.raisePriority(x1, z1, com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHEST_PRIORITY); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + // Paper end +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + chunkproviderserver_a.managedBlock(completablefuture::isDone); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug + this.level.timings.syncChunkLoad.stopTiming(); // Paper ++ this.distanceManager.clearPriorityTickets(pair); // Paper - Chunk priority ++ this.distanceManager.clearUrgent(pair); // Paper - Chunk priority + } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + if (flag && !currentlyUnloading) { + // CraftBukkit end + this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); ++ if (isUrgent) this.distanceManager.markUrgent(chunkcoordintpair); // Paper - Chunk priority + if (this.chunkAbsent(playerchunk, l)) { + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + + gameprofilerfiller.push("chunkLoad"); ++ distanceManager.delayDistanceManagerTick = false; // Paper - Chunk priority - ensure this is never false + this.runDistanceManagerUpdates(); + playerchunk = this.getVisibleChunkIfPresent(k); + gameprofilerfiller.pop(); +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + } + } + } +- +- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); ++ // Paper start - Chunk priority ++ CompletableFuture> future = this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(chunkstatus, this.chunkMap); ++ if (isUrgent) { ++ future.thenAccept(either -> this.distanceManager.clearUrgent(chunkcoordintpair)); ++ } ++ return future; ++ // Paper end + } + + private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + } + + public boolean runDistanceManagerUpdates() { ++ if (distanceManager.delayDistanceManagerTick) return false; // Paper - Chunk priority + boolean flag = this.distanceManager.runAllUpdates(this.chunkMap); + boolean flag1 = this.chunkMap.promoteChunkMap(); + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + private int lastRecordedArmor = Integer.MIN_VALUE; + private int lastRecordedLevel = Integer.MIN_VALUE; + private int lastRecordedExperience = Integer.MIN_VALUE; ++ // Paper start - Chunk priority ++ public long lastHighPriorityChecked; ++ public void forceCheckHighPriority() { ++ lastHighPriorityChecked = -1; ++ getLevel().getChunkSource().chunkMap.checkHighPriorityChunks(this); ++ } ++ public boolean isRealPlayer; ++ // Paper end + private float lastSentHealth = -1.0E8F; + private int lastSentFood = -99999999; + private boolean lastFoodSaturationZero = true; +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.maxHealthCache = this.getMaxHealth(); + this.cachedSingleMobDistanceMap = new com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper + } ++ // Paper start - Chunk priority ++ public BlockPos getPointInFront(double inFront) { ++ double rads = Math.toRadians(net.minecraft.server.MCUtil.normalizeYaw(this.yRot + 90)); // MC rotates yaw 90 for some odd reason ++ final double x = getX() + inFront * Math.cos(rads); ++ final double z = getZ() + inFront * Math.sin(rads); ++ return new BlockPos(x, getY(), z); ++ } ++ ++ public ChunkPos getChunkInFront(double inFront) { ++ double rads = Math.toRadians(net.minecraft.server.MCUtil.normalizeYaw(this.yRot + 90)); // MC rotates yaw 90 for some odd reason ++ final double x = getX() + (inFront * 16) * Math.cos(rads); ++ final double z = getZ() + (inFront * 16) * Math.sin(rads); ++ return new ChunkPos(Mth.floor(x) >> 4, Mth.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 ServerPlayer extends Player { + if (valid && !this.isSpectator() || !this.touchingUnloadedChunk()) { // Paper - don't tick dead players that are not in the world currently (pending respawn) + super.tick(); + } ++ if (valid && isAlive() && connection != null) ((ServerLevel)level).getChunkSource().chunkMap.checkHighPriorityChunks(this); // Paper - Chunk priority + + for (int i = 0; i < this.getInventory().getContainerSize(); ++i) { + ItemStack itemstack = this.getInventory().getItem(i); +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 key; + public long createdTick; + public long delayUnloadBy; // Paper ++ public int priority; // Paper - Chunk priority + + protected Ticket(TicketType type, int level, T argument) { + this.type = type; +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 @@ import net.minecraft.world.level.ChunkPos; + public class TicketType { + public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper + public static final TicketType ASYNC_LOAD = create("async_load", Long::compareTo); // Paper ++ public static final TicketType PRIORITY = create("priority", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper ++ public static final TicketType URGENT = create("urgent", Comparator.comparingLong(ChunkPos::toLong), 300); // Paper + + private final String name; + private final Comparator comparator; +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + this.awaitingTeleportTime = this.tickCount; + this.player.absMoveTo(d0, d1, d2, f, f1); ++ this.player.forceCheckHighPriority(); // Paper + this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport, flag)); + } + +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 { + net.minecraft.server.level.ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; + net.minecraft.server.level.DistanceManager distanceManager = playerChunkMap.distanceManager; + distanceManager.addTicketAtLevel(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); +- worldserver1.getChunkSource().runDistanceManagerUpdates(); +- worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ worldserver1.getChunkSource().markAreaHighPriority(pos, 28, 3); // Paper - Chunk priority ++ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, false).thenApply(chunk -> { // Paper - Chunk priority + net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); + if (updatingChunk != null) { + return updatingChunk.getEntityTickingChunkFuture(); +@@ -0,0 +0,0 @@ public abstract class PlayerList { + SocketAddress socketaddress = loginlistener.connection.getRemoteAddress(); + + ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameprofile); ++ entity.isRealPlayer = true; // Paper - Chunk priority + Player player = entity.getBukkitEntity(); + PlayerLoginEvent event = new PlayerLoginEvent(player, hostname, ((java.net.InetSocketAddress) socketaddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.getRawAddress()).getAddress()); + +@@ -0,0 +0,0 @@ public abstract class PlayerList { + // CraftBukkit end + + worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper ++ entityplayer1.forceCheckHighPriority(); // Player - Chunk priority + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +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 Nameable, EntityAccess, CommandSource, n + private Vec3 position; + private BlockPos blockPosition; + private Vec3 deltaMovement; +- private float yRot; ++ public float yRot; // Paper - private->public + private float xRot; + public float yRotO; + public float xRotO; +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; + } + ++ // Paper start - Chunk priority ++ if (!urgent) { ++ // If not urgent, at least use a slightly boosted priority ++ world.getChunkSource().markHighPriority(new ChunkPos(x, z), 1); ++ } ++ // Paper end + return this.world.getChunkSource().getChunkAtAsynchronously(x, z, gen, urgent).thenComposeAsync((either) -> { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); + if (chunk != null) addTicket(x, z); // 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 { + throw new UnsupportedOperationException("Cannot set rotation of players. Consider teleporting instead."); + } + ++ // Paper start - Chunk priority ++ @Override ++ public java.util.concurrent.CompletableFuture teleportAsync(Location loc, @javax.annotation.Nonnull PlayerTeleportEvent.TeleportCause cause) { ++ ((CraftWorld)loc.getWorld()).getHandle().getChunkSource().markAreaHighPriority( ++ new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(loc.getX()) >> 4, ++ net.minecraft.util.Mth.floor(loc.getZ()) >> 4), 28, 3); // 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/patches/server/Implement-CraftBlockSoundGroup.patch similarity index 51% rename from Spigot-Server-Patches/Implement-CraftBlockSoundGroup.patch rename to patches/server/Implement-CraftBlockSoundGroup.patch index 1e3cf7690a..2c8884a072 100644 --- a/Spigot-Server-Patches/Implement-CraftBlockSoundGroup.patch +++ b/patches/server/Implement-CraftBlockSoundGroup.patch @@ -12,14 +12,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.block; + -+import net.minecraft.world.level.block.SoundEffectType; ++import net.minecraft.world.level.block.SoundType; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.CraftSound; + +public class CraftBlockSoundGroup implements BlockSoundGroup { -+ private final SoundEffectType soundEffectType; ++ private final SoundType soundEffectType; + -+ public CraftBlockSoundGroup(SoundEffectType soundEffectType) { ++ public CraftBlockSoundGroup(SoundType soundEffectType) { + this.soundEffectType = soundEffectType; + } + @@ -48,36 +48,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); + VoxelShape shape = this.getNMS().getCollisionShape(world, position); + return new CraftVoxelShape(shape); } -+ + // Paper start + @Override + public com.destroystokyo.paper.block.BlockSoundGroup getSoundGroup() { -+ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().getBlockData().getStepSound()); ++ return new com.destroystokyo.paper.block.CraftBlockSoundGroup(getNMSBlock().defaultBlockState().getSoundType()); + } + // Paper end } diff --git a/patches/server/Implement-EntityKnockbackByEntityEvent.patch b/patches/server/Implement-EntityKnockbackByEntityEvent.patch new file mode 100644 index 0000000000..bfad137387 --- /dev/null +++ b/patches/server/Implement-EntityKnockbackByEntityEvent.patch @@ -0,0 +1,92 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + this.hurtDir = (float) (Mth.atan2(d1, d0) * 57.2957763671875D - (double) this.getYRot()); +- this.knockback(0.4000000059604645D, d0, d1); ++ this.knockback(0.4000000059604645D, d0, d1, entity1); + } else { + this.hurtDir = (float) ((int) (Math.random() * 2.0D) * 180); + } +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + protected void blockedByShield(LivingEntity target) { +- target.knockback(0.5D, target.getX() - this.getX(), target.getZ() - this.getZ()); ++ target.knockback(0.5D, target.getX() - this.getX(), target.getZ() - this.getZ(), this); + } + + private boolean checkTotemDeathProtection(DamageSource source) { +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + public void knockback(double strength, double x, double z) { ++ // Paper start - add knockbacking entity parameter ++ this.knockback(strength, x, z, null); ++ } ++ public void knockback(double strength, double x, double z, Entity knockingBackEntity) { ++ // Paper end - add knockbacking entity parameter + strength *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); + if (strength > 0.0D) { + this.hasImpulse = true; +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + Vec3 vec3d1 = (new Vec3(x, 0.0D, z)).normalize().scale(strength); + + this.setDeltaMovement(vec3d.x / 2.0D - vec3d1.x, this.onGround ? Math.min(0.4D, vec3d.y / 2.0D + strength) : vec3d.y, vec3d.z / 2.0D - vec3d1.z); ++ // Paper start - call EntityKnockbackByEntityEvent ++ Vec3 currentMovement = this.getDeltaMovement(); ++ org.bukkit.util.Vector delta = new org.bukkit.util.Vector(currentMovement.x - vec3d.x, currentMovement.y - vec3d.y, currentMovement.z - vec3d.z); ++ // Restore old velocity to be able to access it in the event ++ this.setDeltaMovement(vec3d); ++ if (knockingBackEntity == null || new com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent((org.bukkit.entity.LivingEntity) getBukkitEntity(), knockingBackEntity.getBukkitEntity(), (float) strength, delta).callEvent()) { ++ this.setDeltaMovement(vec3d.x + delta.getX(), vec3d.y + delta.getY(), vec3d.z + delta.getZ()); ++ } ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + + if (flag) { + if (f1 > 0.0F && target instanceof LivingEntity) { +- ((LivingEntity) target).knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ ((LivingEntity) target).knockback((double) (f1 * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper + this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); + } + +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + if (flag5) { + if (i > 0) { + if (target instanceof LivingEntity) { +- ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper + } else { + target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F)); + } +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + if (entityliving != this && entityliving != target && !this.isAlliedTo(entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) { + // CraftBukkit start - Only apply knockback if the damage hits + if (entityliving.hurt(DamageSource.playerAttack(this).sweep(), f4)) { +- entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this); // Paper + } + // CraftBukkit end + } diff --git a/Spigot-Server-Patches/Implement-EntityTeleportEndGatewayEvent.patch b/patches/server/Implement-EntityTeleportEndGatewayEvent.patch similarity index 57% rename from Spigot-Server-Patches/Implement-EntityTeleportEndGatewayEvent.patch rename to patches/server/Implement-EntityTeleportEndGatewayEvent.patch index c056b09c51..c58488a4f5 100644 --- a/Spigot-Server-Patches/Implement-EntityTeleportEndGatewayEvent.patch +++ b/patches/server/Implement-EntityTeleportEndGatewayEvent.patch @@ -4,29 +4,29 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.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 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -0,0 +0,0 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { } // 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); ++ org.bukkit.Location location = new Location(world.getWorld(), (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.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())); ++ 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, blockEntity.getBlockPos()).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 + entity1.setPortalCooldown(); +- entity1.teleportToWithTicket((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D); ++ entity1.teleportToWithTicket(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); // Paper } - this.h(); + TheEndGatewayBlockEntity.triggerCooldown(world, pos, state, blockEntity); diff --git a/Spigot-Server-Patches/Implement-Expanded-ArmorStand-API.patch b/patches/server/Implement-Expanded-ArmorStand-API.patch similarity index 67% rename from Spigot-Server-Patches/Implement-Expanded-ArmorStand-API.patch rename to patches/server/Implement-Expanded-ArmorStand-API.patch index 74ffbf06ae..2493980a19 100644 --- a/Spigot-Server-Patches/Implement-Expanded-ArmorStand-API.patch +++ b/patches/server/Implement-Expanded-ArmorStand-API.patch @@ -7,39 +7,18 @@ 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(); ++ return getHandle().getItemBySlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)).asBukkitMirror(); + } + + @Override @@ -84,8 +63,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); ++ net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot); ++ disabled += (1 << nmsSlot.getFilterFlag()) + (1 << (nmsSlot.getFilterFlag() + 8)) + (1 << (nmsSlot.getFilterFlag() + 16)); + } + getHandle().disabledSlots = disabled; + } @@ -106,7 +85,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public boolean isSlotDisabled(org.bukkit.inventory.EquipmentSlot slot) { -+ return getHandle().isSlotDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); ++ return getHandle().isDisabled(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); + } - // Paper end - } ++ + @Override + public boolean canTick() { + return this.getHandle().canTick; diff --git a/patches/server/Implement-Keyed-on-World.patch b/patches/server/Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..4e27476c78 --- /dev/null +++ b/patches/server/Implement-Keyed-on-World.patch @@ -0,0 +1,51 @@ +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/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.Level.END; + } else { +- worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(name.toLowerCase(java.util.Locale.ENGLISH))); ++ worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, new net.minecraft.resources.ResourceLocation(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper + } + + ServerLevel internal = (ServerLevel) new ServerLevel(this.console, console.executor, worldSession, worlddata, worldKey, dimensionmanager, this.getServer().progressListenerFactory.create(11), +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + return null; + } + ++ // Paper start ++ @Override ++ public World getWorld(NamespacedKey worldKey) { ++ ServerLevel worldServer = console.getLevel(ResourceKey.create(Registry.DIMENSION_REGISTRY, 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 (this.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 java.util.concurrent.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.dimension().location()); ++ } + // Paper end + + // Spigot start diff --git a/Spigot-Server-Patches/Implement-Mob-Goal-API.patch b/patches/server/Implement-Mob-Goal-API.patch similarity index 60% rename from Spigot-Server-Patches/Implement-Mob-Goal-API.patch rename to patches/server/Implement-Mob-Goal-API.patch index 7aac3dcedd..b3cf91577c 100644 --- a/Spigot-Server-Patches/Implement-Mob-Goal-API.patch +++ b/patches/server/Implement-Mob-Goal-API.patch @@ -4,24 +4,18 @@ Date: Fri, 3 Jan 2020 16:26:19 +0100 Subject: [PATCH] Implement Mob Goal API -diff --git a/pom.xml b/pom.xml +diff --git a/build.gradle.kts b/build.gradle.kts 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 -+ - +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + implementation("co.aikar:cleaner:1.0-SNAPSHOT") // Paper + implementation("io.netty:netty-all:4.1.65.Final") // Paper - ++ testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") + } 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 @@ -40,100 +34,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.world.entity.FlyingMob; ++import net.minecraft.world.entity.PathfinderMob; ++import net.minecraft.world.entity.TamableAnimal; ++import net.minecraft.world.entity.ai.goal.Goal; ++import net.minecraft.world.entity.ambient.AmbientCreature; ++import net.minecraft.world.entity.animal.AbstractFish; ++import net.minecraft.world.entity.animal.AbstractGolem; ++import net.minecraft.world.entity.animal.AbstractSchoolingFish; ++import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.animal.Pufferfish; ++import net.minecraft.world.entity.animal.ShoulderRidingEntity; ++import net.minecraft.world.entity.animal.SnowGolem; ++import net.minecraft.world.entity.animal.WaterAnimal; ++import net.minecraft.world.entity.animal.horse.AbstractChestedHorse; ++import net.minecraft.world.entity.boss.wither.WitherBoss; ++import net.minecraft.world.entity.monster.AbstractIllager; ++import net.minecraft.world.entity.monster.AbstractSkeleton; ++import net.minecraft.world.entity.monster.EnderMan; ++import net.minecraft.world.entity.monster.PatrollingMonster; ++import net.minecraft.world.entity.monster.RangedAttackMob; ++import net.minecraft.world.entity.monster.SpellcasterIllager; ++import net.minecraft.world.entity.monster.ZombifiedPiglin; ++import net.minecraft.world.entity.monster.piglin.AbstractPiglin; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.AbstractHorse; +import org.bukkit.entity.AbstractVillager; @@ -227,8 +150,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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<>(); ++ private static final Map, Class> entityClassCache = new HashMap<>(); ++ private static final Map, Class> bukkitMap = new HashMap<>(); + + static final Set ignored = new HashSet<>(); + @@ -315,7 +238,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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("abstract_skeleton_1", "skeleton_melee"); + deobfuscationMap.put("strider_a", "strider_go_to_lava"); + deobfuscationMap.put("turtle_a", "turtle_breed"); + deobfuscationMap.put("turtle_b", "turtle_go_home"); @@ -336,104 +259,110 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + deobfuscationMap.put("wolf_a", "wolf_avoid_entity"); + deobfuscationMap.put("zombie_a", "zombie_attack_turtle_egg"); + ++ ignored.add("goal_selector_1"); ++ ignored.add("goal_selector_2"); + 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); ++ bukkitMap.put(net.minecraft.world.entity.Mob.class, Mob.class); ++ bukkitMap.put(net.minecraft.world.entity.AgeableMob.class, Ageable.class); ++ bukkitMap.put(AmbientCreature.class, Ambient.class); ++ bukkitMap.put(Animal.class, Animals.class); ++ bukkitMap.put(net.minecraft.world.entity.ambient.Bat.class, Bat.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Bee.class, Bee.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Blaze.class, Blaze.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cat.class, Cat.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.CaveSpider.class, CaveSpider.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Chicken.class, Chicken.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cod.class, Cod.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Cow.class, Cow.class); ++ bukkitMap.put(PathfinderMob.class, Creature.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Creeper.class, Creeper.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Dolphin.class, Dolphin.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Drowned.class, Drowned.class); ++ bukkitMap.put(net.minecraft.world.entity.boss.enderdragon.EnderDragon.class, EnderDragon.class); ++ bukkitMap.put(EnderMan.class, Enderman.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Endermite.class, Endermite.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Evoker.class, Evoker.class); ++ bukkitMap.put(AbstractFish.class, Fish.class); ++ bukkitMap.put(AbstractSchoolingFish.class, Fish.class); // close enough ++ bukkitMap.put(FlyingMob.class, Flying.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Fox.class, Fox.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Ghast.class, Ghast.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Giant.class, Giant.class); ++ bukkitMap.put(AbstractGolem.class, Golem.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Guardian.class, Guardian.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.ElderGuardian.class, ElderGuardian.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Horse.class, Horse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.AbstractHorse.class, AbstractHorse.class); ++ bukkitMap.put(AbstractChestedHorse.class, ChestedHorse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Donkey.class, Donkey.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Mule.class, Mule.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.SkeletonHorse.class, SkeletonHorse.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.ZombieHorse.class, ZombieHorse.class); ++ bukkitMap.put(AbstractIllager.class, Illager.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Illusioner.class, Illusioner.class); ++ bukkitMap.put(SpellcasterIllager.class, Spellcaster.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.IronGolem.class, IronGolem.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.Llama.class, Llama.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.horse.TraderLlama.class, TraderLlama.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.MagmaCube.class, MagmaCube.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Monster.class, Monster.class); ++ bukkitMap.put(PatrollingMonster.class, Monster.class); // close enough ++ bukkitMap.put(net.minecraft.world.entity.animal.MushroomCow.class, MushroomCow.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Ocelot.class, Ocelot.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Panda.class, Panda.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Parrot.class, Parrot.class); ++ bukkitMap.put(ShoulderRidingEntity.class, Parrot.class); // close enough ++ bukkitMap.put(net.minecraft.world.entity.monster.Phantom.class, Phantom.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Pig.class, Pig.class); ++ bukkitMap.put(ZombifiedPiglin.class, PigZombie.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Pillager.class, Pillager.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.PolarBear.class, PolarBear.class); ++ bukkitMap.put(Pufferfish.class, PufferFish.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Rabbit.class, Rabbit.class); ++ bukkitMap.put(net.minecraft.world.entity.raid.Raider.class, Raider.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Ravager.class, Ravager.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Salmon.class, Salmon.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Sheep.class, Sheep.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Shulker.class, Shulker.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Silverfish.class, Silverfish.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Skeleton.class, Skeleton.class); ++ bukkitMap.put(AbstractSkeleton.class, Skeleton.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Stray.class, Stray.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.WitherSkeleton.class, WitherSkeleton.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Slime.class, Slime.class); ++ bukkitMap.put(SnowGolem.class, Snowman.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Spider.class, Spider.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Squid.class, Squid.class); ++ bukkitMap.put(TamableAnimal.class, Tameable.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.TropicalFish.class, TropicalFish.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Turtle.class, Turtle.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Vex.class, Vex.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.Villager.class, Villager.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.AbstractVillager.class, AbstractVillager.class); ++ bukkitMap.put(net.minecraft.world.entity.npc.WanderingTrader.class, WanderingTrader.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Vindicator.class, Vindicator.class); ++ bukkitMap.put(WaterAnimal.class, WaterMob.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Witch.class, Witch.class); ++ bukkitMap.put(WitherBoss.class, Wither.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.Wolf.class, Wolf.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Zombie.class, Zombie.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Husk.class, Husk.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.ZombieVillager.class, ZombieVillager.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.hoglin.Hoglin.class, Hoglin.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.piglin.Piglin.class, Piglin.class); ++ bukkitMap.put(AbstractPiglin.class, PiglinAbstract.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.piglin.PiglinBrute.class, PiglinBrute.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Strider.class, Strider.class); ++ bukkitMap.put(net.minecraft.world.entity.monster.Zoglin.class, Zoglin.class); ++ bukkitMap.put(net.minecraft.world.entity.GlowSquid.class, org.bukkit.entity.GlowSquid.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.axolotl.Axolotl.class, org.bukkit.entity.Axolotl.class); ++ bukkitMap.put(net.minecraft.world.entity.animal.goat.Goat.class, org.bukkit.entity.Goat.class); + } + ++ // TODO: FIX THIS + public static String getUsableName(Class clazz) { + String name = clazz.getName(); + name = name.substring(name.lastIndexOf(".") + 1); @@ -451,6 +380,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + name = name.replace("PathfinderGoal", ""); ++ name = name.replace("TargetGoal", ""); ++ name = name.replace("Goal", ""); + StringBuilder sb = new StringBuilder(); + for (char c : name.toCharArray()) { + if (c >= 'A' && c <= 'Z') { @@ -471,7 +402,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return deobfuscationMap.getOrDefault(name, name); + } + -+ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { ++ public static EnumSet vanillaToPaper(OptimizedSmallEnumSet types) { + EnumSet goals = EnumSet.noneOf(GoalType.class); + for (GoalType type : GoalType.values()) { + if (types.hasElement(paperToVanilla(type))) { @@ -481,7 +412,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return goals; + } + -+ public static GoalType vanillaToPaper(PathfinderGoal.Type type) { ++ public static GoalType vanillaToPaper(Goal.Flag type) { + switch (type) { + case MOVE: + return GoalType.MOVE; @@ -498,32 +429,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ public static EnumSet paperToVanilla(EnumSet types) { -+ EnumSet goals = EnumSet.noneOf(PathfinderGoal.Type.class); ++ public static EnumSet paperToVanilla(EnumSet types) { ++ EnumSet goals = EnumSet.noneOf(Goal.Flag.class); + for (GoalType type : types) { + goals.add(paperToVanilla(type)); + } + return goals; + } + -+ public static PathfinderGoal.Type paperToVanilla(GoalType type) { ++ public static Goal.Flag paperToVanilla(GoalType type) { + switch (type) { + case MOVE: -+ return PathfinderGoal.Type.MOVE; ++ return Goal.Flag.MOVE; + case LOOK: -+ return PathfinderGoal.Type.LOOK; ++ return Goal.Flag.LOOK; + case JUMP: -+ return PathfinderGoal.Type.JUMP; ++ return Goal.Flag.JUMP; + case UNKNOWN_BEHAVIOR: -+ return PathfinderGoal.Type.UNKNOWN_BEHAVIOR; ++ return Goal.Flag.UNKNOWN_BEHAVIOR; + case TARGET: -+ return PathfinderGoal.Type.TARGET; ++ return Goal.Flag.TARGET; + default: + throw new IllegalArgumentException("Unknown paper mob goal type " + type.name()); + } + } + -+ public static GoalKey getKey(Class goalClass) { ++ public static GoalKey getKey(Class goalClass) { + String name = getUsableName(goalClass); + if (ignored.contains(name)) { + //noinspection unchecked @@ -532,16 +463,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return GoalKey.of(getEntity(goalClass), NamespacedKey.minecraft(name)); + } + -+ public static Class getEntity(Class goalClass) { ++ 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)) { ++ if (net.minecraft.world.entity.Mob.class.isAssignableFrom(param)) { + //noinspection unchecked -+ return toBukkitClass((Class) param); -+ } else if (IRangedEntity.class.isAssignableFrom(param)) { ++ return toBukkitClass((Class) param); ++ } else if (RangedAttackMob.class.isAssignableFrom(param)) { + return RangedEntity.class; + } + } @@ -550,7 +481,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + -+ public static Class toBukkitClass(Class nmsClass) { ++ 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? @@ -566,32 +497,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.entity.ai; + -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; +import org.bukkit.entity.Mob; ++import com.destroystokyo.paper.entity.ai.Goal; + +/** + * Wraps api in vanilla + */ -+public class PaperCustomGoal extends PathfinderGoal { ++public class PaperCustomGoal extends net.minecraft.world.entity.ai.goal.Goal { + + private final Goal handle; + + public PaperCustomGoal(Goal handle) { + this.handle = handle; + -+ this.setTypes(MobGoalHelper.paperToVanilla(handle.getTypes())); ++ this.setFlags(MobGoalHelper.paperToVanilla(handle.getTypes())); + if (this.getGoalTypes().size() == 0) { -+ this.getGoalTypes().addUnchecked(Type.UNKNOWN_BEHAVIOR); ++ this.getGoalTypes().addUnchecked(Flag.UNKNOWN_BEHAVIOR); + } + } + + @Override -+ public boolean shouldActivate() { ++ public boolean canUse() { + return handle.shouldActivate(); + } + + @Override -+ public boolean shouldStayActive() { ++ public boolean canContinueToUse() { + return handle.shouldStayActive(); + } + @@ -601,7 +532,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public void onTaskReset() { ++ public void stop() { + handle.stop(); + } + @@ -634,15 +565,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.world.entity.ai.goal.GoalSelector; ++import net.minecraft.world.entity.ai.goal.WrappedGoal; +import org.bukkit.craftbukkit.entity.CraftMob; +import org.bukkit.entity.Mob; + +public class PaperMobGoals implements MobGoals { + -+ private final Map> instanceCache = new HashMap<>(); ++ private final Map> instanceCache = new HashMap<>(); + + @Override + public void addGoal(T mob, int priority, Goal goal) { @@ -654,12 +584,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void removeGoal(T mob, Goal goal) { + CraftMob craftMob = (CraftMob) mob; + if (goal instanceof PaperCustomGoal) { -+ getHandle(craftMob, goal.getTypes()).removeGoal((PathfinderGoal) goal); ++ getHandle(craftMob, goal.getTypes()).removeGoal((net.minecraft.world.entity.ai.goal.Goal) 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()) { ++ List toRemove = new LinkedList<>(); ++ for (WrappedGoal item : getHandle(craftMob, goal.getTypes()).availableGoals) { + if (item.getGoal() instanceof PaperCustomGoal) { + //noinspection unchecked + if (((PaperCustomGoal) item.getGoal()).getHandle() == goal) { @@ -668,7 +598,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ for (PathfinderGoal g : toRemove) { ++ for (net.minecraft.world.entity.ai.goal.Goal g : toRemove) { + getHandle(craftMob, goal.getTypes()).removeGoal(g); + } + } @@ -739,7 +669,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public Collection> getAllGoals(T mob, GoalType type) { + CraftMob craftMob = (CraftMob) mob; + Set> goals = new HashSet<>(); -+ for (PathfinderGoalWrapped item : getHandle(craftMob, type).getTasks()) { ++ for (WrappedGoal item : getHandle(craftMob, type).availableGoals) { + if (!item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { + continue; + } @@ -763,7 +693,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (internalType == type) { + continue; + } -+ for (PathfinderGoalWrapped item : getHandle(craftMob, internalType).getTasks()) { ++ for (WrappedGoal item : getHandle(craftMob, internalType).availableGoals) { + if (item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) { + continue; + } @@ -793,7 +723,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public Collection> getRunningGoals(T mob, GoalType type) { + CraftMob craftMob = (CraftMob) mob; + Set> goals = new HashSet<>(); -+ getHandle(craftMob, type).getExecutingGoals() ++ getHandle(craftMob, type).getRunningGoals() + .filter(item -> item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) + .forEach(item -> { + if (item.getGoal() instanceof PaperCustomGoal) { @@ -815,7 +745,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (internalType == type) { + continue; + } -+ getHandle(craftMob, internalType).getExecutingGoals() ++ getHandle(craftMob, internalType).getRunningGoals() + .filter(item -> !item.getGoal().getGoalTypes().hasElement(MobGoalHelper.paperToVanilla(type))) + .forEach(item -> { + if (item.getGoal() instanceof PaperCustomGoal) { @@ -830,7 +760,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return goals; + } + -+ private PathfinderGoalSelector getHandle(CraftMob mob, EnumSet types) { ++ private GoalSelector getHandle(CraftMob mob, EnumSet types) { + if (types.contains(GoalType.TARGET)) { + return mob.getHandle().targetSelector; + } else { @@ -838,7 +768,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private PathfinderGoalSelector getHandle(CraftMob mob, GoalType type) { ++ private GoalSelector getHandle(CraftMob mob, GoalType type) { + if (type == GoalType.TARGET) { + return mob.getHandle().targetSelector; + } else { @@ -855,8 +785,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package com.destroystokyo.paper.entity.ai; + +import java.util.EnumSet; -+ -+import net.minecraft.world.entity.ai.goal.PathfinderGoal; ++import net.minecraft.world.entity.ai.goal.Goal; +import org.bukkit.entity.Mob; + +/** @@ -864,29 +793,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ +public class PaperVanillaGoal implements VanillaGoal { + -+ private final PathfinderGoal handle; ++ private final Goal handle; + private final GoalKey key; + + private final EnumSet types; + -+ public PaperVanillaGoal(PathfinderGoal handle) { ++ public PaperVanillaGoal(Goal handle) { + this.handle = handle; + this.key = MobGoalHelper.getKey(handle.getClass()); + this.types = MobGoalHelper.vanillaToPaper(handle.getGoalTypes()); + } + -+ public PathfinderGoal getHandle() { ++ public Goal getHandle() { + return handle; + } + + @Override + public boolean shouldActivate() { -+ return handle.shouldActivate2(); ++ return handle.canUse(); + } + + @Override + public boolean shouldStayActive() { -+ return handle.shouldStayActive2(); ++ return handle.canContinueToUse(); + } + + @Override @@ -896,7 +825,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public void stop() { -+ handle.onTaskReset(); ++ handle.stop(); + } + + @Override @@ -927,121 +856,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.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 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -0,0 +0,0 @@ public abstract class Goal { + private final EnumSet flags = EnumSet.noneOf(Goal.Flag.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 com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector -- public PathfinderGoal() {} + // Paper start make sure goaltypes is never empty -+ public PathfinderGoal() { ++ public Goal() { + if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); ++ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR); + } + } -+ // paper end ++ // Paper end ++ + public abstract boolean canUse(); -- 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 + public boolean canContinueToUse() { +@@ -0,0 +0,0 @@ public abstract class Goal { // Paper start - remove streams from pathfindergoalselector this.goalTypes.clear(); - this.goalTypes.addAllUnchecked(enumset); + this.goalTypes.addAllUnchecked(controls); + // make sure its never empty + if (this.goalTypes.size() == 0) { -+ this.goalTypes.addUnchecked(Type.UNKNOWN_BEHAVIOR); ++ this.goalTypes.addUnchecked(Flag.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; +@@ -0,0 +0,0 @@ public abstract class Goal { } -- 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) { + public static enum Flag { ++ UNKNOWN_BEHAVIOR, // Paper - add UNKNOWN_BEHAVIOR + MOVE, + LOOK, + JUMP, 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 @@ -1066,8 +918,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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; + @@ -1106,13 +956,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + List> classes; + try (ScanResult scanResult = new ClassGraph().enableAllInfo().whitelistPackages("net.minecraft").scan()) { -+ classes = scanResult.getSubclasses(PathfinderGoal.class.getName()).loadClasses(); ++ classes = scanResult.getSubclasses(net.minecraft.world.entity.ai.goal.Goal.class.getName()).loadClasses(); + } + + List> vanillaNames = classes.stream() + .filter(VanillaMobGoalTest::hasNoEnclosingClass) + .filter(clazz -> !Modifier.isAbstract(clazz.getModifiers())) -+ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) ++ .filter(clazz -> !net.minecraft.world.entity.ai.goal.WrappedGoal.class.equals(clazz)) // TODO - properly fix ++ .map(goalClass -> MobGoalHelper.getKey((Class) goalClass)) + .collect(Collectors.toList()); + + List> missingFromAPI = new ArrayList<>(vanillaNames); @@ -1152,13 +1003,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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(); ++ classes = scanResult.getSubclasses("net.minecraft.world.entity.Mob").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); ++ 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);"); diff --git a/Spigot-Server-Patches/Implement-Paper-VersionChecker.patch b/patches/server/Implement-Paper-VersionChecker.patch similarity index 100% rename from Spigot-Server-Patches/Implement-Paper-VersionChecker.patch rename to patches/server/Implement-Paper-VersionChecker.patch diff --git a/patches/server/Implement-Player-Client-Options-API.patch b/patches/server/Implement-Player-Client-Options-API.patch new file mode 100644 index 0000000000..9eb2e5f9f3 --- /dev/null +++ b/patches/server/Implement-Player-Client-Options-API.patch @@ -0,0 +1,127 @@ +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/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public String locale = null; // CraftBukkit - add, lowercase // Paper - default to null + public java.util.Locale adventure$locale = java.util.Locale.US; // Paper + public void updateOptions(ServerboundClientInformationPacket packet) { ++ new com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent(getBukkitEntity(), packet.language, packet.viewDistance, com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(packet.getChatVisibility().name()), packet.getChatColors(), new com.destroystokyo.paper.PaperSkinParts(packet.getModelCustomisation()), packet.getMainHand() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT).callEvent(); // Paper - settings event + // CraftBukkit start + if (getMainArm() != packet.getMainHand()) { + PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); +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 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(com.destroystokyo.paper.ClientOption type) { ++ if(com.destroystokyo.paper.ClientOption.SKIN_PARTS.equals(type)) { ++ return type.getType().cast(new com.destroystokyo.paper.PaperSkinParts(getHandle().getEntityData().get(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION))); ++ } else if(com.destroystokyo.paper.ClientOption.CHAT_COLORS_ENABLED.equals(type)) { ++ return type.getType().cast(getHandle().canChatInColor()); ++ } else if(com.destroystokyo.paper.ClientOption.CHAT_VISIBILITY.equals(type)) { ++ return type.getType().cast(getHandle().getChatVisibility() == null ? com.destroystokyo.paper.ClientOption.ChatVisibility.UNKNOWN : com.destroystokyo.paper.ClientOption.ChatVisibility.valueOf(getHandle().getChatVisibility().name())); ++ } else if(com.destroystokyo.paper.ClientOption.LOCALE.equals(type)) { ++ return type.getType().cast(getLocale()); ++ } else if(com.destroystokyo.paper.ClientOption.MAIN_HAND.equals(type)) { ++ return type.getType().cast(getMainHand()); ++ } else if(com.destroystokyo.paper.ClientOption.VIEW_DISTANCE.equals(type)) { ++ return type.getType().cast(getClientViewDistance()); ++ } ++ throw new RuntimeException("Unknown settings type"); ++ } + // Paper end + + @Override diff --git a/patches/server/Implement-PlayerFlowerPotManipulateEvent.patch b/patches/server/Implement-PlayerFlowerPotManipulateEvent.patch new file mode 100644 index 0000000000..0def07cf68 --- /dev/null +++ b/patches/server/Implement-PlayerFlowerPotManipulateEvent.patch @@ -0,0 +1,37 @@ +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/FlowerPotBlock.java b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FlowerPotBlock.java +@@ -0,0 +0,0 @@ public class FlowerPotBlock extends Block { + boolean bl = blockState.is(Blocks.AIR); + boolean bl2 = this.isEmpty(); + if (bl != bl2) { ++ // Paper start ++ org.bukkit.entity.Player player1 = (org.bukkit.entity.Player) player.getBukkitEntity(); ++ boolean placing = bl2; ++ org.bukkit.block.Block bukkitblock = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); ++ org.bukkit.inventory.ItemStack bukkititemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemStack); ++ org.bukkit.Material mat = org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(content); ++ org.bukkit.inventory.ItemStack bukkititemstack1 = new org.bukkit.inventory.ItemStack(mat, 1); ++ org.bukkit.inventory.ItemStack whichitem = placing ? bukkititemstack : bukkititemstack1; ++ ++ io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent event = new io.papermc.paper.event.player.PlayerFlowerPotManipulateEvent(player1, bukkitblock, whichitem, placing); ++ player1.getServer().getPluginManager().callEvent(event); ++ ++ if (event.isCancelled()) { ++ // Update client ++ player1.sendBlockChange(bukkitblock.getLocation(), bukkitblock.getBlockData()); ++ player1.updateInventory(); ++ ++ return InteractionResult.PASS; ++ } ++ // Paper end + if (bl2) { + world.setBlock(pos, blockState, 3); + player.awardStat(Stats.POT_FLOWER); diff --git a/Spigot-Server-Patches/Implement-PlayerLocaleChangeEvent.patch b/patches/server/Implement-PlayerLocaleChangeEvent.patch similarity index 60% rename from Spigot-Server-Patches/Implement-PlayerLocaleChangeEvent.patch rename to patches/server/Implement-PlayerLocaleChangeEvent.patch index 551a52c013..63c0f2b359 100644 --- a/Spigot-Server-Patches/Implement-PlayerLocaleChangeEvent.patch +++ b/patches/server/Implement-PlayerLocaleChangeEvent.patch @@ -4,30 +4,30 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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 { +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { 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) { + public void updateOptions(ServerboundClientInformationPacket packet) { // 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); +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.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); +- if (!this.locale.equals(packet.language)) { ++ if (this.locale == null || !this.locale.equals(packet.language)) { // Paper - check for null + PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(this.getBukkitEntity(), packet.language); this.server.server.getPluginManager().callEvent(event); -+ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packetplayinsettings.locale).callEvent(); // Paper ++ new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), this.locale, packet.language).callEvent(); // Paper } - this.locale = packetplayinsettings.locale; + this.locale = packet.language; // 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 @@ -37,10 +37,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public String getLocale() { -- return getHandle().locale; +- return this.getHandle().locale; - + // Paper start - Locale change event -+ final String locale = getHandle().locale; ++ final String locale = this.getHandle().locale; + return locale != null ? locale : "en_us"; + // Paper end } diff --git a/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch b/patches/server/Implement-PlayerPostRespawnEvent.patch similarity index 85% rename from Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch rename to patches/server/Implement-PlayerPostRespawnEvent.patch index 1c48e3be5d..35a98837a2 100644 --- a/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch +++ b/patches/server/Implement-PlayerPostRespawnEvent.patch @@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (location == null) { - boolean isBedSpawn = false; + // boolean isBedSpawn = false; // Paper - moved up - WorldServer worldserver1 = this.server.getWorldServer(entityplayer.getSpawnDimension()); + ServerLevel worldserver1 = this.server.getLevel(entityplayer.getRespawnDimension()); if (worldserver1 != null) { Optional optional; @@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -33,8 +33,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 location.setWorld(worldserver.getWorld()); } @@ -0,0 +0,0 @@ public abstract class PlayerList { - if (entityplayer.playerConnection.isDisconnected()) { - this.savePlayerFile(entityplayer); + if (entityplayer.connection.isDisconnected()) { + this.save(entityplayer); } + + // Paper start diff --git a/patches/server/Implement-TargetHitEvent.patch b/patches/server/Implement-TargetHitEvent.patch new file mode 100644 index 0000000000..3b94d70401 --- /dev/null +++ b/patches/server/Implement-TargetHitEvent.patch @@ -0,0 +1,42 @@ +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/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +@@ -0,0 +0,0 @@ public class TargetBlock extends Block { + @Override + public void onProjectileHit(Level world, BlockState state, BlockHitResult hit, Projectile projectile) { + int i = updateRedstoneOutput(world, state, hit, projectile); ++ // Paper start ++ } ++ private static void awardTargetHitCriteria(Projectile projectile, BlockHitResult hit, int i) { ++ // Paper end + Entity entity = projectile.getOwner(); + if (entity instanceof ServerPlayer) { + ServerPlayer serverPlayer = (ServerPlayer)entity; +@@ -0,0 +0,0 @@ public class TargetBlock extends Block { + private static int updateRedstoneOutput(LevelAccessor world, BlockState state, BlockHitResult hitResult, Entity entity) { + int i = getRedstoneStrength(hitResult, hitResult.getLocation()); + int j = entity instanceof AbstractArrow ? 20 : 8; ++ // Paper start ++ if (entity instanceof Projectile) { ++ final Projectile projectile = (Projectile) entity; ++ final org.bukkit.craftbukkit.block.CraftBlock craftBlock = org.bukkit.craftbukkit.block.CraftBlock.at(world, hitResult.getBlockPos()); ++ final org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(hitResult.getDirection()); ++ final io.papermc.paper.event.block.TargetHitEvent targetHitEvent = new io.papermc.paper.event.block.TargetHitEvent((org.bukkit.entity.Projectile) projectile.getBukkitEntity(), craftBlock, blockFace, i); ++ if (targetHitEvent.callEvent()) { ++ i = targetHitEvent.getSignalStrength(); ++ awardTargetHitCriteria(projectile, hitResult, i); ++ } else { ++ return i; ++ } ++ } ++ // Paper end + if (!world.getBlockTicks().hasScheduledTick(hitResult.getBlockPos(), state.getBlock())) { + setOutputPower(world, state, i, hitResult.getBlockPos(), j); + } diff --git a/Spigot-Server-Patches/Implement-World.getEntity-UUID-API.patch b/patches/server/Implement-World.getEntity-UUID-API.patch similarity index 100% rename from Spigot-Server-Patches/Implement-World.getEntity-UUID-API.patch rename to patches/server/Implement-World.getEntity-UUID-API.patch diff --git a/Spigot-Server-Patches/Implement-alternative-item-despawn-rate.patch b/patches/server/Implement-alternative-item-despawn-rate.patch similarity index 50% rename from Spigot-Server-Patches/Implement-alternative-item-despawn-rate.patch rename to patches/server/Implement-alternative-item-despawn-rate.patch index bbd21c7d53..d5867037b3 100644 --- a/Spigot-Server-Patches/Implement-alternative-item-despawn-rate.patch +++ b/patches/server/Implement-alternative-item-despawn-rate.patch @@ -8,43 +8,26 @@ diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/m 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); + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); } -+ + + public boolean altItemDespawnRateEnabled; -+ public Map altItemDespawnRateMap; ++ public java.util.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()) { ++ java.util.Map altItemDespawnRateMapDefault = new java.util.EnumMap<>(org.bukkit.Material.class); ++ altItemDespawnRateMapDefault.put(org.bukkit.Material.COBBLESTONE, 300); ++ for (org.bukkit.Material key : altItemDespawnRateMapDefault.keySet()) { + config.addDefault("world-settings.default." + path + ".items." + key, altItemDespawnRateMapDefault.get(key)); + } + -+ Map rawMap = new HashMap<>(); ++ java.util.Map rawMap = new java.util.HashMap<>(); + try { -+ ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); ++ org.bukkit.configuration.ConfigurationSection mapSection = config.getConfigurationSection("world-settings." + worldName + "." + path + ".items"); + if (mapSection == null) { + mapSection = config.getConfigurationSection("world-settings.default." + path + ".items"); + } @@ -58,70 +41,65 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + altItemDespawnRateEnabled = false; + } + -+ altItemDespawnRateMap = new EnumMap<>(Material.class); ++ altItemDespawnRateMap = new java.util.EnumMap<>(org.bukkit.Material.class); + if (!altItemDespawnRateEnabled) { + return; + } + + for(String key : rawMap.keySet()) { + try { -+ altItemDespawnRateMap.put(Material.valueOf(key), rawMap.get(key)); ++ altItemDespawnRateMap.put(org.bukkit.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()) { ++ for(org.bukkit.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 ++ + public boolean antiXray; + public EngineMode engineMode; + public int maxBlockHeight; +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { } } -- if (!this.world.isClientSide && this.age >= world.spigotConfig.itemDespawnRate) { // Spigot -+ if (!this.world.isClientSide && this.age >= this.getDespawnRate()) { // Spigot // Paper +- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.level.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 { +@@ -0,0 +0,0 @@ public class ItemEntity 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 +- if (!this.level.isClientSide && this.age >= level.spigotConfig.itemDespawnRate) { // Spigot ++ if (!this.level.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 { +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { - public void s() { - this.o(); -- this.age = world.spigotConfig.itemDespawnRate - 1; // Spigot -+ this.age = this.getDespawnRate() - 1; // Spigot // Paper + public void makeFakeItem() { + this.setNeverPickUp(); +- this.age = level.spigotConfig.itemDespawnRate - 1; // Spigot ++ this.age = this.getDespawnRate() - 1; // Spigot } + // Paper start + public int getDespawnRate(){ -+ Material material = this.getItemStack().getBukkitStack().getType(); -+ return world.paperConfig.altItemDespawnRateMap.getOrDefault(material, world.spigotConfig.itemDespawnRate); ++ org.bukkit.Material material = this.getItem().getBukkitStack().getType(); ++ return level.paperConfig.altItemDespawnRateMap.getOrDefault(material, level.spigotConfig.itemDespawnRate); + } + // Paper end + - @Override - public Packet P() { - return new PacketPlayOutSpawnEntity(this); + public float getSpin(float tickDelta) { + return ((float) this.getAge() + tickDelta) / 20.0F + this.bobOffs; + } diff --git a/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/patches/server/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch similarity index 76% rename from Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch rename to patches/server/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch index a220233e9c..a6acb9bc2b 100644 --- a/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch +++ b/patches/server/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch @@ -4,52 +4,10 @@ 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 @@ -102,12 +60,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw()); @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - persistentDataContainer.put(key, compound.get(key)); + this.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); ++ if (tag.contains(CAN_DESTROY.NBT)) { ++ ListTag 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) { @@ -118,8 +76,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ if (tag.hasKey(CAN_PLACE_ON.NBT)) { -+ NBTTagList list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING); ++ if (tag.contains(CAN_PLACE_ON.NBT)) { ++ ListTag 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) { @@ -131,10 +89,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end - Set keys = tag.getKeys(); + Set keys = tag.getAllKeys(); for (String key : keys) { @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - setDamage(damage); + this.setDamage(damage); } + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values @@ -169,8 +127,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); + if (this.hasDamage()) { + itemTag.putInt(DAMAGE.NBT, damage); } + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values + if (hasPlaceableKeys()) { @@ -178,7 +136,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .map(this::serializeNamespaced) + .collect(java.util.stream.Collectors.toList()); + -+ itemTag.set(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); ++ itemTag.put(CAN_PLACE_ON.NBT, createNonComponentStringList(items)); + } + + if (hasDestroyableKeys()) { @@ -186,40 +144,40 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .map(this::serializeNamespaced) + .collect(java.util.stream.Collectors.toList()); + -+ itemTag.set(CAN_DESTROY.NBT, createNonComponentStringList(items)); ++ itemTag.put(CAN_DESTROY.NBT, createNonComponentStringList(items)); + } + // Paper end - for (Map.Entry e : unhandledTags.entrySet()) { - itemTag.set(e.getKey(), e.getValue()); + for (Map.Entry e : this.unhandledTags.entrySet()) { + itemTag.put(e.getKey(), e.getValue()); @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } } + // Paper start -+ static NBTTagList createNonComponentStringList(List list) { ++ static ListTag createNonComponentStringList(List list) { + if (list == null || list.isEmpty()) { + return null; + } + -+ NBTTagList tagList = new NBTTagList(); ++ ListTag tagList = new ListTag(); + for (String value : list) { -+ tagList.add(NBTTagString.a(value)); // Paper - NBTTagString.of(String str) ++ tagList.add(StringTag.valueOf(value)); // Paper - NBTTagString.of(String str) + } + + return tagList; + } + // Paper end + - NBTTagList createStringList(List list) { + ListTag 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 +- return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers()); ++ return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers() || this.hasPlaceableKeys() || this.hasDestroyableKeys()); // Paper - Implement an API for CanPlaceOn and CanDestroy NBT values } // Paper start @@ -237,12 +195,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 /** @@ -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; + hash = 61 * hash + (this.hasDamage() ? this.damage : 0); + hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); + hash = 61 * hash + this.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); ++ hash = 61 * hash + (this.hasPlaceableKeys() ? this.placeableKeys.hashCode() : 0); ++ hash = 61 * hash + (this.hasDestroyableKeys() ? this.destroyableKeys.hashCode() : 0); + // Paper end return hash; } @@ -267,7 +225,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values -+ if (hasPlaceableKeys()) { ++ if (this.hasPlaceableKeys()) { + List cerealPlaceable = this.placeableKeys.stream() + .map(this::serializeNamespaced) + .collect(java.util.stream.Collectors.toList()); @@ -275,7 +233,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + builder.put(CAN_PLACE_ON.BUKKIT, cerealPlaceable); + } + -+ if (hasDestroyableKeys()) { ++ if (this.hasDestroyableKeys()) { + List cerealDestroyable = this.destroyableKeys.stream() + .map(this::serializeNamespaced) + .collect(java.util.stream.Collectors.toList()); @@ -283,9 +241,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + builder.put(CAN_DESTROY.BUKKIT, cerealDestroyable); + } + // Paper end -+ - final Map internalTags = new HashMap(unhandledTags); - serializeInternal(internalTags); + final Map internalTags = new HashMap(this.unhandledTags); + this.serializeInternal(internalTags); if (!internalTags.isEmpty()) { @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { CraftMetaArmorStand.SHOW_ARMS.NBT, @@ -392,7 +349,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + 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); ++ net.minecraft.commands.arguments.blocks.BlockStateParser blockParser = new net.minecraft.commands.arguments.blocks.BlockStateParser(new com.mojang.brigadier.StringReader(raw), true); + try { + blockParser = blockParser.parse(false); + } catch (com.mojang.brigadier.exceptions.CommandSyntaxException e) { @@ -400,11 +357,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + -+ MinecraftKey key; ++ net.minecraft.resources.ResourceLocation key; + if (isTag) { -+ key = blockParser.getTagKey(); ++ key = blockParser.getTag(); + } else { -+ key = blockParser.getBlockKey(); ++ key = blockParser.id; + } + + if (key == null) { @@ -415,7 +372,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + Namespaced resource = null; + try { + if (isTag) { -+ resource = new NamespacedTag(key.getNamespace(), key.getKey()); ++ resource = new NamespacedTag(key.getNamespace(), key.getPath()); + } else { + resource = CraftNamespacedKey.fromMinecraft(key); + } diff --git a/Spigot-Server-Patches/Implement-ensureServerConversions-API.patch b/patches/server/Implement-ensureServerConversions-API.patch similarity index 95% rename from Spigot-Server-Patches/Implement-ensureServerConversions-API.patch rename to patches/server/Implement-ensureServerConversions-API.patch index d45cbbe21a..261062df05 100644 --- a/Spigot-Server-Patches/Implement-ensureServerConversions-API.patch +++ b/patches/server/Implement-ensureServerConversions-API.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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()); + return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName()); } + + // Paper start diff --git a/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch b/patches/server/Implement-extended-PaperServerListPingEvent.patch similarity index 58% rename from Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch rename to patches/server/Implement-extended-PaperServerListPingEvent.patch index 99abd416e6..186357a88a 100644 --- a/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch +++ b/patches/server/Implement-extended-PaperServerListPingEvent.patch @@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import com.destroystokyo.paper.event.server.PaperServerListPingEvent; +import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.ServerPlayer; +import org.bukkit.entity.Player; +import org.bukkit.util.CachedServerIcon; + @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + PaperServerListPingEventImpl(MinecraftServer server, StatusClient client, int protocolVersion, @Nullable CachedServerIcon icon) { + super(client, server.getMotd(), server.getPlayerCount(), server.getMaxPlayers(), -+ server.getServerModName() + ' ' + server.getVersion(), protocolVersion, icon); ++ server.getServerModName() + ' ' + server.getServerVersion(), protocolVersion, icon); + this.server = server; + } + @@ -37,7 +37,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + protected final Player getBukkitPlayer(Object player) { -+ return ((EntityPlayer) player).getBukkitEntity(); ++ return ((ServerPlayer) player).getBukkitEntity(); + } + +} @@ -49,11 +49,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.network; + -+import net.minecraft.network.NetworkManager; ++import net.minecraft.network.Connection; + +class PaperStatusClient extends PaperNetworkClient implements StatusClient { + -+ PaperStatusClient(NetworkManager networkManager) { ++ PaperStatusClient(Connection networkManager) { + super(networkManager); + } + @@ -75,9 +75,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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.network.Connection; ++import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; ++import net.minecraft.network.protocol.status.ServerStatus; +import net.minecraft.server.MinecraftServer; + +public final class StandardPaperServerListPingEventImpl extends PaperServerListPingEventImpl { @@ -87,8 +87,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + 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()); ++ private StandardPaperServerListPingEventImpl(MinecraftServer server, Connection networkManager, ServerStatus ping) { ++ super(server, new PaperStatusClient(networkManager), ping.getVersion() != null ? ping.getVersion().getProtocol() : -1, server.server.getServerIcon()); + this.originalSample = ping.getPlayers() == null ? null : ping.getPlayers().getSample(); // GH-1473 - pre-tick race condition NPE + } + @@ -139,30 +139,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @SuppressWarnings("deprecation") -+ public static void processRequest(MinecraftServer server, NetworkManager networkManager) { -+ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getServerPing()); ++ public static void processRequest(MinecraftServer server, Connection networkManager) { ++ StandardPaperServerListPingEventImpl event = new StandardPaperServerListPingEventImpl(server, networkManager, server.getStatus()); + server.server.getPluginManager().callEvent(event); + + // Close connection immediately if event is cancelled + if (event.isCancelled()) { -+ networkManager.close(null); ++ networkManager.disconnect(null); + return; + } + + // Setup response -+ ServerPing ping = new ServerPing(); ++ ServerStatus ping = new ServerStatus(); + + // Description -+ ping.setMOTD(new AdventureComponent(event.motd())); ++ ping.setDescription(new AdventureComponent(event.motd())); + + // Players + if (!event.shouldHidePlayers()) { -+ ping.setPlayerSample(new ServerPing.ServerPingPlayerSample(event.getMaxPlayers(), event.getNumPlayers())); ++ ping.setPlayers(new ServerStatus.Players(event.getMaxPlayers(), event.getNumPlayers())); + ping.getPlayers().setSample(event.getPlayerSampleHandle()); + } + + // Version -+ ping.setServerInfo(new ServerPing.ServerData(event.getVersion(), event.getProtocolVersion())); ++ ping.setVersion(new ServerStatus.Version(event.getVersion(), event.getProtocolVersion())); + + // Favicon + if (event.getServerIcon() != null) { @@ -170,58 +170,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + // Send response -+ networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); ++ networkManager.send(new ClientboundStatusResponsePacket(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 +diff --git a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.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; +--- a/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/status/ClientboundStatusResponsePacket.java +@@ -0,0 +0,0 @@ import net.minecraft.util.GsonHelper; + import net.minecraft.util.LowerCaseEnumTypeAdapterFactory; - 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()) + public class ClientboundStatusResponsePacket implements Packet { +- private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()).create(); ++ private static final Gson GSON = (new GsonBuilder()).registerTypeAdapter(ServerStatus.Version.class, new ServerStatus.Version.Serializer()).registerTypeAdapter(ServerStatus.Players.class, new ServerStatus.Players.Serializer()).registerTypeAdapter(ServerStatus.class, new ServerStatus.Serializer()).registerTypeHierarchyAdapter(Component.class, new Component.Serializer()).registerTypeHierarchyAdapter(Style.class, new Style.Serializer()).registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory()) ++ .registerTypeAdapter(io.papermc.paper.adventure.AdventureComponent.class, new io.papermc.paper.adventure.AdventureComponent.Serializer()) + .create(); - private ServerPing b; + private final ServerStatus status; - 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; - } + public ClientboundStatusResponsePacket(ServerStatus metadata) { 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 @@ -236,34 +203,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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())); +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 5000000000L) { + this.lastServerStatus = i; + this.status.setPlayers(new ServerStatus.Players(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); + int j = Mth.nextInt(this.random, 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.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); +--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + this.connection.disconnect(ServerStatusPacketListenerImpl.DISCONNECT_REASON); } else { - this.d = true; + this.hasRequestedStatus = 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)); + final Object[] players = this.server.getPlayerList().players.toArray(); +@@ -0,0 +0,0 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene + ping.setVersion(new ServerStatus.Version(this.server.getServerModName() + " " + this.server.getServerVersion(), version)); - this.networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); + this.connection.send(new ClientboundStatusResponsePacket(ping)); + */ -+ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.minecraftServer, this.networkManager); ++ com.destroystokyo.paper.network.StandardPaperServerListPingEventImpl.processRequest(this.server, this.connection); + // Paper end } // CraftBukkit end @@ -276,8 +243,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +- SpigotConfig.playerSample = SpigotConfig.getInt( "settings.sample-count", 12 ); ++ SpigotConfig.playerSample = Math.max( SpigotConfig.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/patches/server/Implement-furnace-cook-speed-multiplier-API.patch b/patches/server/Implement-furnace-cook-speed-multiplier-API.patch new file mode 100644 index 0000000000..c1705faa6c --- /dev/null +++ b/patches/server/Implement-furnace-cook-speed-multiplier-API.patch @@ -0,0 +1,106 @@ +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/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + protected NonNullList items; + public int litTime; + int litDuration; ++ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API + public int cookingProgress; + public int cookingTotalTime; + protected final ContainerData dataAccess; +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + this.recipesUsed.put(new ResourceLocation(s), nbttagcompound1.getInt(s)); + } + ++ // Paper start - cook speed API ++ if (nbt.contains("Paper.CookSpeedMultiplier")) { ++ this.cookSpeedMultiplier = nbt.getDouble("Paper.CookSpeedMultiplier"); ++ } ++ // Paper end + } + + @Override +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + nbt.putShort("BurnTime", (short) this.litTime); + nbt.putShort("CookTime", (short) this.cookingProgress); + nbt.putShort("CookTimeTotal", (short) this.cookingTotalTime); ++ nbt.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API + ContainerHelper.saveAllItems(nbt, this.items); + CompoundTag nbttagcompound1 = new CompoundTag(); + +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + + if (blockEntity.isLit() && AbstractFurnaceBlockEntity.canBurn(irecipe, blockEntity.items, i)) { + ++blockEntity.cookingProgress; +- if (blockEntity.cookingProgress == blockEntity.cookingTotalTime) { ++ if (blockEntity.cookingProgress >= blockEntity.cookingTotalTime) { // Paper - cook speed multiplier API + blockEntity.cookingProgress = 0; +- blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity.recipeType, blockEntity); ++ blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity.recipeType, blockEntity, blockEntity.cookSpeedMultiplier); + if (AbstractFurnaceBlockEntity.burn(blockEntity.level, blockEntity.worldPosition, irecipe, blockEntity.items, i)) { // CraftBukkit + blockEntity.setRecipeUsed(irecipe); + } +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } + } + +- private static int getTotalCookTime(Level world, RecipeType recipeType, Container inventory) { +- return (world != null) ? (Integer) world.getRecipeManager().getRecipeFor((RecipeType) recipeType, inventory, world).map(AbstractCookingRecipe::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 static int getTotalCookTime(Level world, RecipeType recipeType, Container inventory, final double cookSpeedMultiplier) { ++ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */ ++ int cookTime = world != null ? world.getRecipeManager().getRecipeFor((RecipeType) recipeType, inventory, world).map(AbstractCookingRecipe::getCookingTime).orElse(200) : 200; // CraftBukkit - SPIGOT-4302 // Eclipse fail ++ return (int) Math.ceil (cookTime / cookSpeedMultiplier); + } ++ // Paper end + + public static boolean isFuel(ItemStack stack) { + return AbstractFurnaceBlockEntity.getFuel().containsKey(stack.getItem()); +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + } + + if (slot == 0 && !flag) { +- this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.level, this.recipeType, this); ++ this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.level, this.recipeType, this, this.cookSpeedMultiplier); + this.cookingProgress = 0; + this.setChanged(); + } +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 + public void setCookTimeTotal(int cookTimeTotal) { + this.getSnapshot().cookingTotalTime = 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.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(this.world.getHandle(), snapshot.getCurrentRecipe().getType(), ((CraftInventoryFurnace) this.getInventory()).getInventory(), snapshot.cookSpeedMultiplier); // 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/patches/server/Implement-getI18NDisplayName.patch similarity index 50% rename from Spigot-Server-Patches/Implement-getI18NDisplayName.patch rename to patches/server/Implement-getI18NDisplayName.patch index 9990e53298..17719821ea 100644 --- a/Spigot-Server-Patches/Implement-getI18NDisplayName.patch +++ b/patches/server/Implement-getI18NDisplayName.patch @@ -7,32 +7,6 @@ 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 @@ -52,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + nms = CraftItemStack.asNMSCopy(item); + } + -+ return nms != null ? net.minecraft.locale.LocaleLanguage.getInstance().translateKey(nms.getItem().getName()) : null; ++ return nms != null ? net.minecraft.locale.Language.getInstance().getOrDefault(nms.getItem().getDescriptionId()) : null; + } // Paper end } diff --git a/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch b/patches/server/Implement-methods-to-convert-between-Component-and-B.patch similarity index 91% rename from Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch rename to patches/server/Implement-methods-to-convert-between-Component-and-B.patch index 6faedaa799..61c05830a0 100644 --- a/Spigot-Server-Patches/Implement-methods-to-convert-between-Component-and-B.patch +++ b/patches/server/Implement-methods-to-convert-between-Component-and-B.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.network.chat.ComponentUtils; +import org.checkerframework.checker.nullness.qual.NonNull; + +import static java.util.Objects.requireNonNull; @@ -38,18 +38,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public @NonNull Component componentFromMessage(final @NonNull Message message) { + requireNonNull(message, "message"); -+ return PaperAdventure.asAdventure(ChatComponentUtils.fromMessage(message)); ++ return PaperAdventure.asAdventure(ComponentUtils.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 +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } 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); + this.setPvpAllowed(dedicatedserverproperties.pvp); diff --git a/patches/server/Implemented-BlockFailedDispenseEvent.patch b/patches/server/Implemented-BlockFailedDispenseEvent.patch new file mode 100644 index 0000000000..1492d8bc60 --- /dev/null +++ b/patches/server/Implemented-BlockFailedDispenseEvent.patch @@ -0,0 +1,50 @@ +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/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +@@ -0,0 +0,0 @@ public class DispenserBlock extends BaseEntityBlock { + int i = tileentitydispenser.getRandomSlot(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) {// Paper - BlockFailedDispenseEvent is called here + world.levelEvent(1001, pos, 0); + world.gameEvent(GameEvent.DISPENSE_FAIL, pos); ++ } // Paper + } else { + ItemStack itemstack = tileentitydispenser.getItem(i); + DispenseItemBehavior idispensebehavior = this.getDispenseMethod(itemstack); +diff --git a/src/main/java/net/minecraft/world/level/block/DropperBlock.java b/src/main/java/net/minecraft/world/level/block/DropperBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/DropperBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DropperBlock.java +@@ -0,0 +0,0 @@ public class DropperBlock extends DispenserBlock { + int i = tileentitydispenser.getRandomSlot(); + + if (i < 0) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFailedDispenseEvent(world, pos)) // Paper - BlockFailedDispenseEvent is called here + world.levelEvent(1001, pos, 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 @@ public class CraftEventFactory { + Bukkit.getPluginManager().callEvent(event); + return event; + } ++ ++ // Paper start ++ public static boolean handleBlockFailedDispenseEvent(ServerLevel serverLevel, BlockPos blockposition) { ++ org.bukkit.block.Block block = serverLevel.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); ++ io.papermc.paper.event.block.BlockFailedDispenseEvent event = new io.papermc.paper.event.block.BlockFailedDispenseEvent(block); ++ return event.callEvent(); ++ } ++ // Paper end + } diff --git a/Spigot-Server-Patches/Improve-BlockPosition-inlining.patch b/patches/server/Improve-BlockPosition-inlining.patch similarity index 56% rename from Spigot-Server-Patches/Improve-BlockPosition-inlining.patch rename to patches/server/Improve-BlockPosition-inlining.patch index b4f67f97ea..4653aaf6b2 100644 --- a/Spigot-Server-Patches/Improve-BlockPosition-inlining.patch +++ b/patches/server/Improve-BlockPosition-inlining.patch @@ -20,56 +20,44 @@ This should result in an across the board speedup in anything that accesses bloc 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 +diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.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)); +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -0,0 +0,0 @@ public class Vec3i implements Comparable { } + @Override - 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 { - } + } else if (!(object instanceof Vec3i)) { +@@ -0,0 +0,0 @@ public class Vec3i implements Comparable { } + @Override - 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(); +@@ -0,0 +0,0 @@ public class Vec3i implements Comparable { + } } - public int getX() { + public final int getX() { // Paper - return this.a; + return this.x; } - public int getY() { + public final int getY() { // Paper - return this.b; + return this.y; } - public int getZ() { + public final int getZ() { // Paper - return this.e; + return this.z; } -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/patches/server/Improve-Chunk-Status-Transition-Speed.patch similarity index 52% rename from Spigot-Server-Patches/Improve-Chunk-Status-Transition-Speed.patch rename to patches/server/Improve-Chunk-Status-Transition-Speed.patch index 9f76c26f75..8606e368f0 100644 --- a/Spigot-Server-Patches/Improve-Chunk-Status-Transition-Speed.patch +++ b/patches/server/Improve-Chunk-Status-Transition-Speed.patch @@ -35,65 +35,47 @@ scenario / path: 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 +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.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); - } +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { // Paper end - optimise isOutsideOfRange + long lastAutoSaveTime; // Paper - incremental autosave + long inactiveTimeStart; // Paper - incremental autosave + // 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))); ++ ChunkAccess chunk = getAvailableChunkNow(); ++ return chunk != null && (status == null || chunk.getStatus().isOrAfter(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 + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 { +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return either.mapLeft((list) -> { - return (Chunk) list.get(list.size() / 2); + return (LevelChunk) list.get(list.size() / 2); }); -- }, this.executor); +- }, this.mainThreadExecutor); + }, 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) -> { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return "chunkGenerate " + requiredStatus.getName(); + }); + Executor executor = (runnable) -> { + // Paper start - optimize chunk status progression without jumping through thread pool -+ if (playerchunk.canAdvanceStatus()) { ++ if (holder.canAdvanceStatus()) { + this.mainInvokingExecutor.execute(runnable); + return; + } + // Paper end - this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); - }); - } + this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); + }; + diff --git a/patches/server/Improve-EntityShootBowEvent.patch b/patches/server/Improve-EntityShootBowEvent.patch new file mode 100644 index 0000000000..b5fbb4d63c --- /dev/null +++ b/patches/server/Improve-EntityShootBowEvent.patch @@ -0,0 +1,44 @@ +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/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -0,0 +0,0 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); + // CraftBukkit start +- org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper + if (event.isCancelled()) { + event.getProjectile().remove(); + return; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +@@ -0,0 +0,0 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + + entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level.getDifficulty().getId() * 4)); ++ // Paper start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), entityarrow.getPickupItem(), entityarrow, target.getUsedItemHand(), 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level.addFreshEntity(entityarrow); ++ } + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level.addFreshEntity(entityarrow); ++ // Paper end + } + + @Override diff --git a/patches/server/Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch b/patches/server/Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch new file mode 100644 index 0000000000..88d87428c2 --- /dev/null +++ b/patches/server/Improve-EntityTargetLivingEntityEvent-for-1.16-mobs.patch @@ -0,0 +1,60 @@ +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/StopAttackingIfTargetInvalid.java b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +@@ -0,0 +0,0 @@ public class StopAttackingIfTargetInvalid extends Behavior { + LivingEntity entityliving = this.getAttackTarget(entity); + + if (!entity.canAttack(entityliving)) { +- this.clearAttackTarget(entity); ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } else if (StopAttackingIfTargetInvalid.isTiredOfTryingToReachTarget((LivingEntity) entity)) { +- this.clearAttackTarget(entity); ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.FORGOT_TARGET); // Paper + } else if (this.isCurrentTargetDeadOrRemoved(entity)) { +- this.clearAttackTarget(entity); ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_DIED); // Paper + } else if (this.isCurrentTargetInDifferentLevel(entity)) { +- this.clearAttackTarget(entity); ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_OTHER_LEVEL); // Paper + } else if (this.stopAttackingWhen.test(this.getAttackTarget(entity))) { +- this.clearAttackTarget(entity); ++ this.clearAttackTarget(entity, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_INVALID); // Paper + } + } + +@@ -0,0 +0,0 @@ public class StopAttackingIfTargetInvalid extends Behavior { + return optional.isPresent() && !((LivingEntity) optional.get()).isAlive(); + } + +- protected void clearAttackTarget(E entity) { ++ protected void clearAttackTarget(E entity, EntityTargetEvent.TargetReason reason) { + // CraftBukkit start +- LivingEntity old = entity.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); +- EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, 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(entity, null, reason); + if (event.isCancelled()) { + return; + } +- if (event.getTarget() != null) { +- entity.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); ++ // comment out, bad logic - bad ++ /*if (event.getTarget() != null) { ++ e0.getBehaviorController().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); + return; +- } ++ }*/ ++ // Paper end + // CraftBukkit end + this.onTargetErased.accept(entity); + entity.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); diff --git a/Spigot-Server-Patches/Improve-Legacy-Component-serialization-size.patch b/patches/server/Improve-Legacy-Component-serialization-size.patch similarity index 69% rename from Spigot-Server-Patches/Improve-Legacy-Component-serialization-size.patch rename to patches/server/Improve-Legacy-Component-serialization-size.patch index 004a3e112b..1adb6079de 100644 --- a/Spigot-Server-Patches/Improve-Legacy-Component-serialization-size.patch +++ b/patches/server/Improve-Legacy-Component-serialization-size.patch @@ -14,12 +14,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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 static final Style EMPTY = Style.EMPTY.withItalic(false); // Paper - OBFHELPER + private static final Style RESET = Style.EMPTY.withBold(false).withItalic(false).withUnderlined(false).withStrikethrough(false).withObfuscated(false); - private final List list = new ArrayList(); + 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); + Matcher matcher = (keepNewlines ? StringMessage.INCREMENTAL_PATTERN_KEEP_NEWLINES : StringMessage.INCREMENTAL_PATTERN).matcher(message); String match = null; boolean needsAdd = false; + boolean hasReset = false; // Paper @@ -30,25 +30,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 throw new AssertionError("Unexpected message format"); } } else { // Color resets formatting -- modifier = RESET.setColor(format); +- this.modifier = StringMessage.RESET.withColor(format); + // Paper start - improve legacy formatting -+ ChatModifier previous = modifier; -+ modifier = (!hasReset ? RESET : EMPTY).setColor(format); ++ Style previous = modifier; ++ modifier = (!hasReset ? RESET : EMPTY).withColor(format); + hasReset = true; + if (previous.isBold()) { -+ modifier = modifier.setBold(false); ++ modifier = modifier.withBold(false); + } + if (previous.isItalic()) { -+ modifier = modifier.setItalic(false); ++ modifier = modifier.withItalic(false); + } -+ if (previous.isRandom()) { -+ modifier = modifier.setRandom(false); ++ if (previous.isObfuscated()) { ++ modifier = modifier.withObfuscated(false); + } + if (previous.isStrikethrough()) { -+ modifier = modifier.setStrikethrough(false); ++ modifier = modifier.withStrikethrough(false); + } + if (previous.isUnderlined()) { -+ modifier = modifier.setUnderline(false); ++ modifier = modifier.withUnderlined(false); + } + // Paper end } diff --git a/Spigot-Server-Patches/Improve-Log4J-Configuration-Plugin-Loggers.patch b/patches/server/Improve-Log4J-Configuration-Plugin-Loggers.patch similarity index 100% rename from Spigot-Server-Patches/Improve-Log4J-Configuration-Plugin-Loggers.patch rename to patches/server/Improve-Log4J-Configuration-Plugin-Loggers.patch diff --git a/patches/server/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/patches/server/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch new file mode 100644 index 0000000000..07517b6c77 --- /dev/null +++ b/patches/server/Improve-Maps-in-item-frames-performance-and-bug-fixe.patch @@ -0,0 +1,142 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + { + if ( iter.next().player == entity ) + { ++ map.decorations.remove(entity.getName().getString()); // Paper + iter.remove(); + } + } +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ import net.minecraft.world.item.ElytraItem; + import net.minecraft.world.item.ItemCooldowns; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.item.MapItem; // Paper + import net.minecraft.world.item.ProjectileWeaponItem; + import net.minecraft.world.item.SwordItem; + import net.minecraft.world.item.crafting.Recipe; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.block.entity.StructureBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.block.state.pattern.BlockInWorld; ++import net.minecraft.world.level.saveddata.maps.MapItemSavedData; // Paper + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.scores.PlayerTeam; +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + return null; + } + // CraftBukkit end ++ // Paper start - remove player from map on drop ++ if (stack.getItem() == Items.FILLED_MAP) { ++ MapItemSavedData worldmap = MapItem.getSavedData(stack, this.level); ++ worldmap.tickCarriedBy(this, stack); ++ } ++ // Paper end + + return entityitem; + } +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { + public final Map decorations = Maps.newLinkedHashMap(); + private final Map frameMarkers = Maps.newHashMap(); + private int trackedDecorationCount; ++ 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 MapItemSavedData extends SavedData { + // CraftBukkit start + this.mapView = new CraftMapView(this); + this.server = (CraftServer) org.bukkit.Bukkit.getServer(); ++ this.vanillaRender.buffer = colors; // Paper + // CraftBukkit end + } + +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { + if (abyte.length == 16384) { + worldmap.colors = abyte; + } ++ worldmap.vanillaRender.buffer = abyte; // Paper + + ListTag nbttaglist = nbt.getList("banners", 10); + +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { + + public class HoldingPlayer { + ++ // Paper start ++ private void addSeenPlayers(java.util.Collection icons) { ++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.player.getBukkitEntity(); ++ MapItemSavedData.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 Player player; + private boolean dirtyData = true; + private int minDirtyX; +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { + @Nullable + Packet nextUpdatePacket(int mapId) { + MapItemSavedData.MapPatch worldmap_b; +- org.bukkit.craftbukkit.map.RenderData render = MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()); // CraftBukkit ++ if (!this.dirtyData && this.tick % 5 != 0) { this.tick++; 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 ? MapItemSavedData.this.mapView.render((org.bukkit.craftbukkit.entity.CraftPlayer) this.player.getBukkitEntity()) : MapItemSavedData.this.vanillaRender; // CraftBukkit // Paper + + if (this.dirtyData) { + this.dirtyData = false; +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { + // CraftBukkit start + java.util.Collection icons = new java.util.ArrayList(); + ++ if (vanillaMaps) addSeenPlayers(icons); // Paper ++ + for (org.bukkit.map.MapCursor cursor : render.cursors) { + if (cursor.isVisible()) { + icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure +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/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch b/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch new file mode 100644 index 0000000000..1fbf015998 --- /dev/null +++ b/patches/server/Improve-Server-Thread-Pool-and-Thread-Priorities.patch @@ -0,0 +1,100 @@ +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/Util.java b/src/main/java/net/minecraft/Util.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -0,0 +0,0 @@ import java.util.stream.Stream; + import javax.annotation.Nullable; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.Bootstrap; +-import net.minecraft.util.Mth; ++import net.minecraft.server.ServerWorkerThread; + import net.minecraft.util.datafix.DataFixers; + import net.minecraft.world.level.block.state.properties.Property; + import org.apache.commons.io.IOUtils; +@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; + + public class Util { + private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1); +- private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap"); +- private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); ++ private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap", -2); // Paper - add -2 priority ++ private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - add -1 priority + private static final ExecutorService IO_POOL = makeIoExecutor(); + public static LongSupplier timeSource = System::nanoTime; + public static final UUID NIL_UUID = new UUID(0L, 0L); +@@ -0,0 +0,0 @@ public class Util { + return Instant.now().toEpochMilli(); + } + +- private static ExecutorService makeExecutor(String name) { +- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7); ++ private static ExecutorService makeExecutor(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 executorService; ++ + if (i <= 0) { + executorService = MoreExecutors.newDirectExecutorService(); + } else { +- executorService = new ForkJoinPool(i, (forkJoinPool) -> { +- ForkJoinWorkerThread forkJoinWorkerThread = new ForkJoinWorkerThread(forkJoinPool) { ++ executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue(), target -> new ServerWorkerThread(target, s, priorityModifier)); ++ } ++ /* + @Override + protected void onTermination(Throwable throwable) { + if (throwable != null) { +@@ -0,0 +0,0 @@ public class Util { + return forkJoinWorkerThread; + }, Util::onThreadException, true); + } ++ }*/ // Paper end + + return executorService; + } +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 ReentrantBlockableEventLoop 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 +diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.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 +--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java @@ -0,0 +0,0 @@ import net.minecraft.DefaultUncaughtExceptionHandler; import net.minecraft.server.dedicated.DedicatedServer; import org.apache.logging.log4j.LogManager; @@ -96,9 +52,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import javax.imageio.ImageIO; +// Paper end - public class ServerGUI extends JComponent { + public class MinecraftServerGui extends JComponent { -@@ -0,0 +0,0 @@ public class ServerGUI extends JComponent { +@@ -0,0 +0,0 @@ public class MinecraftServerGui extends JComponent { jframe.pack(); jframe.setLocationRelativeTo((Component) null); jframe.setVisible(true); @@ -106,14 +62,47 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // Paper start - Add logo as frame image + try { -+ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(ServerGUI.class.getClassLoader().getResourceAsStream("logo.png")))); ++ jframe.setIconImage(ImageIO.read(Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png")))); + } catch (IOException ignore) { + } + // Paper end + jframe.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowevent) { - if (!servergui.f.getAndSet(true)) { + if (!servergui.isClosing.getAndSet(true)) { +diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/gui/StatsComponent.java ++++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java +@@ -0,0 +0,0 @@ public class StatsComponent extends JComponent { + + private void tick() { + long l = 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.msgs[0] = "Memory use: " + l / 1024L / 1024L + " mb (" + Runtime.getRuntime().freeMemory() * 100L / Runtime.getRuntime().maxMemory() + "% free)"; + this.msgs[1] = "Avg tick: " + DECIMAL_FORMAT.format(this.getAverage(this.server.tickTimes) * 1.0E-6D) + " ms"; ++ this.msgs[2] = "TPS from last 1m, 5m, 15m: " + String.join(", ", tpsAvg); ++ // Paper end + this.values[this.vp++ & 255] = (int)(l * 100L / Runtime.getRuntime().maxMemory()); + this.repaint(); + } +@@ -0,0 +0,0 @@ public class StatsComponent extends JComponent { + public void close() { + this.timer.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/resources/logo.png b/src/main/resources/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/patches/server/Improve-death-events.patch b/patches/server/Improve-death-events.patch new file mode 100644 index 0000000000..3e2b2c7849 --- /dev/null +++ b/patches/server/Improve-death-events.patch @@ -0,0 +1,364 @@ +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. + +TODO 1.17: this needs to be checked (actually get off your lazy ass and cancel the events) for the following entities, +maybe more (please check patch overrides for drops for more): +- players, armor stands, foxes, chested donkeys/llamas + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public int latency; + public boolean wonGame; + private int containerUpdateDelay; // Paper ++ // Paper start - cancellable death event ++ public boolean queueHealthUpdatePacket = false; ++ public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; ++ // Paper end + + // CraftBukkit start + public String displayName; +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + Component 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.containerMenu != this.inventoryMenu) { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } + } + } +- +- return super.hurt(source, amount); ++ // Paper start - cancellable death events ++ //return super.hurt(source, amount); ++ this.queueHealthUpdatePacket = true; ++ boolean damaged = super.hurt(source, amount); ++ this.queueHealthUpdatePacket = false; ++ if (this.queuedHealthUpdatePacket != null) { ++ this.connection.send(this.queuedHealthUpdatePacket); ++ this.queuedHealthUpdatePacket = null; ++ } ++ return damaged; ++ // Paper end + } + } + } +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + public Set collidableExemptions = new HashSet<>(); + public boolean bukkitPickUpLoot; + 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 LivingEntity extends Entity { + if (knockbackCancelled) this.level.broadcastEntityEvent(this, (byte) 2); // Paper - Disable explosion knockback + if (this.isDeadOrDying()) { + if (!this.checkTotemDeathProtection(source)) { +- SoundEvent soundeffect = this.getDeathSound(); +- +- if (flag1 && soundeffect != null) { +- this.playSound(soundeffect, this.getSoundVolume(), this.getVoicePitch()); +- } ++ // Paper start - moved into CraftEventFactory event caller for cancellable death event ++ this.silentDeath = !flag1; // mark entity as dying silently ++ // Paper end + + this.die(source); ++ this.silentDeath = false; // Paper - cancellable death event - reset to default + } + } else if (flag1) { + this.playHurtSound(source); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + if (!this.isRemoved() && !this.dead) { + Entity entity = source.getEntity(); + LivingEntity entityliving = this.getKillCredit(); +- ++ /* // Paper - move down to make death event cancellable - this is the runKillTrigger below + if (this.deathScore >= 0 && entityliving != null) { + entityliving.awardKillScore(this, this.deathScore, source); + } +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + if (this.isSleeping()) { + this.stopSleeping(); + } ++ */ // Paper - move down to make death event cancellable - this is the runKillTrigger below ++ + + this.dead = true; +- this.getCombatTracker().recheckStatus(); ++ // Paper - moved into if below + if (this.level instanceof ServerLevel) { + if (entity != null) { +- entity.killed((ServerLevel) this.level, this); ++ // Paper - move below into if for onKill + } + +- this.dropAllDeathLoot(source); ++ // Paper start ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(source); ++ if (deathEvent == null || !deathEvent.isCancelled()) { ++ if (this.deathScore >= 0 && entityliving != null) { ++ entityliving.awardKillScore(this, this.deathScore, source); ++ } ++ ++ if (this.isSleeping()) { ++ this.stopSleeping(); ++ } ++ ++ this.getCombatTracker().recheckStatus(); ++ if (entity != null) { ++ entity.killed((ServerLevel) this.level, this); ++ } ++ } else { ++ this.dead = false; ++ this.setHealth((float) deathEvent.getReviveHealth()); ++ } ++ // Paper end + this.createWitherRose(entityliving); + } + ++ if (this.dead) { // Paper + this.level.broadcastEntityEvent(this, (byte) 3); + this.setPose(Pose.DYING); ++ } // Paper + } + } + +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + if (!this.level.isClientSide) { + boolean flag = false; + +- if (adversary instanceof WitherBoss) { ++ if (this.dead && adversary instanceof WitherBoss) { // Paper + if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + BlockPos blockposition = this.blockPosition(); + BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + } + +- protected void dropAllDeathLoot(DamageSource source) { ++ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { // Paper + Entity entity = source.getEntity(); + int i; + +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.dropCustomDeathLoot(source, 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 dropEquipment() {} ++ 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 LivingEntity extends Entity { + return SoundEvents.GENERIC_HURT; + } + ++ @Deprecated public SoundEvent getDeathSoundPublic() { return getDeathSound(); } // Paper - public OBFHELPER + @Nullable + protected SoundEvent getDeathSound() { + return SoundEvents.GENERIC_DEATH; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java +@@ -0,0 +0,0 @@ public class Fox extends Animal { + } + + @Override +- protected void dropAllDeathLoot(DamageSource source) { +- ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND); ++ // Paper start - Cancellable death event ++ protected org.bukkit.event.entity.EntityDeathEvent dropAllDeathLoot(DamageSource source) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.MAINHAND).copy(); // Paper - modified by supercall ++ ++ org.bukkit.event.entity.EntityDeathEvent deathEvent = super.dropAllDeathLoot(source); ++ ++ // Below is code to drop ++ ++ if (deathEvent == null || deathEvent.isCancelled()) { ++ return deathEvent; ++ } ++ // Paper end + + if (!itemstack.isEmpty()) { + this.spawnAtLocation(itemstack); + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + } + +- super.dropAllDeathLoot(source); ++ return deathEvent; // Paper + } + + public static boolean isPathClear(Fox fox, LivingEntity chasedEntity) { +diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractChestedHorse.java +@@ -0,0 +0,0 @@ public abstract class AbstractChestedHorse extends AbstractHorse { + this.spawnAtLocation(Blocks.CHEST); + } + +- this.setChest(false); ++ //this.setCarryingChest(false); // Paper - moved to post death logic + } + + } + ++ // Paper start ++ protected void postDeathDropItems(org.bukkit.event.entity.EntityDeathEvent event) { ++ if (this.hasChest() && (event == null || !event.isCancelled())) { ++ this.setChest(false); ++ } ++ } ++ // Paper end ++ + @Override + public void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); +diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + + @Override + public void kill() { +- 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.remove(Entity.RemovalReason.KILLED); + } + +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() { +- this.getHandle().connection.send(new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().getSaturationLevel())); ++ // Paper start - cancellable death event ++ ClientboundSetHealthPacket packet = new ClientboundSetHealthPacket(this.getScaledHealth(), this.getHandle().getFoodData().getFoodLevel(), this.getHandle().getFoodData().getSaturationLevel()); ++ if (this.getHandle().queueHealthUpdatePacket) { ++ this.getHandle().queuedHealthUpdatePacket = packet; ++ } else { ++ this.getHandle().connection.send(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 @@ public class CraftEventFactory { + public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity 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(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { ++ event.setReviveHealth(event.getEntity().getAttribute(org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH).getValue()); ++ event.setShouldPlayDeathSound(!victim.silentDeath && !victim.isSilent()); ++ net.minecraft.sounds.SoundEvent soundEffect = victim.getDeathSoundPublic(); ++ event.setDeathSound(soundEffect != null ? org.bukkit.craftbukkit.CraftSound.getBukkit(soundEffect) : null); ++ event.setDeathSoundCategory(org.bukkit.SoundCategory.valueOf(victim.getSoundSource().name())); ++ event.setDeathSoundVolume(victim.getSoundVolume()); ++ event.setDeathSoundPitch(victim.getVoicePitch()); ++ } ++ ++ // Play death sound manually ++ private static void playDeathSound(net.minecraft.world.entity.LivingEntity victim, EntityDeathEvent event) { ++ if (event.shouldPlayDeathSound() && event.getDeathSound() != null && event.getDeathSoundCategory() != null) { ++ net.minecraft.world.entity.player.Player source = victim instanceof net.minecraft.world.entity.player.Player ? (net.minecraft.world.entity.player.Player) victim : null; ++ double x = event.getEntity().getLocation().getX(); ++ double y = event.getEntity().getLocation().getY(); ++ double z = event.getEntity().getLocation().getZ(); ++ net.minecraft.sounds.SoundEvent soundEffect = org.bukkit.craftbukkit.CraftSound.getSoundEffect(event.getDeathSound()); ++ net.minecraft.sounds.SoundSource soundCategory = net.minecraft.sounds.SoundSource.valueOf(event.getDeathSoundCategory().name()); ++ victim.level.playSound(source, x, y, z, soundEffect, soundCategory, event.getDeathSoundVolume(), event.getDeathSoundPitch()); ++ } ++ } ++ // Paper end + /** + * Server methods + */ diff --git a/patches/server/Improve-inlinig-for-some-hot-IBlockData-methods.patch b/patches/server/Improve-inlinig-for-some-hot-IBlockData-methods.patch new file mode 100644 index 0000000000..132659b76c --- /dev/null +++ b/patches/server/Improve-inlinig-for-some-hot-IBlockData-methods.patch @@ -0,0 +1,101 @@ +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/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { + } + // Paper end + ++ // Paper start ++ protected boolean isTicking; ++ protected FluidState fluid; ++ // Paper end ++ + public void initCache() { ++ this.fluid = this.getBlock().getFluidState(this.asState()); // Paper - moved from getFluid() ++ this.isTicking = this.getBlock().isRandomlyTicking(this.asState()); // Paper - moved from isTicking() + if (!this.getBlock().hasDynamicShape()) { + this.cache = new BlockBehaviour.BlockStateBase.Cache(this.asState()); + } +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { + return this.getBlock().getOcclusionShape(this.asState(), world, pos); + } + +- public boolean hasLargeCollisionShape() { ++ public final boolean hasLargeCollisionShape() { // Paper + return this.cache == null || this.cache.largeCollisionShape; + } + +- public boolean useShapeForLightOcclusion() { ++ public final boolean useShapeForLightOcclusion() { // Paper + return this.useShapeForLightOcclusion; + } + +- public int getLightEmission() { ++ public final int getLightEmission() { // Paper + return this.lightEmission; + } + +- public boolean isAir() { ++ public final boolean isAir() { // Paper + return this.isAir; + } + +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { + } + } + +- public boolean canOcclude() { ++ public final boolean canOcclude() { // Paper + return this.canOcclude; + } + +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { + return this.getBlock() == block; + } + +- public FluidState getFluidState() { +- return this.getBlock().getFluidState(this.asState()); ++ public final FluidState getFluidState() { // Paper ++ return this.fluid; // Paper - moved into init + } + +- public boolean isRandomlyTicking() { +- return this.getBlock().isRandomlyTicking(this.asState()); ++ public final boolean isRandomlyTicking() { // Paper ++ return this.isTicking; // Paper - moved into init + } + + public long getSeed(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/material/FluidState.java ++++ b/src/main/java/net/minecraft/world/level/material/FluidState.java +@@ -0,0 +0,0 @@ public final class FluidState extends StateHolder { + public static final int AMOUNT_MAX = 9; + public static final int AMOUNT_FULL = 8; + ++ // Paper start ++ protected final boolean isEmpty; ++ // Paper end + public FluidState(Fluid fluid, ImmutableMap, Comparable> propertiesMap, MapCodec codec) { + super(fluid, propertiesMap, codec); ++ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty() + } + + public Fluid getType() { +@@ -0,0 +0,0 @@ public final class FluidState extends StateHolder { + } + + public boolean isEmpty() { +- return this.getType().isEmpty(); ++ return this.isEmpty; // Paper - moved into constructor + } + + public float getHeight(BlockGetter world, BlockPos pos) { diff --git a/Spigot-Server-Patches/Improve-the-Saddle-API-for-Horses.patch b/patches/server/Improve-the-Saddle-API-for-Horses.patch similarity index 85% rename from Spigot-Server-Patches/Improve-the-Saddle-API-for-Horses.patch rename to patches/server/Improve-the-Saddle-API-for-Horses.patch index 353e1bef8e..29ff4077ca 100644 --- a/Spigot-Server-Patches/Improve-the-Saddle-API-for-Horses.patch +++ b/patches/server/Improve-the-Saddle-API-for-Horses.patch @@ -10,7 +10,7 @@ diff --git a/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; +@@ -0,0 +0,0 @@ import net.minecraft.world.entity.ai.attributes.Attributes; import org.apache.commons.lang.Validate; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.inventory.CraftInventoryAbstractHorse; @@ -22,22 +22,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public AbstractHorseInventory getInventory() { -- return new CraftInventoryAbstractHorse(getHandle().inventoryChest); -+ return new CraftSaddledInventory(getHandle().inventoryChest); +- return new CraftInventoryAbstractHorse(this.getHandle().inventory); ++ return new CraftSaddledInventory(getHandle().inventory); } } 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; +@@ -0,0 +0,0 @@ import net.minecraft.world.Container; 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) { + public CraftInventoryHorse(Container 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 @@ -47,12 +47,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package org.bukkit.craftbukkit.inventory; + -+import net.minecraft.world.IInventory; ++import net.minecraft.world.Container; +import org.bukkit.inventory.SaddledHorseInventory; + +public class CraftSaddledInventory extends CraftInventoryAbstractHorse implements SaddledHorseInventory { + -+ public CraftSaddledInventory(IInventory inventory) { ++ public CraftSaddledInventory(Container inventory) { + super(inventory); + } + diff --git a/Spigot-Server-Patches/Improved-Async-Task-Scheduler.patch b/patches/server/Improved-Async-Task-Scheduler.patch similarity index 92% rename from Spigot-Server-Patches/Improved-Async-Task-Scheduler.patch rename to patches/server/Improved-Async-Task-Scheduler.patch index b05b55f2ee..2abe157c16 100644 --- a/Spigot-Server-Patches/Improved-Async-Task-Scheduler.patch +++ b/patches/server/Improved-Async-Task-Scheduler.patch @@ -190,7 +190,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { } }; - private CraftAsyncDebugger debugTail = debugHead; + private CraftAsyncDebugger debugTail = this.debugHead; + + */ // Paper end private static final int RECENT_TICKS; @@ -223,8 +223,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } 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 +- return this.handle(new CraftAsyncTask(this.runners, plugin, runnable, this.nextId(), period), delay); ++ return this.handle(new CraftAsyncTask(this.asyncScheduler.runners, plugin, runnable, this.nextId(), period), delay); // Paper } @Override @@ -237,7 +237,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.asyncScheduler.cancelTask(taskId); + } + // Paper end - CraftTask task = runners.get(taskId); + CraftTask task = this.runners.get(taskId); if (task != null) { task.cancel0(); @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { @@ -257,13 +257,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean isCurrentlyRunning(final int taskId) { + // Paper start -+ if (!isAsyncScheduler) { ++ if (!this.isAsyncScheduler) { + if (this.asyncScheduler.isCurrentlyRunning(taskId)) { + return true; + } + } + // Paper end - final CraftTask task = runners.get(taskId); + final CraftTask task = this.runners.get(taskId); if (task == null) { return false; @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { @@ -275,7 +275,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return true; + } + // Paper end - for (CraftTask task = head.getNext(); task != null; task = task.getNext()) { + for (CraftTask task = this.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 { @@ -289,7 +289,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end final ArrayList workers = new ArrayList(); - for (final CraftTask taskObj : runners.values()) { + for (final CraftTask taskObj : this.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); @@ -314,18 +314,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end this.currentTick = currentTick; final List temp = this.temp; - parsePending(); + this.parsePending(); @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - parsePending(); + this.parsePending(); } else { - //debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper -- executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper + //this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper +- this.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 + //this.debugHead = this.debugHead.getNextHead(currentTick); // Paper } - private void addTask(final CraftTask task) { @@ -345,11 +345,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return task; + } + // Paper end - task.setNextRun(currentTick + delay); - addTask(task); + task.setNextRun(this.currentTick + delay); + this.addTask(task); return task; @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - return ids.incrementAndGet(); + return this.ids.incrementAndGet(); } - private void parsePending() { diff --git a/Spigot-Server-Patches/Improved-Watchdog-Support.patch b/patches/server/Improved-Watchdog-Support.patch similarity index 75% rename from Spigot-Server-Patches/Improved-Watchdog-Support.patch rename to patches/server/Improved-Watchdog-Support.patch index 10804f9c96..d233b0265f 100644 --- a/Spigot-Server-Patches/Improved-Watchdog-Support.patch +++ b/patches/server/Improved-Watchdog-Support.patch @@ -65,117 +65,101 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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(); + public static CrashReport forThrowable(Throwable cause, String title) { ++ if (cause instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(cause); // Paper + while (cause instanceof CompletionException && cause.getCause() != null) { + cause = cause.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 processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; - public boolean serverAutoSave = false; // Paper - public CommandDispatcher vanillaCommandDispatcher; + public Commands vanillaCommandDispatcher; - private boolean forceTicks; + public boolean forceTicks; // Paper // CraftBukkit end // Spigot start public static final int TPS = 20; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant S a(Function function) { + public static S spin(Function serverFactory) { 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); + return new TickTask(this.tickCount, 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); + this.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) +- entityplayer.doTick(); // SPIGOT-924 ++ if (server.isSameThread()) entityplayer.doTick(); // 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 +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.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 Profiler try { - r0.run(); - } catch (Exception exception) { -+ if (exception.getCause() instanceof ThreadDeath) throw exception; // Paper - IAsyncTaskHandler.LOGGER.fatal("Error executing task on {}", this.bj(), exception); + task.run(); + } catch (Exception var3) { ++ if (var3.getCause() instanceof ThreadDeath) throw var3; // Paper + LOGGER.fatal("Error executing task on {}", this.name(), var3); } -diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent tile entity and entity crashes - String msg = "TileEntity threw exception at " + tileentity.getWorld().getWorld().getName() + ":" + tileentity.getPosition().getX() + "," + tileentity.getPosition().getY() + "," + tileentity.getPosition().getZ(); - System.err.println(msg); -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { - consumer.accept(entity); + tickConsumer.accept(entity); } catch (Throwable throwable) { + if (throwable instanceof ThreadDeath) throw throwable; // Paper // Paper start - Prevent tile entity and entity crashes - String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); + String msg = "Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ(); System.err.println(msg); +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { ++ if (throwable instanceof ThreadDeath) throw throwable; // Paper + // Paper start - Prevent tile entity and entity crashes + String msg = "TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ(); + System.err.println(msg); 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 @@ -368,8 +343,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import java.util.logging.Logger; import joptsimple.OptionParser; import joptsimple.OptionSet; -+import net.minecraft.util.ExceptionSuppressor; -+import net.minecraft.world.level.lighting.LightEngineLayerEventListener; ++import net.minecraft.util.ExceptionCollector; ++import net.minecraft.world.level.lighting.LayerLightEventListener; import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper public class Main { @@ -453,9 +428,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + tryPreloadClass("com.destroystokyo.paper.event.player.PlayerConnectionCloseEvent"); + tryPreloadClass("com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent"); + // Minecraft, seen during saving -+ tryPreloadClass(LightEngineLayerEventListener.Void.class.getName()); -+ tryPreloadClass(LightEngineLayerEventListener.class.getName()); -+ tryPreloadClass(ExceptionSuppressor.class.getName()); ++ tryPreloadClass(LayerLightEventListener.DummyLightLayerEventListener.class.getName()); ++ tryPreloadClass(LayerLightEventListener.class.getName()); ++ tryPreloadClass(ExceptionCollector.class.getName()); + // Paper end + } + } @@ -496,7 +471,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 org.spigotmc.AsyncCatcher.enabled = false; // Spigot org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper + server.forceTicks = true; - server.close(); + this.server.close(); + while (!server.hasFullyShutdown) Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); @@ -535,19 +510,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private boolean restart; @@ -0,0 +0,0 @@ public class WatchdogThread extends Thread { - if ( instance == null ) + if ( WatchdogThread.instance == null ) { + if (timeoutTime <= 0) timeoutTime = 300; // Paper - instance = new WatchdogThread( timeoutTime * 1000L, restart ); - instance.start(); + WatchdogThread.instance = new WatchdogThread( timeoutTime * 1000L, restart ); + WatchdogThread.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") ) + long currentTime = WatchdogThread.monotonicMillis(); +- if ( this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable + MinecraftServer server = MinecraftServer.getServer(); -+ if (lastTick != 0 && timeoutTime > 0 && hasStarted && (!server.isRunning() || (currentTime > lastTick + earlyWarningEvery && !DISABLE_WATCHDOG) )) ++ if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.hasStarted && (!server.isRunning() || (currentTime > this.lastTick + this.earlyWarningEvery && !DISABLE_WATCHDOG) )) // Paper - add property to disable { - boolean isLongTimeout = currentTime > lastTick + timeoutTime; + boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); @@ -561,9 +536,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 ); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper +- WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); ++ WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log ); log.log( Level.SEVERE, "------------------------------" ); // // Paper start - Only print full dump on long timeouts @@ -571,7 +546,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if ( isLongTimeout ) { -- if ( restart && !MinecraftServer.getServer().hasStopped() ) +- if ( this.restart && !MinecraftServer.getServer().hasStopped() ) + if ( !server.hasStopped() ) { - RestartCommand.restart(); diff --git a/Spigot-Server-Patches/Increase-Light-Queue-Size.patch b/patches/server/Increase-Light-Queue-Size.patch similarity index 73% rename from Spigot-Server-Patches/Increase-Light-Queue-Size.patch rename to patches/server/Increase-Light-Queue-Size.patch index 837ab8176c..0a6dee0ea7 100644 --- a/Spigot-Server-Patches/Increase-Light-Queue-Size.patch +++ b/patches/server/Increase-Light-Queue-Size.patch @@ -18,8 +18,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); } + + public int lightQueueSize = 20; @@ -27,16 +27,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 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 +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit // Paper - move down + // MinecraftServer.LOGGER.debug("Autosave started"); // Paper + serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper ++ // Paper start ++ int playerSaveInterval = com.destroystokyo.paper.PaperConfig.playerAutoSaveRate; ++ if (playerSaveInterval < 0) { ++ playerSaveInterval = autosavePeriod; ++ } ++ // Paper end + this.profiler.push("save"); +- if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // Paper - moved from above +- this.playerList.saveAll(); ++ 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 + // this.saveAllChunks(true, false, false); // Paper - saved incrementally below + } // Paper start + for (ServerLevel level : this.getAllLevels()) { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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 { +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder private static final Logger LOGGER = LogManager.getLogger(); + public long lastSave = MinecraftServer.currentTick; // Paper - public PlayerConnection playerConnection; - public NetworkManager networkManager; // Paper - public final MinecraftServer server; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; + public ServerGamePacketListenerImpl connection; 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 + protected void save(ServerPlayer player) { + if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit + if (!player.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) ++ player.lastSave = MinecraftServer.currentTick; // Paper + this.playerIo.save(player); + ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit @@ -0,0 +0,0 @@ public abstract class PlayerList { } - public void savePlayers() { + public void saveAll() { +- net.minecraft.server.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + // Paper start - incremental player saving + savePlayers(null); + } + public void savePlayers(Integer interval) { - MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main ++ 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); +- this.save(this.players.get(i)); ++ ServerPlayer entityplayer = this.players.get(i); + if (interval == null || now - entityplayer.lastSave >= interval) { -+ this.savePlayerFile(entityplayer); ++ this.save(entityplayer); + if (interval != null && ++numSaved <= com.destroystokyo.paper.PaperConfig.maxPlayerAutoSavePerTick) { break; } + } + // Paper end diff --git a/patches/server/Inline-shift-direction-fields.patch b/patches/server/Inline-shift-direction-fields.patch new file mode 100644 index 0000000000..2fc3f9a14a --- /dev/null +++ b/patches/server/Inline-shift-direction-fields.patch @@ -0,0 +1,55 @@ +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/Direction.java b/src/main/java/net/minecraft/core/Direction.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/Direction.java ++++ b/src/main/java/net/minecraft/core/Direction.java +@@ -0,0 +0,0 @@ public enum Direction implements StringRepresentable { + }, (direction1, direction2) -> { + throw new IllegalArgumentException("Duplicate keys"); + }, Long2ObjectOpenHashMap::new)); ++ // Paper start ++ private final int adjX; ++ private final int adjY; ++ private final int adjZ; ++ // Paper end + + private Direction(int id, int idOpposite, int idHorizontal, String name, Direction.AxisDirection direction, Direction.Axis axis, Vec3i vector) { + this.data3d = id; +@@ -0,0 +0,0 @@ public enum Direction implements StringRepresentable { + this.axis = axis; + this.axisDirection = direction; + this.normal = vector; ++ // Paper start ++ this.adjX = vector.getX(); ++ this.adjY = vector.getY(); ++ this.adjZ = vector.getZ(); ++ // Paper end + } + + public static Direction[] orderedByNearest(Entity entity) { +@@ -0,0 +0,0 @@ public enum Direction implements StringRepresentable { + } + + public int getStepX() { +- return this.normal.getX(); ++ return this.adjX; // Paper + } + + public int getStepY() { +- return this.normal.getY(); ++ return this.adjY; // Paper + } + + public int getStepZ() { +- return this.normal.getZ(); ++ return this.adjZ; // Paper + } + + public Vector3f step() { diff --git a/Spigot-Server-Patches/Introduce-beacon-activation-deactivation-events.patch b/patches/server/Introduce-beacon-activation-deactivation-events.patch similarity index 50% rename from Spigot-Server-Patches/Introduce-beacon-activation-deactivation-events.patch rename to patches/server/Introduce-beacon-activation-deactivation-events.patch index 802e282afd..e95e748b1f 100644 --- a/Spigot-Server-Patches/Introduce-beacon-activation-deactivation-events.patch +++ b/patches/server/Introduce-beacon-activation-deactivation-events.patch @@ -4,34 +4,34 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.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); +--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { + BeaconBlockEntity.playSound(world, pos, SoundEvents.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); ++ if (i1 <= 0 && blockEntity.levels > 0) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); + 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); ++ } else if (i1 > 0 && blockEntity.levels <= 0) { ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos); + 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 + if (blockEntity.lastCheckY >= l) { + blockEntity.lastCheckY = world.getMinBuildHeight() - 1; +@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider { @Override - public void al_() { + public void setRemoved() { + // Paper start - BeaconDeactivatedEvent -+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, position); ++ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition); + new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent(); + // Paper end - this.a(SoundEffects.BLOCK_BEACON_DEACTIVATE); - super.al_(); + BeaconBlockEntity.playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE); + super.setRemoved(); } diff --git a/Spigot-Server-Patches/Inventory-close.patch b/patches/server/Inventory-close.patch similarity index 97% rename from Spigot-Server-Patches/Inventory-close.patch rename to patches/server/Inventory-close.patch index 8218375461..05cebcc0bb 100644 --- a/Spigot-Server-Patches/Inventory-close.patch +++ b/patches/server/Inventory-close.patch @@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + this.clear(i); } } + // Paper start diff --git a/Spigot-Server-Patches/Inventory-getHolder-method-without-block-snapshot.patch b/patches/server/Inventory-getHolder-method-without-block-snapshot.patch similarity index 67% rename from Spigot-Server-Patches/Inventory-getHolder-method-without-block-snapshot.patch rename to patches/server/Inventory-getHolder-method-without-block-snapshot.patch index 61853fe17c..f540c971d5 100644 --- a/Spigot-Server-Patches/Inventory-getHolder-method-without-block-snapshot.patch +++ b/patches/server/Inventory-getHolder-method-without-block-snapshot.patch @@ -8,28 +8,20 @@ diff --git a/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(); + return this.inventory.getOwner(); } + // Paper start - getHolder without snapshot + @Override + public InventoryHolder getHolder(boolean useSnapshot) { -+ return inventory instanceof TileEntity ? ((TileEntity) inventory).getOwner(useSnapshot) : getHolder(); ++ return inventory instanceof net.minecraft.world.level.block.entity.BlockEntity ? ((net.minecraft.world.level.block.entity.BlockEntity) inventory).getOwner(useSnapshot) : getHolder(); + } + // Paper end + @Override public int getMaxStackSize() { - return inventory.getMaxStackSize(); + return this.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 @@ -47,4 +39,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public Location getLocation() { - return getLeftSide().getLocation().add(getRightSide().getLocation()).multiply(0.5); + return this.getLeftSide().getLocation().add(this.getRightSide().getLocation()).multiply(0.5); diff --git a/Spigot-Server-Patches/Inventory-removeItemAnySlot.patch b/patches/server/Inventory-removeItemAnySlot.patch similarity index 89% rename from Spigot-Server-Patches/Inventory-removeItemAnySlot.patch rename to patches/server/Inventory-removeItemAnySlot.patch index c9b419fec2..1550c9a9f3 100644 --- a/Spigot-Server-Patches/Inventory-removeItemAnySlot.patch +++ b/patches/server/Inventory-removeItemAnySlot.patch @@ -21,8 +21,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (item == null) { return -1; } -- ItemStack[] inventory = getStorageContents(); -+ //ItemStack[] inventory = getStorageContents(); // Paper - let param deal +- ItemStack[] inventory = this.getStorageContents(); ++ // ItemStack[] inventory = this.getStorageContents(); // Paper - let param deal for (int i = 0; i < inventory.length; i++) { if (inventory[i] == null) continue; @@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 int toDelete = item.getAmount(); while (true) { -- int first = first(item, false); +- int first = this.first(item, false); + // Paper start - Allow searching entire contents + ItemStack[] toSearch = searchEntire ? getContents() : getStorageContents(); -+ int first = first(item, false, toSearch); ++ int first = this.first(item, false, toSearch); + // Paper end // Drat! we don't have this type in the inventory diff --git a/patches/server/InventoryCloseEvent-Reason-API.patch b/patches/server/InventoryCloseEvent-Reason-API.patch new file mode 100644 index 0000000000..10f05a18e5 --- /dev/null +++ b/patches/server/InventoryCloseEvent-Reason-API.patch @@ -0,0 +1,232 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + for (BlockEntity tileentity : chunk.getBlockEntities().values()) { + if (tileentity instanceof net.minecraft.world.Container) { + for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((net.minecraft.world.Container) tileentity).getViewers())) { +- h.closeInventory(); ++ h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper + } + } + } +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + // 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/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } + // Paper end + if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } + +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + + // SPIGOT-943 - only call if they have an inventory open + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(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 ServerPlayer extends Player { + return OptionalInt.empty(); + } else { + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + this.nextContainerCounter(); +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } + // CraftBukkit end + if (this.containerMenu != this.inventoryMenu) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + // this.nextContainerCounter(); // CraftBukkit - moved up +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + + @Override + public void closeContainer() { +- CraftEventFactory.handleInventoryCloseEvent(this); // CraftBukkit ++ // Paper start ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ @Override ++ public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit ++ // Paper end + this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); + this.doCloseContainer(); + } +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + @Override + public void handleContainerClose(ServerboundContainerClosePacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); ++ // Paper start ++ handleContainerClose(packet, InventoryCloseEvent.Reason.PLAYER); ++ } ++ public void handleContainerClose(ServerboundContainerClosePacket packetplayinclosewindow, InventoryCloseEvent.Reason reason) { ++ // Paper end ++ PacketUtils.ensureRunningOnSameThread(packetplayinclosewindow, this, this.player.getLevel()); + + if (this.player.isImmobile()) return; // CraftBukkit +- CraftEventFactory.handleInventoryCloseEvent(this.player); // CraftBukkit ++ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper + + this.player.doCloseContainer(); + } +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.containerMenu != entityplayer.inventoryMenu) { +- entityplayer.closeContainer(); ++ entityplayer.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DISCONNECT); // Paper + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.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.getScoreboardName()))); +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + this.updateIsUnderwater(); + super.tick(); + if (!this.level.isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) { +- this.closeContainer(); ++ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } + +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + + } + ++ // Paper start - unused code, but to keep signatures aligned ++ public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ closeContainer(); ++ this.containerMenu = this.inventoryMenu; ++ } ++ // Paper end ++ + public void closeContainer() { + this.containerMenu = this.inventoryMenu; + } +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 (((ServerPlayer) this.getHandle()).connection == null) return; + if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) { + // fire INVENTORY_CLOSE if one already open +- ((ServerPlayer) this.getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(this.getHandle().containerMenu.containerId)); ++ ((ServerPlayer) this.getHandle()).connection.handleContainerClose(new ServerboundContainerClosePacket(this.getHandle().containerMenu.containerId), org.bukkit.event.inventory.InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + ServerPlayer player = (ServerPlayer) this.getHandle(); + AbstractContainerMenu container; +@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + + @Override + public void closeInventory() { +- this.getHandle().closeContainer(); ++ this.getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); ++ getHandle().closeContainer(); ++ // Paper start ++ getHandle().closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.PLUGIN); + } ++ @Override ++ public void closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ getHandle().closeContainer(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 (this.getHandle().containerMenu != this.getHandle().inventoryMenu) { +- this.getHandle().closeContainer(); ++ this.getHandle().closeContainer(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 AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) { + if (player.containerMenu != player.inventoryMenu) { // fire INVENTORY_CLOSE if one already open +- player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId)); ++ player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper + } + + CraftServer server = player.level.getCraftServer(); +@@ -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(net.minecraft.world.entity.player.Player human) { +- InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView()); ++ handleInventoryCloseEvent(human, org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNKNOWN); ++ } ++ public static void handleInventoryCloseEvent(net.minecraft.world.entity.player.Player human, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { ++ // Paper end ++ InventoryCloseEvent event = new InventoryCloseEvent(human.containerMenu.getBukkitView(), reason); // Paper + human.level.getCraftServer().getPluginManager().callEvent(event); + human.containerMenu.transferTo(human.inventoryMenu, human.getBukkitEntity()); + } diff --git a/Spigot-Server-Patches/Item-Rarity-API.patch b/patches/server/Item-Rarity-API.patch similarity index 51% rename from Spigot-Server-Patches/Item-Rarity-API.patch rename to patches/server/Item-Rarity-API.patch index 4c3e4b9412..57e2716634 100644 --- a/Spigot-Server-Patches/Item-Rarity-API.patch +++ b/patches/server/Item-Rarity-API.patch @@ -4,27 +4,6 @@ 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 @@ -40,12 +19,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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()]; ++ return io.papermc.paper.inventory.ItemRarity.values()[item.rarity.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()]; ++ return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; + } // Paper end diff --git a/Spigot-Server-Patches/Item-canEntityPickup.patch b/patches/server/Item-canEntityPickup.patch similarity index 58% rename from Spigot-Server-Patches/Item-canEntityPickup.patch rename to patches/server/Item-canEntityPickup.patch index 7d40d6629a..ae2954513a 100644 --- a/Spigot-Server-Patches/Item-canEntityPickup.patch +++ b/patches/server/Item-canEntityPickup.patch @@ -4,34 +4,34 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.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(); +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + ItemEntity entityitem = (ItemEntity) iterator.next(); - if (!entityitem.dead && !entityitem.getItemStack().isEmpty() && !entityitem.p() && this.i(entityitem.getItemStack())) { + if (!entityitem.isRemoved() && !entityitem.getItem().isEmpty() && !entityitem.hasPickUpDelay() && this.wantsToPickUp(entityitem.getItem())) { + // Paper Start + if (!entityitem.canMobPickup) { + continue; + } + // Paper End - this.b(entityitem); + this.pickUpItem(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 +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { private UUID owner; - public final float b; + public final float bobOffs; private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit + public boolean canMobPickup = true; // Paper - public EntityItem(EntityTypes entitytypes, World world) { - super(entitytypes, world); + public ItemEntity(EntityType type, Level world) { + super(type, 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 @@ -41,10 +41,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + // Paper Start ++ @Override + public boolean canMobPickup() { + return item.canMobPickup; + } + ++ @Override + public void setCanMobPickup(boolean canMobPickup) { + item.canMobPickup = canMobPickup; + } @@ -52,4 +54,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public void setOwner(UUID uuid) { - item.setOwner(uuid); + this.item.setOwner(uuid); diff --git a/Spigot-Server-Patches/Item-no-age-no-player-pickup.patch b/patches/server/Item-no-age-no-player-pickup.patch similarity index 93% rename from Spigot-Server-Patches/Item-no-age-no-player-pickup.patch rename to patches/server/Item-no-age-no-player-pickup.patch index 287bfb99b2..c74fda88aa 100644 --- a/Spigot-Server-Patches/Item-no-age-no-player-pickup.patch +++ b/patches/server/Item-no-age-no-player-pickup.patch @@ -18,9 +18,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private final static int NO_PICKUP_TIME = (int) Short.MAX_VALUE; + // Paper end + - private final EntityItem item; + private final ItemEntity item; - public CraftItem(CraftServer server, Entity entity, EntityItem item) { + public CraftItem(CraftServer server, Entity entity, ItemEntity item) { @@ -0,0 +0,0 @@ public class CraftItem extends CraftEntity implements Item { public void setCanMobPickup(boolean canMobPickup) { item.canMobPickup = canMobPickup; diff --git a/Spigot-Server-Patches/ItemStack-getMaxItemUseDuration.patch b/patches/server/ItemStack-getMaxItemUseDuration.patch similarity index 56% rename from Spigot-Server-Patches/ItemStack-getMaxItemUseDuration.patch rename to patches/server/ItemStack-getMaxItemUseDuration.patch index ad228f3fa5..c2e14fceb8 100644 --- a/Spigot-Server-Patches/ItemStack-getMaxItemUseDuration.patch +++ b/patches/server/ItemStack-getMaxItemUseDuration.patch @@ -5,30 +5,18 @@ 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(); + return (this.handle == null) ? Material.AIR.getMaxStackSize() : this.handle.getItem().getMaxStackSize(); } + // Paper start + @Override + public int getMaxItemUseDuration() { -+ return handle == null ? 0 : handle.getItemUseMaxDuration(); ++ return handle == null ? 0 : handle.getUseDuration(); + } + // Paper end + diff --git a/Spigot-Server-Patches/ItemStack-repair-check-API.patch b/patches/server/ItemStack-repair-check-API.patch similarity index 75% rename from Spigot-Server-Patches/ItemStack-repair-check-API.patch rename to patches/server/ItemStack-repair-check-API.patch index b397b6702f..69f1d264c9 100644 --- a/Spigot-Server-Patches/ItemStack-repair-check-API.patch +++ b/patches/server/ItemStack-repair-check-API.patch @@ -4,24 +4,12 @@ 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()]; + return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; } + @Override @@ -29,12 +17,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!itemToBeRepaired.getType().isItem() || !repairMaterial.getType().isItem()) { + return false; + } -+ return this.getItem(itemToBeRepaired.getType()).canRepair(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); ++ return CraftMagicNumbers.getItem(itemToBeRepaired.getType()).isValidRepairItem(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); + } + @Override public int getProtocolVersion() { - return net.minecraft.SharedConstants.getGameVersion().getProtocolVersion(); + return net.minecraft.SharedConstants.getCurrentVersion().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 diff --git a/patches/server/Lag-compensate-eating.patch b/patches/server/Lag-compensate-eating.patch new file mode 100644 index 0000000000..062a9220e2 --- /dev/null +++ b/patches/server/Lag-compensate-eating.patch @@ -0,0 +1,75 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; + } + ++ // Paper start - lag compensate eating ++ protected long eatStartTime; ++ protected int totalEatTimeTicks; ++ // Paper end ++ + private void updatingUsingItem() { + if (this.isUsingItem()) { + if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + if (this.shouldTriggerItemUseEffects()) { + this.triggerItemUseEffects(stack, 5); + } +- +- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !stack.useOnRelease()) { ++ // Paper start - lag compensate eating ++ // we add 1 to the expected time to avoid lag compensating when we should not ++ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); ++ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { ++ this.useItemRemaining = 0; ++ // Paper end + this.completeUsingItem(); + } + +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + + if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag + this.useItem = itemstack; +- this.useItemRemaining = itemstack.getUseDuration(); ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = itemstack.getUseDuration(); ++ this.eatStartTime = System.nanoTime(); ++ // Paper end + if (!this.level.isClientSide) { + this.setLivingEntityFlag(1, true); + this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + } else if (!this.isUsingItem() && !this.useItem.isEmpty()) { + this.useItem = ItemStack.EMPTY; +- this.useItemRemaining = 0; ++ // Paper start - lag compensate eating ++ this.useItemRemaining = this.totalEatTimeTicks = 0; ++ this.eatStartTime = -1L; ++ // Paper end + } + } + +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + this.useItem = ItemStack.EMPTY; +- this.useItemRemaining = 0; ++ // Paper start - lag compensate eating ++ this.useItemRemaining = 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/patches/server/Lazily-track-plugin-scoreboards-by-default.patch similarity index 85% rename from Spigot-Server-Patches/Lazily-track-plugin-scoreboards-by-default.patch rename to patches/server/Lazily-track-plugin-scoreboards-by-default.patch index d50d241b01..baae44e919 100644 --- a/Spigot-Server-Patches/Lazily-track-plugin-scoreboards-by-default.patch +++ b/patches/server/Lazily-track-plugin-scoreboards-by-default.patch @@ -44,16 +44,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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) { ++ if (craftCriteria.criteria != net.minecraft.world.scores.criteria.ObjectiveCriteria.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)); + net.minecraft.world.scores.Objective objective = board.addObjective(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"); + net.minecraft.world.scores.Objective objective = this.board.addObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType)); CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria); + // Paper start @@ -72,19 +72,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public final class CraftScoreboardManager implements ScoreboardManager { public CraftScoreboardManager(MinecraftServer minecraftserver, net.minecraft.world.scores.Scoreboard scoreboardServer) { - mainScoreboard = new CraftScoreboard(scoreboardServer); + this.mainScoreboard = new CraftScoreboard(scoreboardServer); + mainScoreboard.registeredGlobally = true; // Paper - server = minecraftserver; - scoreboards.add(mainScoreboard); + this.server = minecraftserver; + this.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)); + CraftScoreboard scoreboard = new CraftScoreboard(new ServerScoreboard(this.server)); +- this.scoreboards.add(scoreboard); + // Paper start + if (com.destroystokyo.paper.PaperConfig.trackPluginScoreboards) { + scoreboard.registeredGlobally = true; - scoreboards.add(scoreboard); ++ scoreboards.add(scoreboard); + } + // Paper end return scoreboard; @@ -99,4 +100,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // CraftBukkit method public CraftScoreboard getPlayerBoard(CraftPlayer player) { - CraftScoreboard board = playerBoards.get(player); + CraftScoreboard board = this.playerBoards.get(player); diff --git a/patches/server/Limit-Client-Sign-length-more.patch b/patches/server/Limit-Client-Sign-length-more.patch new file mode 100644 index 0000000000..b5b9082341 --- /dev/null +++ b/patches/server/Limit-Client-Sign-length-more.patch @@ -0,0 +1,58 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private int aboveGroundVehicleTickCount; + private int receivedMovePacketCount; + private int knownMovePacketCount; ++ 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 ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + List lines = new java.util.ArrayList<>(); + + for (int i = 0; i < list.size(); ++i) { ++ // Paper start - cap line length - modified clients can send longer data than normal ++ net.minecraft.server.network.TextFilter.FilteredText currentLine = list.get(i); ++ if (MAX_SIGN_LINE_LENGTH > 0 && currentLine.getRaw().length() > MAX_SIGN_LINE_LENGTH) { ++ // This handles multibyte characters as 1 ++ int offset = currentLine.getRaw().codePoints().limit(MAX_SIGN_LINE_LENGTH).map(Character::charCount).sum(); ++ if (offset < currentLine.getRaw().length()) { ++ list.set(i, currentLine = net.minecraft.server.network.TextFilter.FilteredText.passThrough(currentLine.getRaw().substring(0, offset))); // this will break any filtering, but filtering is NYI as of 1.17 ++ } ++ } ++ // Paper end + if (this.player.isTextFilteringEnabled()) { +- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getFiltered()))); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(currentLine.getFiltered()))); + } else { +- lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(list.get(i).getRaw()))); ++ lines.add(net.kyori.adventure.text.Component.text(SharedConstants.filterText(currentLine.getRaw()))); + } + } + SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.cserver.getPlayer(this.player), lines); diff --git a/Spigot-Server-Patches/Limit-item-frame-cursors-on-maps.patch b/patches/server/Limit-item-frame-cursors-on-maps.patch similarity index 56% rename from Spigot-Server-Patches/Limit-item-frame-cursors-on-maps.patch rename to patches/server/Limit-item-frame-cursors-on-maps.patch index e8ca03f8f2..aac43baa02 100644 --- a/Spigot-Server-Patches/Limit-item-frame-cursors-on-maps.patch +++ b/patches/server/Limit-item-frame-cursors-on-maps.patch @@ -18,20 +18,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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()); +diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java ++++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +@@ -0,0 +0,0 @@ public class MapItemSavedData extends SavedData { + + MapFrame worldmapframe1 = new MapFrame(blockposition, entityitemframe.getDirection().get2DDataValue() * 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); ++ if (this.decorations.size() < player.level.paperConfig.mapItemFrameCursorLimit) { + this.addDecoration(MapDecoration.Type.FRAME, player.level, "frame-" + entityitemframe.getId(), (double) blockposition.getX(), (double) blockposition.getZ(), (double) (entityitemframe.getDirection().get2DDataValue() * 90), (Component) null); + this.frameMarkers.put(worldmapframe1.getId(), worldmapframe1); + } + // Paper end } - NBTTagCompound nbttagcompound = itemstack.getTag(); + CompoundTag nbttagcompound = stack.getTag(); diff --git a/patches/server/Limit-recipe-packets.patch b/patches/server/Limit-recipe-packets.patch new file mode 100644 index 0000000000..993815cc8a --- /dev/null +++ b/patches/server/Limit-recipe-packets.patch @@ -0,0 +1,59 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // CraftBukkit start - multithreaded fields + private AtomicInteger chatSpamTickCount = new AtomicInteger(); + 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 dropSpamTickCount; + private double firstGoodX; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // CraftBukkit start + for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(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.chatSpamTickCount > 0) { + --this.chatSpamTickCount; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + @Override + public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { ++ // Paper start ++ if (!org.bukkit.Bukkit.isPrimaryThread()) { ++ if (recipeSpamPackets.addAndGet(com.destroystokyo.paper.PaperConfig.autoRecipeIncrement) > com.destroystokyo.paper.PaperConfig.autoRecipeLimit) { ++ server.scheduleOnMain(() -> this.disconnect(new TranslatableComponent("disconnect.spam", new Object[0]))); // Paper ++ return; ++ } ++ } ++ // Paper end + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + this.player.resetLastActionTime(); + if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.getContainerId() && this.player.containerMenu instanceof RecipeBookMenu) { diff --git a/patches/server/LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server/LivingEntity-Hand-Raised-Item-Use-API.patch new file mode 100644 index 0000000000..e948b54b5d --- /dev/null +++ b/patches/server/LivingEntity-Hand-Raised-Item-Use-API.patch @@ -0,0 +1,42 @@ +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/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().getUseItem().asBukkitMirror(); ++ } ++ ++ @Override ++ public int getItemUseRemainingTime() { ++ return getHandle().getUseItemRemainingTicks(); ++ } ++ ++ @Override ++ public int getHandRaisedTime() { ++ return getHandle().getTicksUsingItem(); ++ } ++ ++ @Override ++ public boolean isHandRaised() { ++ return getHandle().isUsingItem(); ++ } ++ ++ @Override ++ public org.bukkit.inventory.EquipmentSlot getHandRaised() { ++ return getHandle().getUsedItemHand() == net.minecraft.world.InteractionHand.MAIN_HAND ? org.bukkit.inventory.EquipmentSlot.HAND : org.bukkit.inventory.EquipmentSlot.OFF_HAND; ++ } + // Paper end + } diff --git a/patches/server/LivingEntity-setKiller.patch b/patches/server/LivingEntity-setKiller.patch new file mode 100644 index 0000000000..38028d9151 --- /dev/null +++ b/patches/server/LivingEntity-setKiller.patch @@ -0,0 +1,35 @@ +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/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.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffect; +@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + return this.getHandle().lastHurtByPlayer == null ? null : (Player) this.getHandle().lastHurtByPlayer.getBukkitEntity(); + } + ++ // Paper start ++ @Override ++ public void setKiller(Player killer) { ++ ServerPlayer entityPlayer = killer == null ? null : ((CraftPlayer) killer).getHandle(); ++ getHandle().lastHurtByPlayer = entityPlayer; ++ getHandle().lastHurtByMob = entityPlayer; ++ getHandle().lastHurtByPlayerTime = entityPlayer == null ? 0 : 100; // 100 value taken from EntityLiving#damageEntity ++ } ++ // Paper end ++ + @Override + public boolean addPotionEffect(PotionEffect effect) { + return this.addPotionEffect(effect, false); diff --git a/patches/server/Load-Chunks-for-Login-Asynchronously.patch b/patches/server/Load-Chunks-for-Login-Asynchronously.patch new file mode 100644 index 0000000000..32e0f78469 --- /dev/null +++ b/patches/server/Load-Chunks-for-Login-Asynchronously.patch @@ -0,0 +1,258 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; + public ServerGamePacketListenerImpl connection; ++ public net.minecraft.network.Connection networkManager; // Paper + public final MinecraftServer server; + public final ServerPlayerGameMode gameMode; + private final PlayerAdvancements advancements; +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + 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/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 = TicketType.create("forced", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType LIGHT = TicketType.create("light", Comparator.comparingLong(ChunkPos::toLong)); + public static final TicketType PORTAL = TicketType.create("portal", Vec3i::compareTo, 300); ++ public static final TicketType LOGIN = create("login", Long::compareTo, 100); // Paper + public static final TicketType POST_TELEPORT = TicketType.create("post_teleport", Integer::compareTo, 5); + public static final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private static final int LATENCY_CHECK_INTERVAL = 15000; + public final Connection connection; + private final MinecraftServer server; ++ public Runnable playerJoinReady; // Paper + public ServerPlayer player; + private int tickCount; + private long keepAliveTime = Util.getMillis(); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + // 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.resetPosition(); + this.player.xo = this.player.getX(); + this.player.yo = this.player.getY(); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.lastVehicle = null; + this.clientVehicleIsFloating = false; + this.aboveGroundVehicleTickCount = 0; +- } ++ }} // Paper - end if (valid) + + this.server.getProfiler().push("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/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + // Paper end + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + if (entityplayer == null) { + this.state = ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT; +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + + this.connection.send(new ClientboundGameProfilePacket(this.gameProfile)); +- ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); ++ ServerPlayer entityplayer = this.server.getPlayerList().getActivePlayer(this.gameProfile.getId()); // Paper + + try { + ServerPlayer entityplayer1 = this.server.getPlayerList().processLogin(this.gameProfile, s); // CraftBukkit - add player reference +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.Packet; + import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; + import net.minecraft.network.protocol.game.ClientboundChatPacket; + import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; ++import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import net.minecraft.network.protocol.game.ClientboundEntityEventPacket; + import net.minecraft.network.protocol.game.ClientboundGameEventPacket; + import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; +@@ -0,0 +0,0 @@ public abstract class PlayerList { + private final IpBanList ipBans; + private final ServerOpList ops; + private final UserWhiteList 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 placeNewPlayer(Connection connection, ServerPlayer player) { ++ ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper ++ if (prev != null) { ++ disconnectPendingPlayer(prev); ++ } ++ player.networkManager = connection; // Paper + player.loginTime = System.currentTimeMillis(); // Paper + GameProfile gameprofile = player.getGameProfile(); + GameProfileCache usercache = this.server.getProfileCache(); +@@ -0,0 +0,0 @@ public abstract class PlayerList { + if (nbttagcompound != null && nbttagcompound.contains("bukkit")) { + CompoundTag bukkit = nbttagcompound.getCompound("bukkit"); + s = bukkit.contains("lastKnownName", 8) ? bukkit.getString("lastKnownName") : s; +- } ++ }String lastKnownName = s; // Paper + // CraftBukkit end + + if (nbttagcompound != null) { +@@ -0,0 +0,0 @@ public abstract class PlayerList { + player.getRecipeBook().sendInitialRecipeBook(player); + this.updateEntireScoreboard(worldserver1.getScoreboard(), player); + this.server.invalidateStatus(); ++ // Paper start - async load spawn in chunk ++ ServerLevel finalWorldserver = worldserver1; ++ int chunkX = loc.getBlockX() >> 4; ++ int chunkZ = loc.getBlockZ() >> 4; ++ final net.minecraft.world.level.ChunkPos pos = new net.minecraft.world.level.ChunkPos(chunkX, chunkZ); ++ net.minecraft.server.level.ChunkMap playerChunkMap = worldserver1.getChunkSource().chunkMap; ++ net.minecraft.server.level.DistanceManager distanceManager = playerChunkMap.distanceManager; ++ distanceManager.addTicketAtLevel(net.minecraft.server.level.TicketType.LOGIN, pos, 31, pos.toLong()); ++ worldserver1.getChunkSource().runDistanceManagerUpdates(); ++ worldserver1.getChunkSource().getChunkAtAsynchronously(chunkX, chunkZ, true, true).thenApply(chunk -> { ++ net.minecraft.server.level.ChunkHolder updatingChunk = playerChunkMap.getUpdatingChunkIfPresent(pos.toLong()); ++ if (updatingChunk != null) { ++ return updatingChunk.getEntityTickingChunkFuture(); ++ } else { ++ return java.util.concurrent.CompletableFuture.completedFuture(chunk); ++ } ++ }).thenAccept(chunk -> { ++ playerconnection.playerJoinReady = () -> { ++ postChunkLoadJoin( ++ player, finalWorldserver, connection, playerconnection, ++ nbttagcompound, connection.getRemoteAddress().toString(), lastKnownName ++ ); ++ }; ++ }); ++ } ++ ++ public ServerPlayer getActivePlayer(UUID uuid) { ++ ServerPlayer player = this.playersByUUID.get(uuid); ++ return player != null ? player : pendingPlayers.get(uuid); ++ } ++ ++ void disconnectPendingPlayer(ServerPlayer entityplayer) { ++ TranslatableComponent msg = new TranslatableComponent("multiplayer.disconnect.duplicate_login", new Object[0]); ++ entityplayer.networkManager.send(new ClientboundDisconnectPacket(msg), (future) -> { ++ entityplayer.networkManager.disconnect(msg); ++ entityplayer.networkManager = null; ++ }); ++ } ++ ++ private void postChunkLoadJoin(ServerPlayer player, ServerLevel worldserver1, Connection networkmanager, ServerGamePacketListenerImpl playerconnection, CompoundTag nbttagcompound, String s1, String s) { ++ pendingPlayers.remove(player.getUUID(), player); ++ if (!networkmanager.isConnected()) { ++ return; ++ } ++ player.didPlayerJoinEvent = true; ++ // Paper end + TranslatableComponent chatmessage; + + if (player.getGameProfile().getName().equalsIgnoreCase(s)) { +@@ -0,0 +0,0 @@ public abstract class PlayerList { + + protected void save(ServerPlayer player) { + if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit ++ if (!player.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.playerIo.save(player); + ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit + +@@ -0,0 +0,0 @@ public abstract class PlayerList { + } + + PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(this.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.getScoreboardName()))); +- this.cserver.getPluginManager().callEvent(playerQuitEvent); ++ if (entityplayer.didPlayerJoinEvent) this.cserver.getPluginManager().callEvent(playerQuitEvent); // Paper - if we disconnected before join ever fired, don't fire quit + entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + + if (server.isSameThread()) entityplayer.doTick(); // 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 { + this.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 Nameable, EntityAccess, CommandSource, n + this.yo = y; + this.zo = d4; + this.setPos(d3, y, d4); +- this.level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit ++ if (valid) this.level.getChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4); // CraftBukkit // Paper + } + + public void moveTo(Vec3 pos) { diff --git a/Spigot-Server-Patches/LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server/LootTable-API-Replenishable-Lootables-Feature.patch similarity index 67% rename from Spigot-Server-Patches/LootTable-API-Replenishable-Lootables-Feature.patch rename to patches/server/LootTable-API-Replenishable-Lootables-Feature.patch index 3c7ced6215..57db3aad8a 100644 --- a/Spigot-Server-Patches/LootTable-API-Replenishable-Lootables-Feature.patch +++ b/patches/server/LootTable-API-Replenishable-Lootables-Feature.patch @@ -49,15 +49,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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 net.minecraft.core.BlockPos; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; +import org.bukkit.Chunk; +import org.bukkit.block.Block; + +public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { + -+ TileEntityLootable getTileEntity(); ++ RandomizableContainerBlockEntity getTileEntity(); + + @Override + default LootableInventory getAPILootableInventory() { @@ -65,13 +65,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ default World getNMSWorld() { -+ return getTileEntity().getWorld(); ++ default Level getNMSWorld() { ++ return getTileEntity().getLevel(); + } + + default Block getBlock() { -+ final BlockPosition position = getTileEntity().getPosition(); -+ final Chunk bukkitChunk = getTileEntity().getWorld().getChunkAtWorldCoords(position).bukkitChunk; ++ final BlockPos position = getTileEntity().getBlockPos(); ++ final Chunk bukkitChunk = getTileEntity().getLevel().getChunkAt(position).bukkitChunk; + return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); + } + @@ -88,7 +88,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.loottable; + -+import net.minecraft.world.level.World; ++import net.minecraft.world.level.Level; +import org.bukkit.entity.Entity; + +public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { @@ -105,8 +105,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ default World getNMSWorld() { -+ return getHandle().getWorld(); ++ default Level getNMSWorld() { ++ return getHandle().getCommandSenderWorld(); + } + + @Override @@ -122,17 +122,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.loottable; + -+import net.minecraft.world.level.World; +import org.bukkit.loot.Lootable; -+ +import java.util.UUID; ++import net.minecraft.world.level.Level; + +public interface PaperLootableInventory extends LootableInventory, Lootable { + + PaperLootableInventoryData getLootableData(); + LootableInventory getAPILootableInventory(); + -+ World getNMSWorld(); ++ Level getNMSWorld(); + + default org.bukkit.World getBukkitWorld() { + return getNMSWorld().getWorld(); @@ -200,13 +199,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; @@ -240,7 +237,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return prev; + } + -+ public boolean shouldReplenish(@Nullable EntityHuman player) { ++ public boolean shouldReplenish(@Nullable net.minecraft.world.entity.player.Player player) { + LootTable table = this.lootable.getLootTable(); + + // No Loot Table associated @@ -278,12 +275,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + final Player bukkitPlayer = (Player) player.getBukkitEntity(); + LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); -+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) { ++ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUUID())) { + event.setCancelled(true); + } + return event.callEvent(); + } -+ public void processRefill(@Nullable EntityHuman player) { ++ public void processRefill(@Nullable net.minecraft.world.entity.player.Player player) { + this.lastFill = System.currentTimeMillis(); + final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; + if (paperConfig.autoReplenishLootables) { @@ -295,7 +292,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ this.setPlayerLootedState(player.getUUID(), true); + } + } else { + this.lootable.clearLootTable(); @@ -303,57 +300,57 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + -+ public void loadNbt(NBTTagCompound base) { -+ if (!base.hasKeyOfType("Paper.LootableData", 10)) { // 10 = compound ++ public void loadNbt(CompoundTag base) { ++ if (!base.contains("Paper.LootableData", 10)) { // 10 = compound + return; + } -+ NBTTagCompound comp = base.getCompound("Paper.LootableData"); -+ if (comp.hasKey("lastFill")) { ++ CompoundTag comp = base.getCompound("Paper.LootableData"); ++ if (comp.contains("lastFill")) { + this.lastFill = comp.getLong("lastFill"); + } -+ if (comp.hasKey("nextRefill")) { ++ if (comp.contains("nextRefill")) { + this.nextRefill = comp.getLong("nextRefill"); + } + -+ if (comp.hasKey("numRefills")) { ++ if (comp.contains("numRefills")) { + this.numRefills = comp.getInt("numRefills"); + } -+ if (comp.hasKeyOfType("lootedPlayers", 9)) { // 9 = list -+ NBTTagList list = comp.getList("lootedPlayers", 10); // 10 = compound ++ if (comp.contains("lootedPlayers", 9)) { // 9 = list ++ ListTag 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); ++ final CompoundTag cmp = list.getCompound(i); + lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); + } + } + } -+ public void saveNbt(NBTTagCompound base) { -+ NBTTagCompound comp = new NBTTagCompound(); ++ public void saveNbt(CompoundTag base) { ++ CompoundTag comp = new CompoundTag(); + if (this.nextRefill != -1) { -+ comp.setLong("nextRefill", this.nextRefill); ++ comp.putLong("nextRefill", this.nextRefill); + } + if (this.lastFill != -1) { -+ comp.setLong("lastFill", this.lastFill); ++ comp.putLong("lastFill", this.lastFill); + } + if (this.numRefills != 0) { -+ comp.setInt("numRefills", this.numRefills); ++ comp.putInt("numRefills", this.numRefills); + } + if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { -+ NBTTagList list = new NBTTagList(); ++ ListTag list = new ListTag(); + for (Map.Entry entry : this.lootedPlayers.entrySet()) { -+ NBTTagCompound cmp = new NBTTagCompound(); -+ cmp.setUUID("UUID", entry.getKey()); -+ cmp.setLong("Time", entry.getValue()); ++ CompoundTag cmp = new CompoundTag(); ++ cmp.putUUID("UUID", entry.getKey()); ++ cmp.putLong("Time", entry.getValue()); + list.add(cmp); + } -+ comp.set("lootedPlayers", list); ++ comp.put("lootedPlayers", list); + } + + if (!comp.isEmpty()) { -+ base.set("Paper.LootableData", comp); ++ base.put("Paper.LootableData", comp); + } + } + @@ -387,16 +384,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.world.entity.vehicle.AbstractMinecartContainer; ++import net.minecraft.world.level.Level; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; + +public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { + -+ private EntityMinecartContainer entity; ++ private AbstractMinecartContainer entity; + -+ public PaperMinecartLootableInventory(EntityMinecartContainer entity) { ++ public PaperMinecartLootableInventory(AbstractMinecartContainer entity) { + this.entity = entity; + } + @@ -442,8 +439,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public World getNMSWorld() { -+ return entity.world; ++ public Level getNMSWorld() { ++ return entity.level; + } +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java @@ -455,15 +452,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.world.level.Level; ++import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; + +public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { -+ private TileEntityLootable tileEntityLootable; ++ private RandomizableContainerBlockEntity tileEntityLootable; + -+ public PaperTileEntityLootableInventory(TileEntityLootable tileEntityLootable) { ++ public PaperTileEntityLootableInventory(RandomizableContainerBlockEntity tileEntityLootable) { + this.tileEntityLootable = tileEntityLootable; + } + @@ -499,29 +496,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public TileEntityLootable getTileEntity() { ++ public RandomizableContainerBlockEntity getTileEntity() { + return tileEntityLootable; + } + + @Override + public LootableInventory getAPILootableInventory() { -+ World world = tileEntityLootable.getWorld(); ++ Level world = tileEntityLootable.getLevel(); + if (world == null) { + return null; + } -+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getPosition())).getState(); ++ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getBlockPos())).getState(); + } + + @Override -+ public World getNMSWorld() { -+ return tileEntityLootable.getWorld(); ++ public Level getNMSWorld() { ++ return tileEntityLootable.getLevel(); + } +} 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n }; // Paper end @@ -529,11 +526,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.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 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -0,0 +0,0 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme public long lootTableSeed; // CraftBukkit start @@ -541,74 +538,74 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public List transaction = new java.util.ArrayList(); private int maxStack = MAX_STACK; -@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp +@@ -0,0 +0,0 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme @Override - protected void saveData(NBTTagCompound nbttagcompound) { - super.saveData(nbttagcompound); -+ this.lootableData.saveNbt(nbttagcompound); // Paper + protected void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); ++ this.lootableData.saveNbt(nbt); // Paper if (this.lootTable != null) { - nbttagcompound.setString("LootTable", this.lootTable.toString()); + nbt.putString("LootTable", this.lootTable.toString()); if (this.lootTableSeed != 0L) { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); + nbt.putLong("LootTableSeed", this.lootTableSeed); } - } else { + } if (true) { // Paper - Always save the items, Table may stick around - ContainerUtil.a(nbttagcompound, this.items); + ContainerHelper.saveAllItems(nbt, this.itemStacks); } -@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp +@@ -0,0 +0,0 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme @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"); + protected void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); ++ this.lootableData.loadNbt(nbt); // Paper + this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); + if (nbt.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(nbt.getString("LootTable")); + this.lootTableSeed = nbt.getLong("LootTableSeed"); - } else { + } if (true) { // Paper - always load the items, table may still remain - ContainerUtil.b(nbttagcompound, this.items); + ContainerHelper.loadAllItems(nbt, this.itemStacks); } -@@ -0,0 +0,0 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp +@@ -0,0 +0,0 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme } - 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); + public void unpackLootTable(@Nullable Player player) { +- if (this.lootTable != null && this.level.getServer() != null) { ++ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper + LootTable loottable = this.level.getServer().getLootTables().get(this.lootTable); - if (entityhuman instanceof EntityPlayer) { - CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); + if (player instanceof ServerPlayer) { + CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer) player, 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); ++ this.lootableData.processRefill(player); // Paper + LootContext.Builder loottableinfo_builder = (new LootContext.Builder((ServerLevel) this.level)).withParameter(LootContextParams.ORIGIN, this.position()).withOptionalRandomSeed(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 + if (player != null) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.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 { +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -0,0 +0,0 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc @Nullable - public MinecraftKey lootTable; + public ResourceLocation 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 RandomizableContainerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); +@@ -0,0 +0,0 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc } - protected boolean b(NBTTagCompound nbttagcompound) { -+ this.lootableData.loadNbt(nbttagcompound); // Paper - if (nbttagcompound.hasKeyOfType("LootTable", 8)) { - this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); + protected boolean tryLoadLootTable(CompoundTag nbt) { ++ this.lootableData.loadNbt(nbt); // Paper + if (nbt.contains("LootTable", 8)) { + this.lootTable = new ResourceLocation(nbt.getString("LootTable")); + try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate - this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); + this.lootTableSeed = nbt.getLong("LootTableSeed"); - return true; + return false; // Paper - always load the items, table may still remain } else { @@ -616,13 +613,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } - protected boolean c(NBTTagCompound nbttagcompound) { -+ this.lootableData.saveNbt(nbttagcompound); // Paper + protected boolean trySaveLootTable(CompoundTag nbt) { ++ this.lootableData.saveNbt(nbt); // Paper if (this.lootTable == null) { return false; } else { -@@ -0,0 +0,0 @@ public abstract class TileEntityLootable extends TileEntityContainer { - nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); +@@ -0,0 +0,0 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + nbt.putLong("LootTableSeed", this.lootTableSeed); } - return true; @@ -630,34 +627,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } - 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); + public void unpackLootTable(@Nullable Player player) { +- if (this.lootTable != null && this.level.getServer() != null) { ++ if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper + LootTable lootTable = this.level.getServer().getLootTables().get(this.lootTable); + if (player instanceof ServerPlayer) { + CriteriaTriggers.GENERATE_LOOT.trigger((ServerPlayer)player, 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; - } - ++ this.lootableData.processRefill(player); // Paper + LootContext.Builder builder = (new LootContext.Builder((ServerLevel)this.level)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(this.worldPosition)).withOptionalRandomSeed(this.lootTableSeed); + if (player != null) { + builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player); 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 @@ -668,11 +651,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 class CraftChest extends CraftLootable implements Chest { ++public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper public CraftChest(final Block block) { - super(block, TileEntityChest.class); + super(block, ChestBlockEntity.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 @@ -681,20 +664,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 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 @@ -707,20 +681,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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); - } + public CraftMinecartChest(CraftServer server, MinecartChest entity) { 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 @@ -733,4 +694,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper private final CraftInventory inventory; - public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) { + public CraftMinecartHopper(CraftServer server, MinecartHopper entity) { diff --git a/patches/server/MC-135506-Experience-should-save-as-Integers.patch b/patches/server/MC-135506-Experience-should-save-as-Integers.patch new file mode 100644 index 0000000000..45d3690918 --- /dev/null +++ b/patches/server/MC-135506-Experience-should-save-as-Integers.patch @@ -0,0 +1,28 @@ +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/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + public void addAdditionalSaveData(CompoundTag nbt) { + nbt.putShort("Health", (short) this.health); + nbt.putShort("Age", (short) this.age); +- nbt.putShort("Value", (short) this.value); ++ nbt.putInt("Value", this.value); // Paper - save as Integer + nbt.putInt("Count", this.count); + this.savePaperNBT(nbt); // Paper + } +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + public void readAdditionalSaveData(CompoundTag nbt) { + this.health = nbt.getShort("Health"); + this.age = nbt.getShort("Age"); +- this.value = nbt.getShort("Value"); ++ this.value = nbt.getInt("Value"); // Paper - load as Integer + this.count = Math.max(nbt.getInt("Count"), 1); + this.loadPaperNBT(nbt); // Paper + } diff --git a/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/patches/server/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch similarity index 58% rename from Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch rename to patches/server/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch index d1581e0c3c..fb0b1b1815 100644 --- a/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ b/patches/server/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch @@ -14,23 +14,23 @@ diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/ma 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; +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; 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; + import net.minecraft.server.PlayerAdvancements; + import net.minecraft.server.ServerScoreboard; @@ -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); + boolean isOp = this.ops.contains(gameprofile); +- boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(gameprofile); ++ boolean isWhitelisted = !this.isUsingWhitelist() || isOp || this.whitelist.contains(gameprofile); // Paper - use isUsingWhitelist() 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 = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); ++ event = new com.destroystokyo.paper.event.profile.ProfileWhitelistVerifyEvent(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.isUsingWhitelist(), isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); // Paper - use isUsingWhitelist() event.callEvent(); if (!event.isWhitelisted()) { if (loginEvent != null) { diff --git a/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch new file mode 100644 index 0000000000..ba80ddca14 --- /dev/null +++ b/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch @@ -0,0 +1,65 @@ +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/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java +@@ -0,0 +0,0 @@ public class NearestAttackableTargetGoal extends TargetG + this.randomInterval = reciprocalChance; + this.setFlags(EnumSet.of(Goal.Flag.TARGET)); + this.targetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(targetPredicate); ++ if (mob.level.paperConfig.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java ++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +@@ -0,0 +0,0 @@ public class TargetingConditions { + + if (this.range > 0.0D) { + double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; +- double e = Math.max(this.range * d, 2.0D); ++ double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0D); // Paper + double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); + if (f > e * e) { + return false; +@@ -0,0 +0,0 @@ public class TargetingConditions { + return true; + } + } ++ ++ // Paper start ++ private boolean useFollowRange = false; ++ ++ public TargetingConditions useFollowRange() { ++ this.useFollowRange = true; ++ return this; ++ } ++ ++ private double getFollowRange(LivingEntity entityliving) { ++ net.minecraft.world.entity.ai.attributes.AttributeInstance attributeinstance = entityliving.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.FOLLOW_RANGE); ++ return attributeinstance == null ? 16.0D : attributeinstance.getValue(); ++ } ++ // Paper end + } diff --git a/Spigot-Server-Patches/MC-29274-Fix-Wither-hostility-towards-players.patch b/patches/server/MC-29274-Fix-Wither-hostility-towards-players.patch similarity index 57% rename from Spigot-Server-Patches/MC-29274-Fix-Wither-hostility-towards-players.patch rename to patches/server/MC-29274-Fix-Wither-hostility-towards-players.patch index 9d393a6752..8e65af4a92 100644 --- a/Spigot-Server-Patches/MC-29274-Fix-Wither-hostility-towards-players.patch +++ b/patches/server/MC-29274-Fix-Wither-hostility-towards-players.patch @@ -19,15 +19,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.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)); +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -0,0 +0,0 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(7, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); ++ if(this.level.paperConfig.fixWitherTargetingBug) this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 0, false, false, null)); // Paper - Fix MC-29274 + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Mob.class, 0, false, false, WitherBoss.LIVING_ENTITY_SELECTOR)); } diff --git a/patches/server/MC-4-Fix-item-position-desync.patch b/patches/server/MC-4-Fix-item-position-desync.patch new file mode 100644 index 0000000000..53d77697f4 --- /dev/null +++ b/patches/server/MC-4-Fix-item-position-desync.patch @@ -0,0 +1,63 @@ +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/ClientboundMoveEntityPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMoveEntityPacket.java +@@ -0,0 +0,0 @@ public abstract class ClientboundMoveEntityPacket implements Packet +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/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -0,0 +0,0 @@ public abstract class Projectile extends Entity { + return this.cachedOwner; + } else if (this.ownerUUID != null && this.level instanceof ServerLevel) { + this.cachedOwner = ((ServerLevel) this.level).getEntity(this.ownerUUID); ++ // Paper start - check all worlds ++ if (this.cachedOwner == null) { ++ for (final ServerLevel level : this.level.getServer().getAllLevels()) { ++ if (level == this.level) continue; ++ final Entity entity = level.getEntity(this.ownerUUID); ++ if (entity != null) { ++ this.cachedOwner = entity; ++ break; ++ } ++ } ++ } ++ // Paper end + return this.cachedOwner; + } else { + return null; diff --git a/patches/server/MC-Dev-fixes.patch b/patches/server/MC-Dev-fixes.patch new file mode 100644 index 0000000000..3be2d825a1 --- /dev/null +++ b/patches/server/MC-Dev-fixes.patch @@ -0,0 +1,358 @@ +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/Util.java b/src/main/java/net/minecraft/Util.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -0,0 +0,0 @@ public class Util { + } + + public static Strategy identityStrategy() { +- return Util.IdentityStrategy.INSTANCE; ++ return (Strategy) Util.IdentityStrategy.INSTANCE; // Paper - decompile fix + } + + public static CompletableFuture> sequence(List> futures) { +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + if (this.index == l) { + return this.endOfData(); + } else { +- int i = this.index % i; +- int j = this.index / i; +- int k = j % j; +- int l = j / j; ++ int offsetX = this.index % i; // Paper - decomp fix ++ int u = this.index / i; // Paper - decomp fix ++ int offsetY = u % j; // Paper - decomp fix ++ int offsetZ = u / j; // Paper - decomp fix + ++this.index; +- return this.cursor.set(startX + i, startY + k, startZ + l); ++ return this.cursor.set(startX + offsetX, startY + offsetY, startZ + offsetZ); // Paper - decomp fix + } + } + }; +diff --git a/src/main/java/net/minecraft/nbt/ListTag.java b/src/main/java/net/minecraft/nbt/ListTag.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/nbt/ListTag.java ++++ b/src/main/java/net/minecraft/nbt/ListTag.java +@@ -0,0 +0,0 @@ package net.minecraft.nbt; + + import com.google.common.collect.Iterables; + import com.google.common.collect.Lists; ++import it.unimi.dsi.fastutil.bytes.ByteOpenHashSet; ++import it.unimi.dsi.fastutil.bytes.ByteSet; ++ + import java.io.DataInput; + import java.io.DataOutput; + import java.io.IOException; ++import java.util.Arrays; + import java.util.List; + import java.util.Objects; + +@@ -0,0 +0,0 @@ public class ListTag extends CollectionTag { + return "TAG_List"; + } + }; ++ private static final ByteSet INLINE_ELEMENT_TYPES = 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/nbt/NbtIo.java b/src/main/java/net/minecraft/nbt/NbtIo.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/nbt/NbtIo.java ++++ b/src/main/java/net/minecraft/nbt/NbtIo.java +@@ -0,0 +0,0 @@ import javax.annotation.Nullable; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; ++import io.netty.buffer.ByteBufInputStream; // Paper + + public class NbtIo { + +@@ -0,0 +0,0 @@ public class NbtIo { + + public static CompoundTag read(DataInput input, NbtAccounter tracker) throws IOException { + // Spigot start +- if ( input instanceof io.netty.buffer.ByteBufInputStream ) ++ if ( input instanceof ByteBufInputStream) // Paper + { + input = new DataInputStream(new org.spigotmc.LimitStream((InputStream) input, tracker)); + } +diff --git a/src/main/java/net/minecraft/nbt/Tag.java b/src/main/java/net/minecraft/nbt/Tag.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/nbt/Tag.java ++++ b/src/main/java/net/minecraft/nbt/Tag.java +@@ -0,0 +0,0 @@ public interface Tag { + + TagType getType(); + +- Tag copy(); ++ public Tag copy(); // Paper - decompile fix + + default String getAsString() { + return (new StringTagVisitor()).visit(this); +diff --git a/src/main/java/net/minecraft/network/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java ++++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java +@@ -0,0 +0,0 @@ import javax.annotation.Nullable; + import net.minecraft.Util; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.PacketFlow; ++import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; + import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; + import net.minecraft.network.protocol.game.ClientboundAddMobPacket; +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; + import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; ++import net.minecraft.network.protocol.game.ServerGamePacketListener; + import net.minecraft.network.protocol.game.ServerboundAcceptTeleportationPacket; + import net.minecraft.network.protocol.game.ServerboundBlockEntityTagQuery; + import net.minecraft.network.protocol.game.ServerboundChangeDifficultyPacket; +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ServerboundTeleportToEntityPacket; + import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket; + import net.minecraft.network.protocol.game.ServerboundUseItemPacket; + import net.minecraft.network.protocol.handshake.ClientIntentionPacket; ++import net.minecraft.network.protocol.handshake.ServerHandshakePacketListener; ++import net.minecraft.network.protocol.login.ClientLoginPacketListener; + import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ClientboundGameProfilePacket; + import net.minecraft.network.protocol.login.ClientboundHelloPacket; + import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; + import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; ++import net.minecraft.network.protocol.login.ServerLoginPacketListener; + import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket; + import net.minecraft.network.protocol.login.ServerboundHelloPacket; + import net.minecraft.network.protocol.login.ServerboundKeyPacket; ++import net.minecraft.network.protocol.status.ClientStatusPacketListener; + import net.minecraft.network.protocol.status.ClientboundPongResponsePacket; + import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; ++import net.minecraft.network.protocol.status.ServerStatusPacketListener; + import net.minecraft.network.protocol.status.ServerboundPingRequestPacket; + import net.minecraft.network.protocol.status.ServerboundStatusRequestPacket; + import org.apache.logging.log4j.LogManager; + + public enum ConnectionProtocol { +- HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), +- PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAddVibrationSignalPacket.class, ClientboundAddVibrationSignalPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::read).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::read).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::read).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPingPacket.class, ClientboundPingPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new).addPacket(ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new).addPacket(ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntityPacket.class, ClientboundRemoveEntityPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new).addPacket(ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new).addPacket(ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new).addPacket(ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new).addPacket(ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new).addPacket(ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new).addPacket(ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::read).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::read).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::read).addPacket(ServerboundMovePlayerPacket.StatusOnly.class, ServerboundMovePlayerPacket.StatusOnly::read).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundPongPacket.class, ServerboundPongPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), +- STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), +- LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); ++ // Paper start - fix decompile error - add correct generic packet listeners (e.g. ServerHandshakePacketListener) to PacketSet's generic type, matching the packet flow direction ++ HANDSHAKING(-1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientIntentionPacket.class, ClientIntentionPacket::new))), ++ PLAY(0, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new).addPacket(ClientboundAddExperienceOrbPacket.class, ClientboundAddExperienceOrbPacket::new).addPacket(ClientboundAddMobPacket.class, ClientboundAddMobPacket::new).addPacket(ClientboundAddPaintingPacket.class, ClientboundAddPaintingPacket::new).addPacket(ClientboundAddPlayerPacket.class, ClientboundAddPlayerPacket::new).addPacket(ClientboundAddVibrationSignalPacket.class, ClientboundAddVibrationSignalPacket::new).addPacket(ClientboundAnimatePacket.class, ClientboundAnimatePacket::new).addPacket(ClientboundAwardStatsPacket.class, ClientboundAwardStatsPacket::new).addPacket(ClientboundBlockBreakAckPacket.class, ClientboundBlockBreakAckPacket::new).addPacket(ClientboundBlockDestructionPacket.class, ClientboundBlockDestructionPacket::new).addPacket(ClientboundBlockEntityDataPacket.class, ClientboundBlockEntityDataPacket::new).addPacket(ClientboundBlockEventPacket.class, ClientboundBlockEventPacket::new).addPacket(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new).addPacket(ClientboundBossEventPacket.class, ClientboundBossEventPacket::new).addPacket(ClientboundChangeDifficultyPacket.class, ClientboundChangeDifficultyPacket::new).addPacket(ClientboundChatPacket.class, ClientboundChatPacket::new).addPacket(ClientboundClearTitlesPacket.class, ClientboundClearTitlesPacket::new).addPacket(ClientboundCommandSuggestionsPacket.class, ClientboundCommandSuggestionsPacket::new).addPacket(ClientboundCommandsPacket.class, ClientboundCommandsPacket::new).addPacket(ClientboundContainerClosePacket.class, ClientboundContainerClosePacket::new).addPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new).addPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new).addPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new).addPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new).addPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new).addPacket(ClientboundCustomSoundPacket.class, ClientboundCustomSoundPacket::new).addPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new).addPacket(ClientboundEntityEventPacket.class, ClientboundEntityEventPacket::new).addPacket(ClientboundExplodePacket.class, ClientboundExplodePacket::new).addPacket(ClientboundForgetLevelChunkPacket.class, ClientboundForgetLevelChunkPacket::new).addPacket(ClientboundGameEventPacket.class, ClientboundGameEventPacket::new).addPacket(ClientboundHorseScreenOpenPacket.class, ClientboundHorseScreenOpenPacket::new).addPacket(ClientboundInitializeBorderPacket.class, ClientboundInitializeBorderPacket::new).addPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new).addPacket(ClientboundLevelChunkPacket.class, ClientboundLevelChunkPacket::new).addPacket(ClientboundLevelEventPacket.class, ClientboundLevelEventPacket::new).addPacket(ClientboundLevelParticlesPacket.class, ClientboundLevelParticlesPacket::new).addPacket(ClientboundLightUpdatePacket.class, ClientboundLightUpdatePacket::new).addPacket(ClientboundLoginPacket.class, ClientboundLoginPacket::new).addPacket(ClientboundMapItemDataPacket.class, ClientboundMapItemDataPacket::new).addPacket(ClientboundMerchantOffersPacket.class, ClientboundMerchantOffersPacket::new).addPacket(ClientboundMoveEntityPacket.Pos.class, ClientboundMoveEntityPacket.Pos::read).addPacket(ClientboundMoveEntityPacket.PosRot.class, ClientboundMoveEntityPacket.PosRot::read).addPacket(ClientboundMoveEntityPacket.Rot.class, ClientboundMoveEntityPacket.Rot::read).addPacket(ClientboundMoveVehiclePacket.class, ClientboundMoveVehiclePacket::new).addPacket(ClientboundOpenBookPacket.class, ClientboundOpenBookPacket::new).addPacket(ClientboundOpenScreenPacket.class, ClientboundOpenScreenPacket::new).addPacket(ClientboundOpenSignEditorPacket.class, ClientboundOpenSignEditorPacket::new).addPacket(ClientboundPingPacket.class, ClientboundPingPacket::new).addPacket(ClientboundPlaceGhostRecipePacket.class, ClientboundPlaceGhostRecipePacket::new).addPacket(ClientboundPlayerAbilitiesPacket.class, ClientboundPlayerAbilitiesPacket::new).addPacket(ClientboundPlayerCombatEndPacket.class, ClientboundPlayerCombatEndPacket::new).addPacket(ClientboundPlayerCombatEnterPacket.class, ClientboundPlayerCombatEnterPacket::new).addPacket(ClientboundPlayerCombatKillPacket.class, ClientboundPlayerCombatKillPacket::new).addPacket(ClientboundPlayerInfoPacket.class, ClientboundPlayerInfoPacket::new).addPacket(ClientboundPlayerLookAtPacket.class, ClientboundPlayerLookAtPacket::new).addPacket(ClientboundPlayerPositionPacket.class, ClientboundPlayerPositionPacket::new).addPacket(ClientboundRecipePacket.class, ClientboundRecipePacket::new).addPacket(ClientboundRemoveEntityPacket.class, ClientboundRemoveEntityPacket::new).addPacket(ClientboundRemoveMobEffectPacket.class, ClientboundRemoveMobEffectPacket::new).addPacket(ClientboundResourcePackPacket.class, ClientboundResourcePackPacket::new).addPacket(ClientboundRespawnPacket.class, ClientboundRespawnPacket::new).addPacket(ClientboundRotateHeadPacket.class, ClientboundRotateHeadPacket::new).addPacket(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new).addPacket(ClientboundSelectAdvancementsTabPacket.class, ClientboundSelectAdvancementsTabPacket::new).addPacket(ClientboundSetActionBarTextPacket.class, ClientboundSetActionBarTextPacket::new).addPacket(ClientboundSetBorderCenterPacket.class, ClientboundSetBorderCenterPacket::new).addPacket(ClientboundSetBorderLerpSizePacket.class, ClientboundSetBorderLerpSizePacket::new).addPacket(ClientboundSetBorderSizePacket.class, ClientboundSetBorderSizePacket::new).addPacket(ClientboundSetBorderWarningDelayPacket.class, ClientboundSetBorderWarningDelayPacket::new).addPacket(ClientboundSetBorderWarningDistancePacket.class, ClientboundSetBorderWarningDistancePacket::new).addPacket(ClientboundSetCameraPacket.class, ClientboundSetCameraPacket::new).addPacket(ClientboundSetCarriedItemPacket.class, ClientboundSetCarriedItemPacket::new).addPacket(ClientboundSetChunkCacheCenterPacket.class, ClientboundSetChunkCacheCenterPacket::new).addPacket(ClientboundSetChunkCacheRadiusPacket.class, ClientboundSetChunkCacheRadiusPacket::new).addPacket(ClientboundSetDefaultSpawnPositionPacket.class, ClientboundSetDefaultSpawnPositionPacket::new).addPacket(ClientboundSetDisplayObjectivePacket.class, ClientboundSetDisplayObjectivePacket::new).addPacket(ClientboundSetEntityDataPacket.class, ClientboundSetEntityDataPacket::new).addPacket(ClientboundSetEntityLinkPacket.class, ClientboundSetEntityLinkPacket::new).addPacket(ClientboundSetEntityMotionPacket.class, ClientboundSetEntityMotionPacket::new).addPacket(ClientboundSetEquipmentPacket.class, ClientboundSetEquipmentPacket::new).addPacket(ClientboundSetExperiencePacket.class, ClientboundSetExperiencePacket::new).addPacket(ClientboundSetHealthPacket.class, ClientboundSetHealthPacket::new).addPacket(ClientboundSetObjectivePacket.class, ClientboundSetObjectivePacket::new).addPacket(ClientboundSetPassengersPacket.class, ClientboundSetPassengersPacket::new).addPacket(ClientboundSetPlayerTeamPacket.class, ClientboundSetPlayerTeamPacket::new).addPacket(ClientboundSetScorePacket.class, ClientboundSetScorePacket::new).addPacket(ClientboundSetSubtitleTextPacket.class, ClientboundSetSubtitleTextPacket::new).addPacket(ClientboundSetTimePacket.class, ClientboundSetTimePacket::new).addPacket(ClientboundSetTitleTextPacket.class, ClientboundSetTitleTextPacket::new).addPacket(ClientboundSetTitlesAnimationPacket.class, ClientboundSetTitlesAnimationPacket::new).addPacket(ClientboundSoundEntityPacket.class, ClientboundSoundEntityPacket::new).addPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new).addPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new).addPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new).addPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new).addPacket(ClientboundTakeItemEntityPacket.class, ClientboundTakeItemEntityPacket::new).addPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new).addPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new).addPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new).addPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new).addPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new).addPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new).addPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new).addPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new).addPacket(ServerboundChatPacket.class, ServerboundChatPacket::new).addPacket(ServerboundClientCommandPacket.class, ServerboundClientCommandPacket::new).addPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new).addPacket(ServerboundCommandSuggestionPacket.class, ServerboundCommandSuggestionPacket::new).addPacket(ServerboundContainerButtonClickPacket.class, ServerboundContainerButtonClickPacket::new).addPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new).addPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new).addPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new).addPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new).addPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new).addPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new).addPacket(ServerboundJigsawGeneratePacket.class, ServerboundJigsawGeneratePacket::new).addPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new).addPacket(ServerboundLockDifficultyPacket.class, ServerboundLockDifficultyPacket::new).addPacket(ServerboundMovePlayerPacket.Pos.class, ServerboundMovePlayerPacket.Pos::read).addPacket(ServerboundMovePlayerPacket.PosRot.class, ServerboundMovePlayerPacket.PosRot::read).addPacket(ServerboundMovePlayerPacket.Rot.class, ServerboundMovePlayerPacket.Rot::read).addPacket(ServerboundMovePlayerPacket.StatusOnly.class, ServerboundMovePlayerPacket.StatusOnly::read).addPacket(ServerboundMoveVehiclePacket.class, ServerboundMoveVehiclePacket::new).addPacket(ServerboundPaddleBoatPacket.class, ServerboundPaddleBoatPacket::new).addPacket(ServerboundPickItemPacket.class, ServerboundPickItemPacket::new).addPacket(ServerboundPlaceRecipePacket.class, ServerboundPlaceRecipePacket::new).addPacket(ServerboundPlayerAbilitiesPacket.class, ServerboundPlayerAbilitiesPacket::new).addPacket(ServerboundPlayerActionPacket.class, ServerboundPlayerActionPacket::new).addPacket(ServerboundPlayerCommandPacket.class, ServerboundPlayerCommandPacket::new).addPacket(ServerboundPlayerInputPacket.class, ServerboundPlayerInputPacket::new).addPacket(ServerboundPongPacket.class, ServerboundPongPacket::new).addPacket(ServerboundRecipeBookChangeSettingsPacket.class, ServerboundRecipeBookChangeSettingsPacket::new).addPacket(ServerboundRecipeBookSeenRecipePacket.class, ServerboundRecipeBookSeenRecipePacket::new).addPacket(ServerboundRenameItemPacket.class, ServerboundRenameItemPacket::new).addPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new).addPacket(ServerboundSeenAdvancementsPacket.class, ServerboundSeenAdvancementsPacket::new).addPacket(ServerboundSelectTradePacket.class, ServerboundSelectTradePacket::new).addPacket(ServerboundSetBeaconPacket.class, ServerboundSetBeaconPacket::new).addPacket(ServerboundSetCarriedItemPacket.class, ServerboundSetCarriedItemPacket::new).addPacket(ServerboundSetCommandBlockPacket.class, ServerboundSetCommandBlockPacket::new).addPacket(ServerboundSetCommandMinecartPacket.class, ServerboundSetCommandMinecartPacket::new).addPacket(ServerboundSetCreativeModeSlotPacket.class, ServerboundSetCreativeModeSlotPacket::new).addPacket(ServerboundSetJigsawBlockPacket.class, ServerboundSetJigsawBlockPacket::new).addPacket(ServerboundSetStructureBlockPacket.class, ServerboundSetStructureBlockPacket::new).addPacket(ServerboundSignUpdatePacket.class, ServerboundSignUpdatePacket::new).addPacket(ServerboundSwingPacket.class, ServerboundSwingPacket::new).addPacket(ServerboundTeleportToEntityPacket.class, ServerboundTeleportToEntityPacket::new).addPacket(ServerboundUseItemOnPacket.class, ServerboundUseItemOnPacket::new).addPacket(ServerboundUseItemPacket.class, ServerboundUseItemPacket::new))), ++ STATUS(1, protocol().addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new).addPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new)).addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new).addPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new))), ++ LOGIN(2, protocol().addFlow(PacketFlow.CLIENTBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ClientboundLoginDisconnectPacket.class, ClientboundLoginDisconnectPacket::new).addPacket(ClientboundHelloPacket.class, ClientboundHelloPacket::new).addPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new).addPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new).addPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new)).addFlow(PacketFlow.SERVERBOUND, (new ConnectionProtocol.PacketSet()).addPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new).addPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new).addPacket(ServerboundCustomQueryPacket.class, ServerboundCustomQueryPacket::new))); ++ // Paper end + + private static final int MIN_PROTOCOL_ID = -1; + private static final int MAX_PROTOCOL_ID = 2; +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 ReentrantBlockableEventLoopmap(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error + }, this).thenCompose((immutablelist) -> { + return ServerResources.loadResources(immutablelist, this.registryHolder, this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this); + }).thenAcceptAsync((datapackresources) -> { +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> { + return i; + } else { + int j = Integer.compare(System.identityHashCode(this.type), System.identityHashCode(ticket.type)); +- return j != 0 ? j : this.type.getComparator().compare(this.key, ticket.key); ++ return j != 0 ? j : this.type.getComparator().compare(this.key, (T)ticket.key); // Paper - decompile fix + } + } + +diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java ++++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java +@@ -0,0 +0,0 @@ public class ServerStatsCounter extends StatsCounter { + ObjectIterator objectiterator = this.stats.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 + Stat statistic = (Stat) it_unimi_dsi_fastutil_objects_object2intmap_entry.getKey(); + + ((JsonObject) map.computeIfAbsent(statistic.getType(), (statisticwrapper) -> { +diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/util/SortedArraySet.java ++++ b/src/main/java/net/minecraft/util/SortedArraySet.java +@@ -0,0 +0,0 @@ public class SortedArraySet extends AbstractSet { + } + + public static > SortedArraySet create(int initialCapacity) { +- return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); ++ return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); // Paper - decompile fix + } + + public static SortedArraySet create(Comparator comparator) { +diff --git a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java ++++ b/src/main/java/net/minecraft/util/thread/ProcessorMailbox.java +@@ -0,0 +0,0 @@ public class ProcessorMailbox implements ProfilerMeasured, ProcessorHandle + @Override + public void run() { + try { +- this.pollUntil((i) -> { ++ this.pollUntil((int i) -> { // Paper - decompile fix + return i == 0; + }); + } finally { +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -0,0 +0,0 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + } + + 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* + })); + RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); + } +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -0,0 +0,0 @@ public class TickNextTickData { + } + + public static Comparator> createTimeComparator() { +- return Comparator.comparingLong((tickNextTickData) -> { ++ return Comparator.>comparingLong((tickNextTickData) -> { // Paper - decompile fix + return tickNextTickData.triggerTick; + }).thenComparing((tickNextTickData) -> { + return tickNextTickData.priority; +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; + + public final class Biome { + public static final Logger LOGGER = LogManager.getLogger(); +- public static final Codec DIRECT_CODEC; +- public static final Codec NETWORK_CODEC; ++ // Paper start - decompile fix: move up verbatim from static block ++ public static final Codec DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { ++ return biome.climateSettings; ++ }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { ++ return biome.biomeCategory; ++ }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { ++ return biome.depth; ++ }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { ++ return biome.scale; ++ }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { ++ return biome.specialEffects; ++ }), BiomeGenerationSettings.CODEC.forGetter((biome) -> { ++ return biome.generationSettings; ++ }), MobSpawnSettings.CODEC.forGetter((biome) -> { ++ return biome.mobSettings; ++ })).apply(instance, Biome::new); ++ }); ++ public static final Codec NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { ++ return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { ++ return biome.climateSettings; ++ }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { ++ return biome.biomeCategory; ++ }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { ++ return biome.depth; ++ }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { ++ return biome.scale; ++ }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { ++ return biome.specialEffects; ++ })).apply(instance, (climateSettings, biomeCategory, float_, float2, biomeSpecialEffects) -> { ++ return new Biome(climateSettings, biomeCategory, float_, float2, biomeSpecialEffects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); ++ }); ++ }); ++ // Paper end + public static final Codec> CODEC = RegistryFileCodec.create(Registry.BIOME_REGISTRY, DIRECT_CODEC); + public static final Codec>> LIST_CODEC = RegistryFileCodec.homogeneousList(Registry.BIOME_REGISTRY, DIRECT_CODEC); + private final Map>> structuresByStep = Registry.STRUCTURE_FEATURE.stream().collect(Collectors.groupingBy((structureFeature) -> { +@@ -0,0 +0,0 @@ public final class Biome { + return resourceLocation == null ? super.toString() : resourceLocation.toString(); + } + +- static { +- DIRECT_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { +- return biome.climateSettings; +- }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { +- return biome.biomeCategory; +- }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { +- return biome.depth; +- }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { +- return biome.scale; +- }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { +- return biome.specialEffects; +- }), BiomeGenerationSettings.CODEC.forGetter((biome) -> { +- return biome.generationSettings; +- }), MobSpawnSettings.CODEC.forGetter((biome) -> { +- return biome.mobSettings; +- })).apply(instance, Biome::new); +- }); +- NETWORK_CODEC = RecordCodecBuilder.create((instance) -> { +- return instance.group(Biome.ClimateSettings.CODEC.forGetter((biome) -> { +- return biome.climateSettings; +- }), Biome.BiomeCategory.CODEC.fieldOf("category").forGetter((biome) -> { +- return biome.biomeCategory; +- }), Codec.FLOAT.fieldOf("depth").forGetter((biome) -> { +- return biome.depth; +- }), Codec.FLOAT.fieldOf("scale").forGetter((biome) -> { +- return biome.scale; +- }), BiomeSpecialEffects.CODEC.fieldOf("effects").forGetter((biome) -> { +- return biome.specialEffects; +- })).apply(instance, (climateSettings, biomeCategory, float_, float2, biomeSpecialEffects) -> { +- return new Biome(climateSettings, biomeCategory, float_, float2, biomeSpecialEffects, BiomeGenerationSettings.EMPTY, MobSpawnSettings.EMPTY); +- }); +- }); +- } +- + public static class BiomeBuilder { + @Nullable + private Biome.Precipitation precipitation; +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +@@ -0,0 +0,0 @@ import com.google.common.collect.Lists; + import com.google.common.collect.Maps; + import java.util.Arrays; + import java.util.Collection; ++import java.util.Iterator; + import java.util.Map; + import java.util.Optional; + import java.util.function.Predicate; +@@ -0,0 +0,0 @@ public class EnumProperty & StringRepresentable> extends Prope + protected EnumProperty(String name, Class type, Collection values) { + super(name, type); + this.values = ImmutableSet.copyOf(values); ++ Iterator iterator = values.iterator(); // Paper - decompile fix + + for(T enum_ : values) { + String string = enum_.getSerializedName(); diff --git a/Spigot-Server-Patches/MC-Utils.patch b/patches/server/MC-Utils.patch similarity index 62% rename from Spigot-Server-Patches/MC-Utils.patch rename to patches/server/MC-Utils.patch index 596d96722b..bf2e937ca4 100644 --- a/Spigot-Server-Patches/MC-Utils.patch +++ b/patches/server/MC-Utils.patch @@ -463,36 +463,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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; ++import net.minecraft.world.level.chunk.LevelChunk; + +// list with O(1) remove & contains +/** + * @author Spottedleaf + */ -+public final class ChunkList implements Iterable { ++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 static final LevelChunk[] EMPTY_LIST = new LevelChunk[0]; + -+ protected Chunk[] chunks = EMPTY_LIST; ++ protected LevelChunk[] chunks = EMPTY_LIST; + protected int count; + + public int size() { + return this.count; + } + -+ public boolean contains(final Chunk chunk) { ++ public boolean contains(final LevelChunk chunk) { + return this.chunkToIndex.containsKey(chunk.coordinateKey); + } + -+ public boolean remove(final Chunk chunk) { ++ public boolean remove(final LevelChunk chunk) { + final int index = this.chunkToIndex.remove(chunk.coordinateKey); + if (index == Integer.MIN_VALUE) { + return false; @@ -500,7 +500,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // move the entity at the end to this index + final int endIndex = --this.count; -+ final Chunk end = this.chunks[endIndex]; ++ final LevelChunk end = this.chunks[endIndex]; + if (index != endIndex) { + // not empty after this call + this.chunkToIndex.put(end.coordinateKey, index); // update index @@ -511,7 +511,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return true; + } + -+ public boolean add(final Chunk chunk) { ++ public boolean add(final LevelChunk chunk) { + final int count = this.count; + final int currIndex = this.chunkToIndex.putIfAbsent(chunk.coordinateKey, count); + @@ -519,7 +519,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return false; // already in this list + } + -+ Chunk[] list = this.chunks; ++ LevelChunk[] list = this.chunks; + + if (list.length == count) { + // resize required @@ -532,18 +532,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return true; + } + -+ public Chunk getChecked(final int index) { ++ public LevelChunk 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) { ++ public LevelChunk getUnchecked(final int index) { + return this.chunks[index]; + } + -+ public Chunk[] getRawData() { ++ public LevelChunk[] getRawData() { + return this.chunks; + } + @@ -554,10 +554,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public Iterator iterator() { -+ return new Iterator() { ++ public Iterator iterator() { ++ return new Iterator() { + -+ Chunk lastRet; ++ LevelChunk lastRet; + int current; + + @Override @@ -566,7 +566,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public Chunk next() { ++ public LevelChunk next() { + if (this.current >= ChunkList.this.count) { + throw new NoSuchElementException(); + } @@ -575,7 +575,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public void remove() { -+ final Chunk lastRet = this.lastRet; ++ final LevelChunk lastRet = this.lastRet; + + if (lastRet == null) { + throw new IllegalStateException(); @@ -732,17 +732,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +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; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.GlobalPalette; ++import net.minecraft.world.level.chunk.LevelChunkSection; + +/** + * @author Spottedleaf + */ +public final class IBlockDataList { + -+ static final DataPaletteGlobal GLOBAL_PALETTE = (DataPaletteGlobal) ChunkSection.GLOBAL_PALETTE; ++ static final GlobalPalette GLOBAL_PALETTE = (GlobalPalette) LevelChunkSection.GLOBAL_BLOCKSTATE_PALETTE; + + // map of location -> (index | (location << 16) | (palette id << 32)) + private final Short2LongOpenHashMap map = new Short2LongOpenHashMap(2, 0.8f); @@ -759,8 +759,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 BlockState getBlockDataFromRaw(final long raw) { ++ return GLOBAL_PALETTE.valueFor((int)(raw >>> 32)); + } + + public static int getIndexFromRaw(final long raw) { @@ -771,19 +771,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 getRawFromValues(final int index, final int location, final BlockState data) { ++ return (long)index | ((long)location << 16) | (((long)GLOBAL_PALETTE.idFor(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) { ++ public long add(final int x, final int y, final int z, final BlockState data) { + return this.add(getLocationKey(x, y, z), data); + } + -+ public long add(final int location, final IBlockData data) { ++ public long add(final int location, final BlockState data) { + final long curr = this.map.get((short)location); + + if (curr == Long.MAX_VALUE) { @@ -843,7 +843,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return getLocationFromRaw(this.getRaw(index)); + } + -+ public IBlockData getData(final int index) { ++ public BlockState getData(final int index) { + return getBlockDataFromRaw(this.getRaw(index)); + } + @@ -1107,7 +1107,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; +import net.minecraft.server.MCUtil; +import net.minecraft.server.MinecraftServer; -+import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.level.ChunkPos; +import javax.annotation.Nullable; +import java.util.Iterator; + @@ -1158,7 +1158,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Nullable -+ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkCoordIntPair chunkPos) { ++ public final PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getObjectsInRange(final ChunkPos chunkPos) { + return this.areaMap.get(MCUtil.getCoordinateKey(chunkPos)); + } + @@ -1562,7 +1562,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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; ++import net.minecraft.world.level.ChunkPos; + +/** @author Spottedleaf */ +public abstract class DistanceTrackingAreaMap extends AreaMap { @@ -1597,7 +1597,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + // ret -1 if there is nothing mapped -+ public final int getNearestObjectDistance(final ChunkCoordIntPair chunkPos) { ++ public final int getNearestObjectDistance(final ChunkPos chunkPos) { + return this.chunkToNearestDistance.get(MCUtil.getCoordinateKey(chunkPos)); + } + @@ -1740,33 +1740,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.util.misc; + -+import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.ServerPlayer; + +/** + * @author Spottedleaf + */ -+public final class PlayerAreaMap extends AreaMap { ++public final class PlayerAreaMap extends AreaMap { + + public PlayerAreaMap() { + super(); + } + -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { + super(pooledHashSets); + } + -+ public PlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback) { ++ 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) { ++ 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) { ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { + return player.cachedSingleHashSet; + } +} @@ -1778,25 +1778,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.util.misc; + -+import net.minecraft.server.level.EntityPlayer; ++import net.minecraft.server.level.ServerPlayer; + -+public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { ++public class PlayerDistanceTrackingAreaMap extends DistanceTrackingAreaMap { + + public PlayerDistanceTrackingAreaMap() { + super(); + } + -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { ++ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets) { + super(pooledHashSets); + } + -+ public PlayerDistanceTrackingAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, -+ final ChangeCallback removeCallback, final DistanceChangeCallback distanceChangeCallback) { ++ 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) { ++ protected PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getEmptySetFor(final ServerPlayer player) { + return player.cachedSingleHashSet; + } +} @@ -2257,243 +2257,76 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return (other.backingSet & this.backingSet) != 0; + } +} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.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 { +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -0,0 +0,0 @@ public class Util { } - public static long getMonotonicNanos() { -- return SystemUtils.a.getAsLong(); + public static long getNanos() { +- return timeSource.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 + public static long getEpochMillis() { +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.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 { +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { } } -+ /* // Paper start - comment out useless overrides @Override ++ // Paper start - comment out useless overrides @Override - TODO figure out why this is suddenly important to keep @Override - public void o(int i) { - super.o(i); -@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition { - super.p(i); + public BlockPos.MutableBlockPos setX(int i) { + super.setX(i); +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + super.setZ(i); + return this; } - -- @Override - public void q(int i) { - super.q(i); - } -+ */ // Paper end ++ // 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 + public BlockPos immutable() { +diff --git a/src/main/java/net/minecraft/nbt/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.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 { +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -0,0 +0,0 @@ public class CompoundTag implements Tag { return "TAG_Compound"; } }; -- private final Map map; -+ public final Map map; // Paper +- private final Map tags; ++ public final Map tags; // 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)); + protected CompoundTag(Map entries) { + this.tags = entries; +@@ -0,0 +0,0 @@ public class CompoundTag implements Tag { + this.tags.put(key, NbtUtils.createUUID(value)); } + + /** + * 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)); + public UUID getUUID(String key) { + return NbtUtils.loadUUID(this.get(key)); } -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); + throw new IllegalArgumentException("Packet too big (is " + j + ", should be less than 2097152): " + packet); + } + } catch (Throwable var9) { +- LOGGER.error(var9); ++ LOGGER.error("Packet encoding of packet ID {} threw (skippable? {})", integer, packet.isSkippable(), var9); // Paper - WHAT WAS IT? WHO DID THIS TO YOU? WHAT DID YOU SEE? + if (packet.isSkippable()) { + throw new SkipPacketException(var9); } 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 @@ -2502,16 +2335,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; +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.ChunkPos; ++import net.minecraft.world.level.ClipContext; ++import net.minecraft.world.level.Level; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.bukkit.Location; +import org.bukkit.block.BlockFace; @@ -2608,18 +2440,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return registerCleaner(obj, () -> cleaner.accept(resource)); + } + -+ public static List getSpiralOutChunks(BlockPosition blockposition, int radius) { -+ List list = com.google.common.collect.Lists.newArrayList(); ++ public static List getSpiralOutChunks(BlockPos blockposition, int radius) { ++ List list = com.google.common.collect.Lists.newArrayList(); + -+ list.add(new ChunkCoordIntPair(blockposition.getX() >> 4, blockposition.getZ() >> 4)); ++ list.add(new ChunkPos(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)); ++ list.add(new ChunkPos((blockposition.getX() + (x << 4)) >> 4, (blockposition.getZ() + (z << 4)) >> 4)); ++ list.add(new ChunkPos((blockposition.getX() - (x << 4)) >> 4, (blockposition.getZ() - (z << 4)) >> 4)); + + if (x < r) { + x++; @@ -2674,15 +2506,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return ExceptionUtils.getFullStackTrace(new Throwable(str)); + } + -+ public static long getCoordinateKey(final BlockPosition blockPos) { ++ public static long getCoordinateKey(final BlockPos 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); ++ return ((long)(MCUtil.fastFloor(entity.getZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.getX()) >> 4) & 0xFFFFFFFFL); + } + -+ public static long getCoordinateKey(final ChunkCoordIntPair pair) { ++ public static long getCoordinateKey(final ChunkPos pair) { + return ((long)pair.z << 32) | (pair.x & 0xFFFFFFFFL); + } + @@ -2710,12 +2542,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return ((long)x & 0x7FFFFFF) | (((long)z & 0x7FFFFFF) << 27) | ((long)y << 54); + } + -+ public static long getBlockKey(final BlockPosition pos) { ++ public static long getBlockKey(final BlockPos 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())); ++ return getBlockKey(getBlockCoordinate(entity.getX()), getBlockCoordinate(entity.getY()), getBlockCoordinate(entity.getZ())); + } + + // assumes the sets have the same comparator, and if this comparator is null then assume T is Comparable @@ -2752,7 +2584,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + public static boolean isMainThread() { -+ return MinecraftServer.getServer().isMainThread(); ++ return MinecraftServer.getServer().isSameThread(); + } + + public static org.bukkit.scheduler.BukkitTask scheduleTask(int ticks, Runnable runnable) { @@ -2864,7 +2696,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param e2 + * @return + */ -+ public static double distance(BlockPosition e1, BlockPosition e2) { ++ public static double distance(BlockPos e1, BlockPos e2) { + return Math.sqrt(distanceSq(e1, e2)); + } + @@ -2889,7 +2721,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @return + */ + public static double distanceSq(Entity e1, Entity e2) { -+ return distanceSq(e1.locX(),e1.locY(),e1.locZ(), e2.locX(),e2.locY(),e2.locZ()); ++ return distanceSq(e1.getX(),e1.getY(),e1.getZ(), e2.getX(),e2.getY(),e2.getZ()); + } + + /** @@ -2898,7 +2730,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param pos2 + * @return + */ -+ public static double distanceSq(BlockPosition pos1, BlockPosition pos2) { ++ public static double distanceSq(BlockPos pos1, BlockPos pos2) { + return distanceSq(pos1.getX(), pos1.getY(), pos1.getZ(), pos2.getX(), pos2.getY(), pos2.getZ()); + } + @@ -2924,7 +2756,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param z + * @return + */ -+ public static Location toLocation(World world, double x, double y, double z) { ++ public static Location toLocation(Level world, double x, double y, double z) { + return new Location(world.getWorld(), x, y, z); + } + @@ -2934,7 +2766,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param pos + * @return + */ -+ public static Location toLocation(World world, BlockPosition pos) { ++ public static Location toLocation(Level world, BlockPos pos) { + return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } + @@ -2944,18 +2776,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @return + */ + public static Location toLocation(Entity entity) { -+ return new Location(entity.getWorld().getWorld(), entity.locX(), entity.locY(), entity.locZ()); ++ return new Location(entity.getCommandSenderWorld().getWorld(), entity.getX(), entity.getY(), entity.getZ()); + } + -+ public static org.bukkit.block.Block toBukkitBlock(World world, BlockPosition pos) { ++ public static org.bukkit.block.Block toBukkitBlock(Level world, BlockPos 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 BlockPos toBlockPosition(Location loc) { ++ return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + } + -+ public static boolean isEdgeOfChunk(BlockPosition pos) { ++ public static boolean isEdgeOfChunk(BlockPos pos) { + final int modX = pos.getX() & 15; + final int modZ = pos.getZ() & 15; + return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15); @@ -2970,28 +2802,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Nonnull -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.World world) { ++ public static ServerLevel getNMSWorld(@Nonnull org.bukkit.World world) { + return ((CraftWorld) world).getHandle(); + } + -+ public static WorldServer getNMSWorld(@Nonnull org.bukkit.entity.Entity entity) { ++ public static ServerLevel 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) { ++ public static BlockFace toBukkitBlockFace(Direction enumDirection) { + switch (enumDirection) { + case DOWN: + return BlockFace.DOWN; @@ -3014,52 +2833,278 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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>> futures; + private final LevelHeightAccessor levelHeightAccessor; +- private volatile CompletableFuture> fullChunkFuture; +- private volatile CompletableFuture> tickingChunkFuture; +- private volatile CompletableFuture> entityTickingChunkFuture; ++ private volatile CompletableFuture> fullChunkFuture; private int fullChunkCreateCount; private volatile boolean isFullChunkReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> tickingChunkFuture; private volatile boolean isTickingReady; // Paper - cache chunk ticking stage ++ private volatile CompletableFuture> entityTickingChunkFuture; private volatile boolean isEntityTickingReady; // Paper - cache chunk ticking stage + private CompletableFuture chunkToSave; + @Nullable + private final DebugBuffer chunkToSaveHistory; +@@ -0,0 +0,0 @@ public class ChunkHolder { + private boolean resendLight; + private CompletableFuture pendingFullStateConfirmation; + ++ private final ChunkMap chunkMap; // Paper ++ + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -0,0 +0,0 @@ public class ChunkHolder { + this.queueLevel = this.oldTicketLevel; + this.setTicketLevel(level); + this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()]; ++ this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper + } + + // CraftBukkit start +- public LevelChunk getFullChunk() { ++ public final LevelChunk getFullChunk() { // Paper - final for inline + if (!ChunkHolder.getFullChunkStatus(this.oldTicketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER)) return null; // note: using oldTicketLevel for isLoaded checks + return this.getFullChunkUnchecked(); + } +@@ -0,0 +0,0 @@ public class ChunkHolder { + return ChunkHolder.getStatus(this.ticketLevel).isOrAfter(leastStatus) ? this.getFutureIfPresentUnchecked(leastStatus) : ChunkHolder.UNLOADED_CHUNK_FUTURE; + } + +- public CompletableFuture> getTickingChunkFuture() { ++ public final CompletableFuture> getTickingChunkFuture() { // Paper - final for inline + return this.tickingChunkFuture; + } + +- public CompletableFuture> getEntityTickingChunkFuture() { ++ public final CompletableFuture> getEntityTickingChunkFuture() { // Paper - final for inline + return this.entityTickingChunkFuture; + } + +- public CompletableFuture> getFullChunkFuture() { ++ public final CompletableFuture> getFullChunkFuture() { // Paper - final for inline + return this.fullChunkFuture; + } + + @Nullable +- public LevelChunk getTickingChunk() { ++ public final LevelChunk getTickingChunk() { // Paper - final for inline + CompletableFuture> completablefuture = this.getTickingChunkFuture(); + Either either = (Either) completablefuture.getNow(null); // CraftBukkit - decompile error + +@@ -0,0 +0,0 @@ public class ChunkHolder { + return null; + } + +- public CompletableFuture getChunkToSave() { ++ public final CompletableFuture getChunkToSave() { // Paper - final for inline + return this.chunkToSave; + } + +@@ -0,0 +0,0 @@ public class ChunkHolder { + return ChunkHolder.getFullChunkStatus(this.ticketLevel); + } + +- public ChunkPos getPos() { ++ public final ChunkPos getPos() { // Paper - final for inline + return this.pos; + } + +- public int getTicketLevel() { ++ public final int getTicketLevel() { // Paper - final for inline + return this.ticketLevel; + } + +@@ -0,0 +0,0 @@ public class ChunkHolder { + + this.wasAccessibleSinceLastSave |= flag3; + if (!flag2 && flag3) { ++ int expectCreateCount = ++this.fullChunkCreateCount; // Paper + this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.fullChunkFuture, executor, ChunkHolder.FullChunkStatus.BORDER); ++ // Paper start - cache ticking ready status ++ this.fullChunkFuture.thenAccept(either -> { ++ final Optional left = either.left(); ++ if (left.isPresent() && ChunkHolder.this.fullChunkCreateCount == expectCreateCount) { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ LevelChunk fullChunk = either.left().get(); ++ ChunkHolder.this.isFullChunkReady = true; ++ fullChunk.playerChunk = ChunkHolder.this; ++ } ++ }); + this.updateChunkToSave(this.fullChunkFuture, "full"); + } + + if (flag2 && !flag3) { + completablefuture = this.fullChunkFuture; + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; ++ ++this.fullChunkCreateCount; // Paper - cache ticking ready status ++ this.isFullChunkReady = false; // Paper - cache ticking ready status + this.updateChunkToSave(((CompletableFuture>) completablefuture).thenApply((either1) -> { // CraftBukkit - decompile error + Objects.requireNonNull(chunkStorage); + return either1.ifLeft(chunkStorage::packTicks); +@@ -0,0 +0,0 @@ public class ChunkHolder { + if (!flag4 && flag5) { + this.tickingChunkFuture = chunkStorage.prepareTickingChunk(this); + this.scheduleFullChunkPromotion(chunkStorage, this.tickingChunkFuture, executor, ChunkHolder.FullChunkStatus.TICKING); ++ // Paper start - cache ticking ready status ++ this.tickingChunkFuture.thenAccept(either -> { ++ either.ifLeft(chunk -> { ++ // note: Here is a very good place to add callbacks to logic waiting on this. ++ ChunkHolder.this.isTickingReady = true; ++ }); ++ }); ++ // Paper end + this.updateChunkToSave(this.tickingChunkFuture, "ticking"); + } + + if (flag4 && !flag5) { +- this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.tickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isTickingReady = false; // Paper - cache chunk ticking stage + this.tickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +@@ -0,0 +0,0 @@ public class ChunkHolder { + + this.entityTickingChunkFuture = chunkStorage.prepareEntityTickingChunk(this.pos); + this.scheduleFullChunkPromotion(chunkStorage, this.entityTickingChunkFuture, executor, ChunkHolder.FullChunkStatus.ENTITY_TICKING); ++ // Paper start - cache ticking ready status ++ this.entityTickingChunkFuture.thenAccept(either -> { ++ either.ifLeft(chunk -> { ++ ChunkHolder.this.isEntityTickingReady = true; ++ }); ++ }); ++ // Paper end + this.updateChunkToSave(this.entityTickingChunkFuture, "entity ticking"); + } + + if (flag6 && !flag7) { +- this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); ++ this.entityTickingChunkFuture.complete(ChunkHolder.UNLOADED_LEVEL_CHUNK); this.isEntityTickingReady = false; // Paper - cache chunk ticking stage + this.entityTickingChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; + import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; + import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; + import net.minecraft.network.protocol.game.DebugPackets; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.progress.ChunkProgressListener; + import net.minecraft.server.network.ServerPlayerConnection; + import net.minecraft.util.CsvOutput; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + }; + // CraftBukkit end + ++ // Paper start - distance maps ++ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ ++ void addPlayerToDistanceMaps(ServerPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ ++ void removePlayerFromDistanceMaps(ServerPlayer player) { ++ ++ } ++ ++ void updateMaps(ServerPlayer player) { ++ int chunkX = MCUtil.getChunkCoordinate(player.getX()); ++ int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); ++ // Note: players need to be explicitly added to distance maps before they can be updated ++ } ++ // Paper end ++ + public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { + super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync); + this.visibleChunkMap = this.updatingChunkMap.clone(); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + ++ // 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, ChunkHolder.ChunkLoadingFailure>> getChunkRangeFuture(ChunkPos centerChunk, int margin, IntFunction distanceToStatus) { + List>> list = Lists.newArrayList(); + int j = centerChunk.x; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!flag1) { + this.distanceManager.addPlayer(SectionPos.of((Entity) player), player); + } ++ this.addPlayerToDistanceMaps(player); // Paper - distance maps + } else { + SectionPos sectionposition = player.getLastSectionPos(); + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!flag2) { + this.distanceManager.removePlayer(sectionposition, player); + } ++ this.removePlayerFromDistanceMaps(player); // Paper - distance maps + } + + for (int k = i - this.viewDistance; k <= i + this.viewDistance; ++k) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + ++ this.updateMaps(player); // Paper - distance maps ++ + } + + @Override +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.level.storage.LevelStorageSource; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper - public class ChunkProviderServer extends IChunkProvider { + public class ServerChunkCache extends ChunkSource { -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - private final ChunkMapDistance chunkMapDistance; - public final ChunkGenerator chunkGenerator; - private final WorldServer world; -- private final Thread serverThread; -+ public final Thread serverThread; // Paper - private -> 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]; +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { @Nullable - private SpawnerCreature.d p; + @VisibleForDebug + private NaturalSpawner.SpawnState lastSpawnState; + // 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); ++ final Long2ObjectOpenHashMap loadedChunkMap = new Long2ObjectOpenHashMap<>(8192, 0.5f); + -+ private final Chunk[] lastLoadedChunks = new Chunk[4 * 4]; ++ private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4]; + + private static int getChunkCacheKey(int x, int z) { + return x & 3 | ((z & 3) << 2); + } + -+ public void addLoadedChunk(Chunk chunk) { ++ public void addLoadedChunk(LevelChunk chunk) { + this.loadedChunkMapSeqLock.acquireWrite(); + try { + this.loadedChunkMap.put(chunk.coordinateKey, chunk); @@ -3074,7 +3119,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.lastLoadedChunks[cacheKey] = chunk; + } + -+ public void removeLoadedChunk(Chunk chunk) { ++ public void removeLoadedChunk(LevelChunk chunk) { + this.loadedChunkMapSeqLock.acquireWrite(); + try { + this.loadedChunkMap.remove(chunk.coordinateKey); @@ -3086,21 +3131,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // we do this since we also cache null chunks + int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); + -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; + if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { + this.lastLoadedChunks[cacheKey] = null; + } + } + -+ public final Chunk getChunkAtIfLoadedMainThread(int x, int z) { ++ public final LevelChunk getChunkAtIfLoadedMainThread(int x, int z) { + int cacheKey = getChunkCacheKey(x, z); + -+ Chunk cachedChunk = this.lastLoadedChunks[cacheKey]; ++ LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; + if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { + return this.lastLoadedChunks[cacheKey]; + } + -+ long chunkKey = ChunkCoordIntPair.pair(x, z); ++ long chunkKey = ChunkPos.asLong(x, z); + + cachedChunk = this.loadedChunkMap.get(chunkKey); + // Skipping a null check to avoid extra instructions to improve inline capability @@ -3108,66 +3153,66 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return cachedChunk; + } + -+ public final Chunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { -+ return this.loadedChunkMap.get(ChunkCoordIntPair.pair(x, z)); ++ public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { ++ return this.loadedChunkMap.get(ChunkPos.asLong(x, z)); + } + -+ public final Chunk getChunkAtMainThread(int x, int z) { -+ Chunk ret = this.getChunkAtIfLoadedMainThread(x, z); ++ public final LevelChunk getChunkAtMainThread(int x, int z) { ++ LevelChunk ret = this.getChunkAtIfLoadedMainThread(x, z); + if (ret != null) { + return ret; + } -+ return (Chunk)this.getChunkAt(x, z, ChunkStatus.FULL, true); ++ return (LevelChunk)this.getChunk(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); ++ public void getEntityTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getEntityTickingChunkAsync(x, z, onLoad); + }); + return; + } -+ this.getChunkFutureAsynchronously(x, z, 31, PlayerChunk::getEntityTickingFuture, onLoad); ++ this.getChunkFutureAsynchronously(x, z, 31, ChunkHolder::getEntityTickingChunkFuture, 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); ++ public void getTickingChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getTickingChunkAsync(x, z, onLoad); + }); + return; + } -+ this.getChunkFutureAsynchronously(x, z, 32, PlayerChunk::getTickingFuture, onLoad); ++ this.getChunkFutureAsynchronously(x, z, 32, ChunkHolder::getTickingChunkFuture, 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); ++ public void getFullChunkAsync(int x, int z, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { ++ this.mainThreadProcessor.execute(() -> { ++ ServerChunkCache.this.getFullChunkAsync(x, z, onLoad); + }); + return; + } -+ this.getChunkFutureAsynchronously(x, z, 33, PlayerChunk::getFullChunkFuture, onLoad); ++ this.getChunkFutureAsynchronously(x, z, 33, ChunkHolder::getFullChunkFuture, onLoad); + } + -+ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { -+ if (Thread.currentThread() != this.serverThread) { ++ private void getChunkFutureAsynchronously(int x, int z, int ticketLevel, Function>> futureGet, java.util.function.Consumer onLoad) { ++ if (Thread.currentThread() != this.mainThread) { + throw new IllegalStateException(); + } -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); ++ ChunkPos chunkPos = new ChunkPos(x, z); + Long identifier = this.chunkFutureAwaitCounter++; -+ this.chunkMapDistance.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); -+ this.tickDistanceManager(); ++ this.distanceManager.addTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); ++ this.runDistanceManagerUpdates(); + -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(chunkPos.pair()); ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(chunkPos.toLong()); + + if (chunk == null) { -+ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.world.getWorld().getName() + "'"); ++ throw new IllegalStateException("Expected playerchunk " + chunkPos + " in world '" + this.level.getWorld().getName() + "'"); + } + -+ CompletableFuture> future = futureGet.apply(chunk); ++ CompletableFuture> future = futureGet.apply(chunk); + + future.whenCompleteAsync((either, throwable) -> { + try { @@ -3175,14 +3220,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.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()); ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Failed to complete future await for chunk " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.getWorld().getName() + "': " + either.right().get().toString()); + } + + try { + if (onLoad != null) { -+ playerChunkMap.callbackExecutor.execute(() -> { ++ chunkMap.callbackExecutor.execute(() -> { + onLoad.accept(either == null ? null : either.left().orElse(null)); // indicate failure to the callback. + }); + } @@ -3190,49 +3235,49 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); ++ net.minecraft.server.MinecraftServer.LOGGER.fatal("Load callback for future await failed " + chunkPos.toString() + " in world '" + ServerChunkCache.this.level.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); ++ ServerChunkCache.this.distanceManager.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); ++ ServerChunkCache.this.distanceManager.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, identifier); + } -+ }, this.serverThreadQueue); ++ }, this.mainThreadProcessor); + } + // 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; + public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { + this.level = world; +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.lastChunk[0] = chunk; } + // 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); ++ public LevelChunk getChunkAtIfCachedImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); + + // Note: Bypass cache since we need to check ticket level, and to make this MT-Safe + -+ PlayerChunk playerChunk = this.getChunk(k); ++ ChunkHolder playerChunk = this.getVisibleChunkIfPresent(k); + if (playerChunk == null) { + return null; + } + -+ return playerChunk.getFullChunkIfCached(); ++ return playerChunk.getFullChunkUnchecked(); + } + + @Nullable -+ public Chunk getChunkAtIfLoadedImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); ++ public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { ++ long k = ChunkPos.asLong(x, z); + -+ if (Thread.currentThread() == this.serverThread) { ++ if (Thread.currentThread() == this.mainThread) { + return this.getChunkAtIfLoadedMainThread(x, z); + } + -+ Chunk ret = null; ++ LevelChunk ret = null; + long readlock; + do { + readlock = this.loadedChunkMapSeqLock.acquireRead(); @@ -3253,570 +3298,188 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Nullable @Override - public IChunkAccess getChunkAt(int i, int j, ChunkStatus chunkstatus, boolean flag) { -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { + public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - this.p = spawnercreature_d; - this.world.getMethodProfiler().exit(); -- List list = Lists.newArrayList(this.playerChunkMap.f()); + this.lastSpawnState = spawnercreature_d; + this.level.getProfiler().pop(); +- List list = Lists.newArrayList(this.chunkMap.getChunks()); - - 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(); ++ this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_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 +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 { +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { public Integer clientViewDistance; // CraftBukkit end -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper ++ 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); + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); + this.chatVisibility = ChatVisiblity.FULL; +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.maxUpStep = 1.0F; + this.fudgeSpawnLocation(world); + 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 + this.displayName = this.getScoreboardName(); + this.bukkitPickUpLoot = true; +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/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; +--- a/src/main/java/net/minecraft/server/level/TicketType.java ++++ b/src/main/java/net/minecraft/server/level/TicketType.java +@@ -0,0 +0,0 @@ import net.minecraft.util.Unit; + import net.minecraft.world.level.ChunkPos; -+ 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 + public class TicketType { ++ public static final TicketType FUTURE_AWAIT = create("future_await", Long::compareTo); // Paper - // 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 + private final String name; + private final Comparator comparator; +diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.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; +--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java ++++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +@@ -0,0 +0,0 @@ public class WorldGenRegion implements WorldGenLevel { + return chunkX >= this.firstPos.x && chunkX <= this.lastPos.x && chunkZ >= this.firstPos.z && chunkZ <= this.lastPos.z; } + // Paper start - if loaded util + @Nullable + @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { -+ return this.getChunkAt(x, z, ChunkStatus.FULL, false); ++ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return this.getChunk(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); ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getBlockState(blockposition); + } + + @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); -+ return chunk == null ? null : chunk.getFluid(blockposition); ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluidState(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 + public BlockState getBlockState(BlockPos pos) { + return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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; +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser 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 + public ServerPlayer player; + private int tickCount; +- private long keepAliveTime; +- private boolean keepAlivePending; +- private long keepAliveChallenge; ++ private long keepAliveTime; @Deprecated private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; @Deprecated private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER ++ private boolean keepAlivePending; @Deprecated private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; @Deprecated private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER ++ private long keepAliveChallenge; @Deprecated private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; @Deprecated private long getKeepAliveID() {return this.keepAliveChallenge; }; // 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 + private AtomicInteger chatSpamTickCount = new AtomicInteger(); + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.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 implements Profiler + } } - + // Paper start + public void scheduleOnMain(Runnable r0) { + // postToMainThread does not work the same as older versions of mc + // This method is actually used to create a TickTask, which can then be posted onto main -+ this.addTask(this.postToMainThread(r0)); ++ this.tell(this.wrapRunnable(r0)); + } + // Paper end -+ -+ public final void addTask(R r0) { a(r0); }; // Paper - OBFHELPER - public void a(R r0) { - this.d.add(r0); - LockSupport.unpark(this.getThread()); -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 -+ - 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 + @Override + public void tell(R runnable) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { public boolean collides = true; public Set collidableExemptions = new HashSet<>(); - public boolean canPickUpLoot; + public boolean bukkitPickUpLoot; + 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 +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.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; +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + return this.target; } -- @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 ++ public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper + public void setTarget(@Nullable LivingEntity target) { + // CraftBukkit start - fire event + this.setGoalTarget(target, EntityTargetEvent.TargetReason.UNKNOWN, true); +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.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; +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityUnleashEvent; - public abstract class EntityMonster extends EntityCreature implements IMonster { + public abstract class PathfinderMob extends Mob { ++ public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ + protected PathfinderMob(EntityType type, Level world) { + super(type, world); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Monster.java b/src/main/java/net/minecraft/world/entity/monster/Monster.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Monster.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Monster.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.ServerLevelAccessor; + + public abstract class Monster extends PathfinderMob implements Enemy { + 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; + protected Monster(EntityType type, Level world) { + super(type, world); + this.xpReward = 5; 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(); + return this.tag != null ? this.tag.getList("Enchantments", 10) : new ListTag(); } + // Paper start - (this is just a good no conflict location) @@ -3824,30 +3487,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return CraftItemStack.asCraftMirror(this); + } + public org.bukkit.inventory.ItemStack asBukkitCopy() { -+ return CraftItemStack.asCraftMirror(this.cloneItemStack()); ++ return CraftItemStack.asCraftMirror(this.copy()); + } + 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) { ++ if (bukkitStack == null || bukkitStack.handle != 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); - } + public void setTag(@Nullable CompoundTag tag) { + this.tag = tag; + if (this.getItem().canBeDepleted()) { @@ -0,0 +0,0 @@ public final class ItemStack { // CraftBukkit start @Deprecated @@ -3856,235 +3511,159 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.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")); +--- a/src/main/java/net/minecraft/world/level/BlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java +@@ -0,0 +0,0 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.util.Mth; ++import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.material.FluidState; ++import net.minecraft.world.level.material.Material; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.BlockHitResult; + import net.minecraft.world.phys.Vec3; +@@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor { } -+ 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); + BlockState getBlockState(BlockPos pos); ++ // Paper start - if loaded util ++ BlockState getTypeIfLoaded(BlockPos blockposition); ++ default Material getMaterialIfLoaded(BlockPos blockposition) { ++ BlockState type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getMaterial(); ++ } ++ ++ default Block getBlockIfLoaded(BlockPos blockposition) { ++ BlockState type = this.getTypeIfLoaded(blockposition); ++ return type == null ? null : type.getBlock(); ++ } ++ FluidState getFluidIfLoaded(BlockPos blockposition); ++ // Paper end -diff --git a/src/main/java/net/minecraft/world/level/BlockAccessAir.java b/src/main/java/net/minecraft/world/level/BlockAccessAir.java + FluidState getFluidState(BlockPos pos); + +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.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 { +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -0,0 +0,0 @@ public class ChunkPos { + private static final int REGION_MASK = 31; + public final int x; + public final int z; ++ public final long longKey; // Paper + private static final int HASH_A = 1664525; + private static final int HASH_C = 1013904223; + private static final int HASH_Z_XOR = -559038737; +@@ -0,0 +0,0 @@ public class ChunkPos { + public ChunkPos(int x, int z) { + this.x = x; + this.z = z; ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public ChunkPos(BlockPos pos) { + this.x = SectionPos.blockToSectionCoord(pos.getX()); + this.z = SectionPos.blockToSectionCoord(pos.getZ()); ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public ChunkPos(long pos) { + this.x = (int)pos; + this.z = (int)(pos >> 32); ++ this.longKey = asLong(this.x, this.z); // Paper + } + + public long toLong() { +- return asLong(this.x, this.z); ++ return longKey; // Paper + } + +- public static long asLong(int chunkX, int chunkZ) { ++ public static long asLong(int chunkX, int chunkZ) { + return (long)chunkX & 4294967295L | ((long)chunkZ & 4294967295L) << 32; + } + +diff --git a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/EmptyBlockGetter.java +@@ -0,0 +0,0 @@ public enum EmptyBlockGetter implements BlockGetter { return null; } + // Paper start - If loaded util + @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); + } + + @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(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 + public BlockState getBlockState(BlockPos pos) { + return Blocks.AIR.defaultBlockState(); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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; +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; + import org.bukkit.craftbukkit.SpigotTimings; // Spigot import org.bukkit.craftbukkit.block.CapturedBlockState; +import org.bukkit.craftbukkit.block.CraftBlockState; import org.bukkit.craftbukkit.block.data.CraftBlockData; + import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.event.block.BlockPhysicsEvent; - // CraftBukkit end -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { - return i < 0 || i >= 256; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + Level.this.getCraftServer().getHandle().sendAll(new ClientboundSetBorderWarningDistancePacket(border), border.world); + } + +- public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) {} ++ public void onBorderSetDamagePerBlock(WorldBorder border, double damagePerBlock) { ++ } + +- public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} ++ public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) { ++ } + }); + // CraftBukkit end + this.timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return y < -20000000 || y >= 20000000; } -- public Chunk getChunkAtWorldCoords(BlockPosition blockposition) { -+ public final Chunk getChunkAtWorldCoords(BlockPosition blockposition) { // Paper - help inline - return this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4); +- public LevelChunk getChunkAt(BlockPos pos) { ++ public final LevelChunk getChunkAt(BlockPos pos) { // Paper - help inline + return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); } @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 +- public LevelChunk getChunk(int chunkX, int chunkZ) { +- return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL); ++ public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline ++ return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump + } + ++ // Paper start - if loaded + @Nullable + @Override +- public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { ++ public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z); + } + -+ // 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) { ++ public final BlockState getTypeIfLoaded(BlockPos blockposition) { + // CraftBukkit start - tree generation + if (captureTreeGeneration) { + CraftBlockState previous = capturedBlockStates.get(blockposition); @@ -4093,120 +3672,137 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + // CraftBukkit end -+ if (!isValidLocation(blockposition)) { -+ return Blocks.AIR.getBlockData(); ++ if (!isInWorldBounds(blockposition)) { ++ return Blocks.AIR.defaultBlockState(); + } -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); + -+ return chunk == null ? null : chunk.getType(blockposition); ++ return chunk == null ? null : chunk.getBlockState(blockposition); + } + + @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ IChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); + -+ return chunk == null ? null : chunk.getFluid(blockposition); ++ return chunk == null ? null : chunk.getFluidState(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); ++ public final ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { // Paper - final for inline + ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create); - if (ichunkaccess == null && flag) { -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + if (ichunkaccess == null && create) { +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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); +- public boolean setBlock(BlockPos pos, BlockState state, int flags) { ++ public final boolean setBlock(BlockPos pos, BlockState state, int flags) { // Paper - final for inline + return this.setBlock(pos, state, flags, 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(); +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (this.isOutsideBuildHeight(pos)) { + return Blocks.VOID_AIR.defaultBlockState(); } 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 +- LevelChunk chunk = this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())); ++ ChunkAccess chunk = this.getChunk(pos.getX() >> 4, pos.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); + return chunk.getBlockState(pos); } -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 +diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.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)); - } +--- a/src/main/java/net/minecraft/world/level/LevelReader.java ++++ b/src/main/java/net/minecraft/world/level/LevelReader.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.Heightmap; + import net.minecraft.world.phys.AABB; -+ public final IBlockData getBlockData() { return p(); } // Paper - OBFHELPER - protected abstract IBlockData p(); + public interface LevelReader extends BlockAndTintGetter, CollisionGetter, BiomeManager.NoiseBiomeSource { ++ @Nullable ChunkAccess getChunkIfLoadedImmediately(int x, int z); // Paper - ifLoaded api (we need this since current impl blocks if the chunk is loading) + @Nullable + ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create); - 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 +diff --git a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java b/src/main/java/net/minecraft/world/level/PathNavigationRegion.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()); +--- a/src/main/java/net/minecraft/world/level/PathNavigationRegion.java ++++ b/src/main/java/net/minecraft/world/level/PathNavigationRegion.java +@@ -0,0 +0,0 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.util.profiling.ProfilerFiller; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.entity.BlockEntity; +@@ -0,0 +0,0 @@ public class PathNavigationRegion implements BlockGetter, CollisionGetter { + return this.getChunk(chunkX, chunkZ); } -+ 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 ++ // Paper start - if loaded util ++ private ChunkAccess getChunkIfLoaded(int x, int z) { ++ int k = x - this.centerX; ++ int l = z - this.centerZ; ++ ++ if (k >= 0 && k < this.chunks.length && l >= 0 && l < this.chunks[k].length) { // Paper - if this changes, update getChunkIfLoaded below ++ return this.chunks[k][l]; ++ } ++ return null; ++ } ++ @Override ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getFluidState(blockposition); ++ } ++ ++ @Override ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ ChunkAccess chunk = getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); ++ return chunk == null ? null : chunk.getBlockState(blockposition); ++ } ++ // Paper end ++ + @Nullable + @Override + public BlockEntity getBlockEntity(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.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(); +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ import net.minecraft.core.SectionPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.world.entity.Entity; +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + private Supplier fullStatus; @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; + private Consumer postLoad; +- private final ChunkPos chunkPos; ++ private final ChunkPos chunkPos; public final long coordinateKey; public final int locX; public final int locZ; // Paper - cache coordinate key + private volatile boolean isLightCorrect; + private final Int2ObjectMap gameEventDispatcherSections; - 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); +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + this.structureStarts = Maps.newHashMap(); + this.structuresRefences = Maps.newHashMap(); + this.level = (ServerLevel) world; // CraftBukkit - type +- this.chunkPos = pos; ++ this.locX = pos.x; this.locZ = pos.z; // Paper - reduce need for field look ups ++ this.chunkPos = pos; this.coordinateKey = ChunkPos.asLong(locX, locZ); // Paper - cache long key + this.upgradeData = upgradeData; + this.gameEventDispatcherSections = new Int2ObjectOpenHashMap(); + Heightmap.Types[] aheightmap_type = Heightmap.Types.values(); +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(LevelChunk.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; ++ public ChunkHolder playerChunk; + + static final int NEIGHBOUR_CACHE_RADIUS = 3; + public static int getNeighbourCacheRadius() { @@ -4215,7 +3811,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + boolean loadedTicketLevel; + private long neighbourChunksLoadedBitset; -+ private final Chunk[] loadedNeighbourChunks = new Chunk[(NEIGHBOUR_CACHE_RADIUS * 2 + 1) * (NEIGHBOUR_CACHE_RADIUS * 2 + 1)]; ++ private final LevelChunk[] loadedNeighbourChunks = new LevelChunk[(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) @@ -4223,7 +3819,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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) { ++ public final LevelChunk getRelativeNeighbourIfLoaded(final int relativeX, final int relativeZ) { + return this.loadedNeighbourChunks[getNeighbourIndex(relativeX, relativeZ)]; + } + @@ -4231,9 +3827,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return (this.neighbourChunksLoadedBitset & (1L << getNeighbourIndex(relativeX, relativeZ))) != 0; + } + -+ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final Chunk chunk) { ++ public final void setNeighbourLoaded(final int relativeX, final int relativeZ, final LevelChunk chunk) { + if (chunk == null) { -+ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.loc); ++ throw new IllegalArgumentException("Chunk must be non-null, neighbour: (" + relativeX + "," + relativeZ + "), chunk: " + this.chunkPos); + } + final long before = this.neighbourChunksLoadedBitset; + final int index = getNeighbourIndex(relativeX, relativeZ); @@ -4265,7 +3861,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return neighbourChunksLoadedBitset != 0; + } + public final boolean areNeighboursLoaded(final int radius) { -+ return Chunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); ++ return LevelChunk.areNeighboursLoaded(this.neighbourChunksLoadedBitset, radius); + } + + public static boolean areNeighboursLoaded(final long bitset, final int radius) { @@ -4308,63 +3904,47 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // 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 { + public LevelChunk(ServerLevel worldserver, ProtoChunk protoChunk, @Nullable Consumer consumer) { + this(worldserver, protoChunk.getPos(), protoChunk.getBiomes(), protoChunk.getUpgradeData(), protoChunk.getBlockTicks(), protoChunk.getLiquidTicks(), protoChunk.getInhabitedTime(), protoChunk.getSections(), consumer); + Iterator iterator = protoChunk.getBlockEntities().values().iterator(); +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { } } + // Paper start - If loaded util + @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); + } + + @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(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); + public FluidState getFluidState(BlockPos pos) { + return this.getFluidState(pos.getX(), pos.getY(), pos.getZ()); +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + return this.getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK); } -@@ -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 ++ @Deprecated @Nullable public final BlockEntity getTileEntityImmediately(BlockPos pos) { return this.getBlockEntity(pos, EntityCreationType.IMMEDIATE); } // Paper - OBFHELPER @Nullable - public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) { + public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { // CraftBukkit start -@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess { +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { // 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(); ++ int chunkX = this.chunkPos.x; ++ int chunkZ = this.chunkPos.z; ++ ServerChunkCache chunkProvider = this.level.getChunkSource(); + 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); ++ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); + if (neighbour != null) { + neighbour.setNeighbourLoaded(-dx, -dz, this); + // should be in cached already @@ -4375,23 +3955,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + org.bukkit.Server server = this.level.getCraftServer(); ++ this.level.getChunkSource().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 { +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { 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 ++ this.level.getChunkSource().removeLoadedChunk(this); // Paper + // Paper start - neighbour cache -+ int chunkX = this.loc.x; -+ int chunkZ = this.loc.z; -+ ChunkProviderServer chunkProvider = ((WorldServer)this.world).getChunkProvider(); ++ int chunkX = this.chunkPos.x; ++ int chunkZ = this.chunkPos.z; ++ ServerChunkCache chunkProvider = this.level.getChunkSource(); + 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); ++ LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz); + if (neighbour != null) { + neighbour.setNeighbourUnloaded(-dx, -dz); + } @@ -4403,179 +3983,51 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // 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; +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { } -+ 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 void packTicks(ServerLevel world) { +- DefaultedRegistry registryblocks; +- + if (this.blockTicks == EmptyTickList.empty()) { // CraftBukkit - decompile error +- registryblocks = Registry.BLOCK; +- Objects.requireNonNull(registryblocks); +- this.blockTicks = new ChunkTickList<>(registryblocks::getKey, world.getBlockTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); ++ this.blockTicks = new ChunkTickList<>(Registry.BLOCK::getKey, world.getBlockTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); // Paper - decompile fix: inline Registry.BLOCK + this.setUnsaved(true); + } - public interface DataPalette { + if (this.liquidTicks == EmptyTickList.empty()) { // CraftBukkit - decompile error +- registryblocks = Registry.FLUID; +- Objects.requireNonNull(registryblocks); +- this.liquidTicks = new ChunkTickList<>(registryblocks::getKey, world.getLiquidTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); ++ this.liquidTicks = new ChunkTickList<>(Registry.FLUID::getKey, world.getLiquidTicks().fetchTicksInChunk(this.chunkPos, true, false), world.getGameTime()); // Paper - decompile fix: inline Registry.FLUID + this.setUnsaved(true); + } -+ 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 { - +@@ -0,0 +0,0 @@ public class ProtoChunk implements ChunkAccess { + this.postProcessing = new ShortList[world.getSectionsCount()]; } + // Paper start - If loaded util + @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { -+ return this.getFluid(blockposition); ++ public FluidState getFluidIfLoaded(BlockPos blockposition) { ++ return this.getFluidState(blockposition); + } + + @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { -+ return this.getType(blockposition); ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { ++ return this.getBlockState(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 + public BlockState getBlockState(BlockPos pos) { + int i = pos.getY(); 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 @@ -4589,7 +4041,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 * Counter for IDs. Order doesn't matter, only uniqueness. */ @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - runTaskTimer(plugin, (Object) task, delay, period); + this.runTaskTimer(plugin, (Object) task, delay, period); } + public BukkitTask scheduleInternalTask(Runnable run, int delay, String taskName) { @@ -4598,7 +4050,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + public BukkitTask runTaskTimer(Plugin plugin, Object runnable, long delay, long period) { - validate(plugin, runnable); + CraftScheduler.validate(plugin, runnable); if (delay < 0L) { @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { task.run(); @@ -4624,7 +4076,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end } finally { - currentTask = null; + this.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 @@ -4794,43 +4246,30 @@ diff --git a/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) { +@@ -0,0 +0,0 @@ public class DummyGeneratorAccess implements LevelAccessor { + public FluidState getFluidState(BlockPos pos) { throw new UnsupportedOperationException("Not supported yet."); } + // Paper start - if loaded util + @javax.annotation.Nullable + @Override -+ public IChunkAccess getChunkIfLoadedImmediately(int x, int z) { ++ public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override -+ public IBlockData getTypeIfLoaded(BlockPosition blockposition) { ++ public BlockState getTypeIfLoaded(BlockPos blockposition) { + throw new UnsupportedOperationException("Not supported yet."); + } + @Override -+ public Fluid getFluidIfLoaded(BlockPosition blockposition) { ++ public FluidState getFluidIfLoaded(BlockPos 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 @@ -4847,4 +4286,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end try { - config.save( CONFIG_FILE ); + SpigotConfig.config.save( CONFIG_FILE ); diff --git a/Spigot-Server-Patches/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch b/patches/server/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch similarity index 74% rename from Spigot-Server-Patches/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch rename to patches/server/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch index b467c4075e..1a744c2c68 100644 --- a/Spigot-Server-Patches/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch +++ b/patches/server/Make-CraftWorld-loadChunk-int-int-false-load-unconve.patch @@ -13,8 +13,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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 +- ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); ++ ChunkAccess chunk = this.world.getChunkSource().getChunk(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) { + if (chunk instanceof ImposterProtoChunk) { diff --git a/Spigot-Server-Patches/Make-EnderDragon-implement-Mob.patch b/patches/server/Make-EnderDragon-implement-Mob.patch similarity index 69% rename from Spigot-Server-Patches/Make-EnderDragon-implement-Mob.patch rename to patches/server/Make-EnderDragon-implement-Mob.patch index e43453584d..f22973c810 100644 --- a/Spigot-Server-Patches/Make-EnderDragon-implement-Mob.patch +++ b/patches/server/Make-EnderDragon-implement-Mob.patch @@ -11,23 +11,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ package org.bukkit.craftbukkit.entity; -+import net.minecraft.world.entity.EntityInsentient; // Paper - import net.minecraft.world.entity.EntityLiving; +-import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.Mob; 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 CraftComplexLivingEntity(CraftServer server, LivingEntity entity) { +public abstract class CraftComplexLivingEntity extends CraftMob implements ComplexLivingEntity { // Paper -+ public CraftComplexLivingEntity(CraftServer server, EntityInsentient entity) { // Paper ++ public CraftComplexLivingEntity(CraftServer server, Mob entity) { // Paper super(server, entity); } @Override -- public EntityLiving getHandle() { -- return (EntityLiving) entity; -+ public EntityInsentient getHandle() { // Paper -+ return (EntityInsentient) entity; // Paper +- public LivingEntity getHandle() { +- return (LivingEntity) entity; ++ public Mob getHandle() { // Paper ++ return (Mob) entity; // Paper } @Override diff --git a/Spigot-Server-Patches/Make-item-validations-configurable.patch b/patches/server/Make-item-validations-configurable.patch similarity index 79% rename from Spigot-Server-Patches/Make-item-validations-configurable.patch rename to patches/server/Make-item-validations-configurable.patch index a68bcb43d6..8ad9940241 100644 --- a/Spigot-Server-Patches/Make-item-validations-configurable.patch +++ b/patches/server/Make-item-validations-configurable.patch @@ -35,20 +35,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { super(tag); - if (tag.hasKey(BOOK_TITLE.NBT)) { + if (tag.contains(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)) { + if (tag.contains(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)) { + if (tag.contains(RESOLVED.NBT)) { @@ -0,0 +0,0 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta { } else { - page = validatePage(page); + page = this.validatePage(page); } - this.pages.add( limit( page, 16384 ) ); // Spigot + this.pages.add( limit( page, com.destroystokyo.paper.PaperConfig.itemValidationBookPageLength ) ); // Spigot // Paper - make configurable @@ -60,24 +60,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + CompoundTag 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.contains(NAME.NBT)) { +- this.displayName = limit( display.getString(NAME.NBT), 8192 ); // Spigot ++ this.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.contains(LOCNAME.NBT)) { +- this.locName = limit( display.getString(LOCNAME.NBT), 8192 ); // Spigot ++ this.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()); + if (display.contains(LORE.NBT)) { + ListTag list = display.getList(LORE.NBT, CraftMagicNumbers.NBT.TAG_STRING); + this.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); + this.lore.add(line); } } diff --git a/Spigot-Server-Patches/Make-legacy-ping-handler-more-reliable.patch b/patches/server/Make-legacy-ping-handler-more-reliable.patch similarity index 75% rename from Spigot-Server-Patches/Make-legacy-ping-handler-more-reliable.patch rename to patches/server/Make-legacy-ping-handler-more-reliable.patch index 9d353cfeda..ce41bcd2af 100644 --- a/Spigot-Server-Patches/Make-legacy-ping-handler-more-reliable.patch +++ b/patches/server/Make-legacy-ping-handler-more-reliable.patch @@ -27,20 +27,20 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.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 { - +--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java ++++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java +@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { private static final Logger LOGGER = LogManager.getLogger(); - private final ServerConnection b; + public static final int FAKE_PROTOCOL_VERSION = 127; + private final ServerConnectionListener serverConnectionListener; + 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 { + public LegacyQueryHandler(ServerConnectionListener networkIo) { + this.serverConnectionListener = networkIo; +@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + public void channelRead(ChannelHandlerContext channelhandlercontext, Object object) { ByteBuf bytebuf = (ByteBuf) object; + // Paper start - Make legacy ping handler more reliable @@ -56,8 +56,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 bytebuf.markReaderIndex(); boolean flag = true; -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { - this.a(channelhandlercontext, this.a(s)); +@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { + this.sendFlushAndClose(channelhandlercontext, this.createReply(s)); break; default: + // Paper start - Replace with improved version below @@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 boolean flag1 = bytebuf.readUnsignedByte() == 1; flag1 &= bytebuf.readUnsignedByte() == 250; -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { +@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { } finally { bytebuf1.release(); } @@ -75,7 +75,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } bytebuf.release(); -@@ -0,0 +0,0 @@ public class LegacyPingHandler extends ChannelInboundHandlerAdapter { +@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter { } @@ -121,7 +121,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ MinecraftServer server = this.b.d(); ++ MinecraftServer server = this.serverConnectionListener.getServer(); + int protocolVersion = buf.readByte(); + String host = readLegacyString(buf); + if (host == null) { @@ -141,8 +141,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); ++ Byte.MAX_VALUE, server.getServerVersion(), server.getMotd(), server.getPlayerCount(), server.getMaxPlayers()); ++ this.sendFlushAndClose(ctx, this.createReply(response)); + } + + private void removeHandler(ChannelHandlerContext ctx) { @@ -163,6 +163,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + - private void a(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf) { - channelhandlercontext.pipeline().firstContext().writeAndFlush(bytebuf).addListener(ChannelFutureListener.CLOSE); + private void sendFlushAndClose(ChannelHandlerContext ctx, ByteBuf buf) { + ctx.pipeline().firstContext().writeAndFlush(buf).addListener(ChannelFutureListener.CLOSE); } diff --git a/patches/server/Make-max-squid-spawn-height-configurable.patch b/patches/server/Make-max-squid-spawn-height-configurable.patch new file mode 100644 index 0000000000..8d251bac95 --- /dev/null +++ b/patches/server/Make-max-squid-spawn-height-configurable.patch @@ -0,0 +1,36 @@ +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 { + disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); + log("Creeper lingering effect: " + disableCreeperLingeringEffect); + } ++ ++ 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/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -0,0 +0,0 @@ public class Squid extends WaterAnimal { + } + + public static boolean checkSquidSpawnRules(EntityType type, LevelAccessor world, MobSpawnType spawnReason, BlockPos pos, Random random) { +- return pos.getY() > world.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && pos.getY() < world.getSeaLevel(); // Spigot ++ final double maxHeight = world.getMinecraftWorld().paperConfig.squidMaxSpawnHeight > 0 ? world.getMinecraftWorld().paperConfig.squidMaxSpawnHeight : world.getSeaLevel(); // Paper ++ return pos.getY() > world.getMinecraftWorld().spigotConfig.squidSpawnRangeMin && pos.getY() < maxHeight; // Spigot // Paper + } + + @Override diff --git a/Spigot-Server-Patches/Make-player-data-saving-configurable.patch b/patches/server/Make-player-data-saving-configurable.patch similarity index 100% rename from Spigot-Server-Patches/Make-player-data-saving-configurable.patch rename to patches/server/Make-player-data-saving-configurable.patch diff --git a/patches/server/Make-schedule-command-per-world.patch b/patches/server/Make-schedule-command-per-world.patch new file mode 100644 index 0000000000..4c5b15bfd2 --- /dev/null +++ b/patches/server/Make-schedule-command-per-world.patch @@ -0,0 +1,37 @@ +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/ScheduleCommand.java b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/commands/ScheduleCommand.java ++++ b/src/main/java/net/minecraft/server/commands/ScheduleCommand.java +@@ -0,0 +0,0 @@ public class ScheduleCommand { + return new TranslatableComponent("commands.schedule.cleared.failure", eventName); + }); + private static final SuggestionProvider SUGGEST_SCHEDULE = (context, builder) -> { +- return SharedSuggestionProvider.suggest(context.getSource().getServer().getWorldData().overworldData().getScheduledEvents().getEventsIds(), builder); ++ return SharedSuggestionProvider.suggest(context.getSource().getLevel().serverLevelData.overworldData().getScheduledEvents().getEventsIds(), builder); // Paper + }; + + public static void register(CommandDispatcher dispatcher) { +@@ -0,0 +0,0 @@ public class ScheduleCommand { + } else { + long l = source.getLevel().getGameTime() + (long)time; + ResourceLocation resourceLocation = function.getFirst(); +- TimerQueue timerQueue = source.getServer().getWorldData().overworldData().getScheduledEvents(); ++ TimerQueue timerQueue = source.getLevel().serverLevelData.getScheduledEvents(); // Paper + function.getSecond().ifLeft((functionx) -> { + String string = resourceLocation.toString(); + if (replace) { +@@ -0,0 +0,0 @@ public class ScheduleCommand { + } + + private static int remove(CommandSourceStack source, String eventName) throws CommandSyntaxException { +- int i = source.getServer().getWorldData().overworldData().getScheduledEvents().remove(eventName); ++ int i = source.getLevel().serverLevelData.getScheduledEvents().remove(eventName); // Paper + if (i == 0) { + throw ERROR_CANT_REMOVE.create(eventName); + } else { diff --git a/Spigot-Server-Patches/Make-shield-blocking-delay-configurable.patch b/patches/server/Make-shield-blocking-delay-configurable.patch similarity index 69% rename from Spigot-Server-Patches/Make-shield-blocking-delay-configurable.patch rename to patches/server/Make-shield-blocking-delay-configurable.patch index 36a371579e..8e28491bb0 100644 --- a/Spigot-Server-Patches/Make-shield-blocking-delay-configurable.patch +++ b/patches/server/Make-shield-blocking-delay-configurable.patch @@ -18,25 +18,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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(); +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + if (this.isUsingItem() && !this.useItem.isEmpty()) { + Item item = this.useItem.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 +- return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 5; ++ return item.getUseAnimation(this.useItem) != UseAnim.BLOCK ? false : item.getUseDuration(this.useItem) - this.useItemRemaining >= 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 shieldBlockingDelay = level.paperConfig.shieldBlockingDelay; + + public int getShieldBlockingDelay() { + return shieldBlockingDelay; @@ -46,7 +44,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.shieldBlockingDelay = shieldBlockingDelay; + } + // Paper end - } ++ + public boolean isSuppressingSlidingDownLadder() { + return this.isShiftKeyDown(); + } 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 diff --git a/patches/server/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch b/patches/server/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch new file mode 100644 index 0000000000..d9f2a1cb10 --- /dev/null +++ b/patches/server/Make-targetSize-more-aggressive-in-the-chunk-unload-.patch @@ -0,0 +1,38 @@ +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/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.playerMap = new PlayerMap(); + this.entityMap = new Int2ObjectOpenHashMap(); + this.chunkTypeCache = new Long2ByteOpenHashMap(); +- this.unloadQueue = Queues.newConcurrentLinkedQueue(); ++ this.unloadQueue = new com.destroystokyo.paper.utils.CachedSizeConcurrentLinkedQueue<>(); // Paper - need constant-time size() + this.structureManager = structureManager; + this.storageFolder = session.getDimensionPath(world.dimension()); + this.level = world; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Spigot start + org.spigotmc.SlackActivityAccountant activityAccountant = this.level.getServer().slackActivityAccountant; + activityAccountant.startActivity(0.5); +- int targetSize = (int) (this.toDrop.size() * ChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR); ++ int targetSize = Math.min(this.toDrop.size() - 100, (int) (this.toDrop.size() * ChunkMap.UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive + // Spigot end + while (longiterator.hasNext()) { // Spigot + long j = longiterator.nextLong(); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + Runnable runnable; + +- while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > 2000) && (runnable = (Runnable) this.unloadQueue.poll()) != null) { ++ int queueTarget = Math.min(this.unloadQueue.size() - 100, (int) (this.unloadQueue.size() * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Target this queue as well ++ while ((shouldKeepTicking.getAsBoolean() || this.unloadQueue.size() > queueTarget) && (runnable = (Runnable)this.unloadQueue.poll()) != null) { // Paper - Target this queue as well + runnable.run(); + } + diff --git a/Spigot-Server-Patches/Make-the-GUI-graph-fancier.patch b/patches/server/Make-the-GUI-graph-fancier.patch similarity index 80% rename from Spigot-Server-Patches/Make-the-GUI-graph-fancier.patch rename to patches/server/Make-the-GUI-graph-fancier.patch index 2d2187f046..8a4708dc6d 100644 --- a/Spigot-Server-Patches/Make-the-GUI-graph-fancier.patch +++ b/patches/server/Make-the-GUI-graph-fancier.patch @@ -149,7 +149,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return new Dimension(350, 200); + } + -+ public void stop() { a(); } public void a() { ++ public void close() { + timer.stop(); + ramGraph.stop(); + } @@ -162,7 +162,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.gui; + -+import net.minecraft.SystemUtils; ++import net.minecraft.Util; +import net.minecraft.server.MinecraftServer; + +import javax.swing.DefaultListCellRenderer; @@ -176,7 +176,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.util.Vector; + +public class RAMDetails extends JList { -+ public static final DecimalFormat DECIMAL_FORMAT = SystemUtils.peek(new DecimalFormat("########0.000"), (format) ++ public static final DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("########0.000"), (format) + -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))); + + private final MinecraftServer server; @@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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"); ++ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.tickTimes)) + " ms"); + setListData(vector); + } + @@ -383,54 +383,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + timer.stop(); + } +} -diff --git a/src/main/java/net/minecraft/SystemUtils.java b/src/main/java/net/minecraft/SystemUtils.java +diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.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(); - } +--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java ++++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java +@@ -0,0 +0,0 @@ public class MinecraftServerGui extends JComponent { -+ 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() { + private JComponent buildInfoPanel() { 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 +- StatsComponent guistatscomponent = new StatsComponent(this.server); ++ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.server); // Paper + Collection collection = this.finalizers; // CraftBukkit - decompile error - this.e.add(guistatscomponent::a); - jpanel.add(guistatscomponent, "North"); + Objects.requireNonNull(guistatscomponent); diff --git a/Spigot-Server-Patches/Make-the-default-permission-message-configurable.patch b/patches/server/Make-the-default-permission-message-configurable.patch similarity index 98% rename from Spigot-Server-Patches/Make-the-default-permission-message-configurable.patch rename to patches/server/Make-the-default-permission-message-configurable.patch index cafa7f443d..e3ad0f09d0 100644 --- a/Spigot-Server-Patches/Make-the-default-permission-message-configurable.patch +++ b/patches/server/Make-the-default-permission-message-configurable.patch @@ -3,6 +3,7 @@ From: Shane Freeder Date: Sun, 18 Nov 2018 19:49:56 +0000 Subject: [PATCH] Make the default permission message configurable +TODO: Change the message in PaperCommand diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/Spigot-Server-Patches/Maps-shouldn-t-load-chunks.patch b/patches/server/Maps-shouldn-t-load-chunks.patch similarity index 62% rename from Spigot-Server-Patches/Maps-shouldn-t-load-chunks.patch rename to patches/server/Maps-shouldn-t-load-chunks.patch index 59332304af..9857731686 100644 --- a/Spigot-Server-Patches/Maps-shouldn-t-load-chunks.patch +++ b/patches/server/Maps-shouldn-t-load-chunks.patch @@ -14,19 +14,19 @@ Previously maps would load all chunks in a certain radius depending on 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 +diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.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 { +--- a/src/main/java/net/minecraft/world/item/MapItem.java ++++ b/src/main/java/net/minecraft/world/item/MapItem.java +@@ -0,0 +0,0 @@ public class MapItem extends ComplexItem { 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 + Multiset multiset = LinkedHashMultiset.create(); +- LevelChunk chunk = world.getChunkAt(new BlockPos(k2, 0, l2)); ++ LevelChunk chunk = world.getChunkIfLoaded(new BlockPos(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(); + ChunkPos chunkcoordintpair = chunk.getPos(); int i3 = k2 & 15; int j3 = l2 & 15; diff --git a/Spigot-Server-Patches/Merchant-getRecipes-should-return-an-immutable-list.patch b/patches/server/Merchant-getRecipes-should-return-an-immutable-list.patch similarity index 66% rename from Spigot-Server-Patches/Merchant-getRecipes-should-return-an-immutable-list.patch rename to patches/server/Merchant-getRecipes-should-return-an-immutable-list.patch index 82b49fd28e..d31191d03a 100644 --- a/Spigot-Server-Patches/Merchant-getRecipes-should-return-an-immutable-list.patch +++ b/patches/server/Merchant-getRecipes-should-return-an-immutable-list.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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()) +- return Collections.unmodifiableList(Lists.transform(this.merchant.getOffers(), new Function() { ++ return com.google.common.collect.ImmutableList.copyOf(Lists.transform(this.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) { + public MerchantRecipe apply(net.minecraft.world.item.trading.MerchantOffer recipe) { return recipe.asBukkit(); diff --git a/Spigot-Server-Patches/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 55% rename from Spigot-Server-Patches/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch index 05158f57e5..b0c6ba939d 100644 --- a/Spigot-Server-Patches/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ b/patches/server/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch @@ -59,24 +59,24 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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 { + this.managedBlock(() -> { + 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(); + this.level.timings.chunkTicks.startTiming(); // Paper +- this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping ++ final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_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 ServerChunkCache extends ChunkSource { + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); + if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); ++ if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper } - } - } -@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { - super.executeTask(runnable); + + // this.level.timings.doTickTiles.startTiming(); // Spigot // Paper +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + super.doRunTask(task); } + // Paper start + private long lastMidTickChunkTask = 0; + public boolean pollChunkLoadTasks() { -+ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask()) { ++ if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ServerChunkCache.this.level.asyncChunkTaskManager.pollNextChunkTask()) { + try { -+ ChunkProviderServer.this.tickDistanceManager(); ++ ServerChunkCache.this.runDistanceManagerUpdates(); + } finally { + // from below: process pending Chunk loadCallback() and unloadCallback() after each run task -+ playerChunkMap.callbackExecutor.run(); ++ chunkMap.callbackExecutor.run(); + } + return true; + } + return false; + } + public void midTickLoadChunks() { -+ MinecraftServer server = ChunkProviderServer.this.world.getMinecraftServer(); ++ net.minecraft.server.MinecraftServer server = ServerChunkCache.this.level.getServer(); + // always try to load chunks, restrain generation/other updates only. don't count these towards tick count + //noinspection StatementWithEmptyBody + while (pollChunkLoadTasks()) {} @@ -219,8 +211,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.canSleepForTick();) { -+ if (this.executeNext()) { ++ for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.haveTime();) { ++ if (this.pollTask()) { + server.midTickChunksTasksRan++; + lastMidTickChunkTask = System.nanoTime(); + } else { @@ -231,41 +223,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 + public boolean pollTask() { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 { +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } timings.scheduledBlocks.stopTiming(); // Paper -+ this.getMinecraftServer().midTickLoadChunks(); // Paper - gameprofilerfiller.exitEnter("raid"); ++ this.getServer().midTickLoadChunks(); // Paper + gameprofilerfiller.popPush("raid"); this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.raids.tick(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl timings.doSounds.startTiming(); // Spigot - this.ak(); + this.runBlockEvents(); 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 { ++ this.getServer().midTickLoadChunks(); // Paper + this.handlingTick = false; + gameprofilerfiller.pop(); + boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl 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 + gameprofilerfiller.pop(); ++ this.getServer().midTickLoadChunks(); // Paper this.tickBlockEntities(); } + gameprofilerfiller.push("entityManagement"); ++ this.getServer().midTickLoadChunks(); // Paper + this.entityManager.tick(); + gameprofilerfiller.pop(); + } diff --git a/patches/server/Mob-Pathfinding-API.patch b/patches/server/Mob-Pathfinding-API.patch new file mode 100644 index 0000000000..e9e3d5e4a8 --- /dev/null +++ b/patches/server/Mob-Pathfinding-API.patch @@ -0,0 +1,180 @@ +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 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 net.minecraft.world.level.pathfinder.Node; ++import net.minecraft.world.level.pathfinder.Path; ++import java.util.ArrayList; ++import java.util.List; ++ ++public class PaperPathfinder implements com.destroystokyo.paper.entity.Pathfinder { ++ ++ private final net.minecraft.world.entity.Mob entity; ++ ++ public PaperPathfinder(net.minecraft.world.entity.Mob entity) { ++ this.entity = entity; ++ } ++ ++ @Override ++ public Mob getEntity() { ++ return entity.getBukkitMob(); ++ } ++ ++ @Override ++ public void stopPathfinding() { ++ entity.getNavigation().stop(); ++ } ++ ++ @Override ++ public boolean hasPath() { ++ return entity.getNavigation().getPath() != null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult getCurrentPath() { ++ Path path = entity.getNavigation().getPath(); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(Location loc) { ++ Validate.notNull(loc, "Location can not be null"); ++ Path path = entity.getNavigation().createPath(loc.getX(), loc.getY(), loc.getZ(), 0); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Nullable ++ @Override ++ public PathResult findPath(LivingEntity target) { ++ Validate.notNull(target, "Target can not be null"); ++ Path path = entity.getNavigation().createPath(((CraftLivingEntity) target).getHandle(), 0); ++ return path != null ? new PaperPathResult(path) : null; ++ } ++ ++ @Override ++ public boolean moveTo(@Nonnull PathResult path, double speed) { ++ Validate.notNull(path, "PathResult can not be null"); ++ Path pathEntity = ((PaperPathResult) path).path; ++ return entity.getNavigation().moveTo(pathEntity, speed); ++ } ++ ++ @Override ++ public boolean canOpenDoors() { ++ return entity.getNavigation().pathFinder.nodeEvaluator.canOpenDoors(); ++ } ++ ++ @Override ++ public void setCanOpenDoors(boolean canOpenDoors) { ++ entity.getNavigation().pathFinder.nodeEvaluator.setCanOpenDoors(canOpenDoors); ++ } ++ ++ @Override ++ public boolean canPassDoors() { ++ return entity.getNavigation().pathFinder.nodeEvaluator.canPassDoors(); ++ } ++ ++ @Override ++ public void setCanPassDoors(boolean canPassDoors) { ++ entity.getNavigation().pathFinder.nodeEvaluator.setCanPassDoors(canPassDoors); ++ } ++ ++ @Override ++ public boolean canFloat() { ++ return entity.getNavigation().pathFinder.nodeEvaluator.canFloat(); ++ } ++ ++ @Override ++ public void setCanFloat(boolean canFloat) { ++ entity.getNavigation().pathFinder.nodeEvaluator.setCanFloat(canFloat); ++ } ++ ++ public class PaperPathResult implements com.destroystokyo.paper.entity.PaperPathfinder.PathResult { ++ ++ private final Path path; ++ PaperPathResult(Path path) { ++ this.path = path; ++ } ++ ++ @Nullable ++ @Override ++ public Location getFinalPoint() { ++ Node point = path.getEndNode(); ++ return point != null ? toLoc(point) : null; ++ } ++ ++ @Override ++ public List getPoints() { ++ List points = new ArrayList<>(); ++ for (Node point : path.nodes) { ++ points.add(toLoc(point)); ++ } ++ return points; ++ } ++ ++ @Override ++ public int getNextPointIndex() { ++ return path.getNextNodeIndex(); ++ } ++ ++ @Nullable ++ @Override ++ public Location getNextPoint() { ++ if (!path.hasNext()) { ++ return null; ++ } ++ return toLoc(path.nodes.get(path.getNextNodeIndex())); ++ } ++ } ++ ++ private Location toLoc(Node point) { ++ return new Location(entity.level.getWorld(), point.x, point.y, point.z); ++ } ++} +diff --git a/src/main/java/net/minecraft/world/level/pathfinder/Path.java b/src/main/java/net/minecraft/world/level/pathfinder/Path.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/Path.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/Path.java +@@ -0,0 +0,0 @@ public class Path { + private final BlockPos target; + private final float distToTarget; + private final boolean reached; ++ public boolean hasNext() { return getNextNodeIndex() < this.nodes.size(); } // Paper + + public Path(List nodes, BlockPos target, boolean reachesTarget) { + this.nodes = nodes; +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, net.minecraft.world.entity.Mob 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) { + net.minecraft.world.entity.Mob entity = this.getHandle(); diff --git a/patches/server/Mob-Spawner-API-Enhancements.patch b/patches/server/Mob-Spawner-API-Enhancements.patch new file mode 100644 index 0000000000..b2f8cbefd2 --- /dev/null +++ b/patches/server/Mob-Spawner-API-Enhancements.patch @@ -0,0 +1,129 @@ +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/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + + private static final Logger LOGGER = LogManager.getLogger(); + private static final int EVENT_SPAWN = 1; +- private static WeightedRandomList EMPTY_POTENTIALS = WeightedRandomList.create(); ++ public static WeightedRandomList EMPTY_POTENTIALS = WeightedRandomList.create(); // Paper - private->public + public int spawnDelay = 20; + public WeightedRandomList spawnPotentials; + public SpawnData nextSpawnData; +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + this.spawnPotentials = BaseSpawner.EMPTY_POTENTIALS; // CraftBukkit - SPIGOT-3496, MC-92282 + } + +- private boolean isNearPlayer(Level world, BlockPos pos) { ++ public boolean isNearPlayer(Level world, BlockPos pos) { // Paper private->public + return world.isAffectsSpawningPlayerNearby((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper + } + +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + } + } + +- private void delay(Level world, BlockPos pos) { ++ public void delay(Level world, BlockPos pos) { // Paper private->public + if (this.maxSpawnDelay <= this.minSpawnDelay) { + this.spawnDelay = this.minSpawnDelay; + } else { +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + } + + public void load(@Nullable Level world, BlockPos pos, CompoundTag nbt) { ++ // Paper start - use larger int if set ++ if (nbt.contains("Paper.Delay")) { ++ this.spawnDelay = nbt.getInt("Paper.Delay"); ++ } else { + this.spawnDelay = nbt.getShort("Delay"); ++ } ++ // Paper end + List list = Lists.newArrayList(); + + if (nbt.contains("SpawnPotentials", 9)) { +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + this.setSpawnData(world, pos, mobspawnerdata); + }); + } +- ++ // Paper start - use ints if set ++ if (nbt.contains("Paper.MinSpawnDelay", 99)) { ++ this.minSpawnDelay = nbt.getInt("Paper.MinSpawnDelay"); ++ this.maxSpawnDelay = nbt.getInt("Paper.MaxSpawnDelay"); ++ this.spawnCount = nbt.getShort("SpawnCount"); ++ } else // Paper end + if (nbt.contains("MinSpawnDelay", 99)) { +- this.minSpawnDelay = nbt.getShort("MinSpawnDelay"); +- this.maxSpawnDelay = nbt.getShort("MaxSpawnDelay"); ++ this.minSpawnDelay = nbt.getInt("MinSpawnDelay"); // Paper - short->int ++ this.maxSpawnDelay = nbt.getInt("MaxSpawnDelay"); // Paper - short->int + this.spawnCount = nbt.getShort("SpawnCount"); + } + +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + if (minecraftkey == null) { + return nbt; + } else { +- nbt.putShort("Delay", (short) this.spawnDelay); +- nbt.putShort("MinSpawnDelay", (short) this.minSpawnDelay); +- nbt.putShort("MaxSpawnDelay", (short) this.maxSpawnDelay); ++ // Paper start ++ if (spawnDelay > Short.MAX_VALUE) { ++ nbt.putInt("Paper.Delay", this.spawnDelay); ++ } ++ nbt.putShort("Delay", (short) Math.min(Short.MAX_VALUE, this.spawnDelay)); ++ ++ if (minSpawnDelay > Short.MAX_VALUE || maxSpawnDelay > Short.MAX_VALUE) { ++ nbt.putInt("Paper.MinSpawnDelay", this.minSpawnDelay); ++ nbt.putInt("Paper.MaxSpawnDelay", this.maxSpawnDelay); ++ } ++ ++ nbt.putShort("MinSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.minSpawnDelay)); ++ nbt.putShort("MaxSpawnDelay", (short) Math.min(Short.MAX_VALUE, this.maxSpawnDelay)); ++ // Paper end + nbt.putShort("SpawnCount", (short) this.spawnCount); + nbt.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); + nbt.putShort("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 @@ public class CraftCreatureSpawner extends CraftBlockEntityState getActiveSlots() { -+ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); ++ return java.util.stream.Stream.of(target.slots).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) { @@ -116,21 +69,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + getHandle().hurtDir = hurtDirection; } + -+ public static EnumMonsterType fromBukkitEntityCategory(EntityCategory entityCategory) { ++ public static MobType fromBukkitEntityCategory(EntityCategory entityCategory) { + switch (entityCategory) { + case NONE: -+ return EnumMonsterType.UNDEFINED; ++ return MobType.UNDEFINED; + case UNDEAD: -+ return EnumMonsterType.UNDEAD; ++ return MobType.UNDEAD; + case ARTHROPOD: -+ return EnumMonsterType.ARTHROPOD; ++ return MobType.ARTHROPOD; + case ILLAGER: -+ return EnumMonsterType.ILLAGER; ++ return MobType.ILLAGER; + case WATER: -+ return EnumMonsterType.WATER_MOB; ++ return MobType.WATER; + } + throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); + } @@ -171,7 +124,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.world.entity.MobType; +import org.bukkit.craftbukkit.entity.CraftLivingEntity; +import org.bukkit.entity.EntityCategory; +import org.junit.Test; @@ -187,16 +140,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @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()); ++ Map enumMonsterTypeFieldMap = Maps.newHashMap(); ++ for (Field field : MobType.class.getDeclaredFields()) { ++ if (field.getType() == MobType.class) { ++ enumMonsterTypeFieldMap.put( (MobType) 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); ++ assertTrue(MobType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); + } +} diff --git a/patches/server/More-Lidded-Block-API.patch b/patches/server/More-Lidded-Block-API.patch new file mode 100644 index 0000000000..eeef00dd63 --- /dev/null +++ b/patches/server/More-Lidded-Block-API.patch @@ -0,0 +1,97 @@ +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/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 Bar + } + getTileEntity().openersCounter.opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().openersCounter.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().openersCounter.opened = false; + } ++ ++ // Paper start - More Lidded Block API ++ @Override ++ public boolean isOpen() { ++ return getTileEntity().openersCounter.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 implem + if (getTileEntity().opened) { + Level world = getTileEntity().getLevel(); + world.blockEvent(getPosition(), getTileEntity().getBlockState().getBlock(), 1, 0); +- world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_OPEN, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F); ++ world.playSound(null, getPosition(), SoundEvents.SHULKER_BOX_CLOSE, SoundSource.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/patches/server/More-World-API.patch b/patches/server/More-World-API.patch new file mode 100644 index 0000000000..db9e514674 --- /dev/null +++ b/patches/server/More-World-API.patch @@ -0,0 +1,86 @@ +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/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) { ++ BlockPos originPos = new BlockPos(origin.getX(), origin.getY(), origin.getZ()); ++ BlockPos nearest = getHandle().findNearestBiome(CraftBlock.biomeToBiomeBase(getHandle().registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), biome), originPos, radius, step); ++ return (nearest == null) ? null : new Location(this, nearest.getX(), nearest.getY(), nearest.getZ()); ++ } ++ ++ @Override ++ public boolean isUltrawarm() { ++ return getHandle().dimensionType().ultraWarm(); ++ } ++ ++ @Override ++ public boolean isNatural() { ++ return getHandle().dimensionType().natural(); ++ } ++ ++ @Override ++ public double getCoordinateScale() { ++ return getHandle().dimensionType().coordinateScale(); ++ } ++ ++ @Override ++ public boolean hasSkylight() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean hasBedrockCeiling() { ++ return getHandle().dimensionType().hasSkyLight(); ++ } ++ ++ @Override ++ public boolean isPiglinSafe() { ++ return getHandle().dimensionType().piglinSafe(); ++ } ++ ++ @Override ++ public boolean doesBedWork() { ++ return getHandle().dimensionType().bedWorks(); ++ } ++ ++ @Override ++ public boolean doesRespawnAnchorWork() { ++ return getHandle().dimensionType().respawnAnchorWorks(); ++ } ++ ++ @Override ++ public boolean hasRaids() { ++ return getHandle().dimensionType().hasRaids(); ++ } ++ ++ @Override ++ public boolean isFixedTime() { ++ return getHandle().dimensionType().hasFixedTime(); ++ } ++ ++ @Override ++ public Collection getInfiniburn() { ++ return com.google.common.collect.Sets.newHashSet(com.google.common.collect.Iterators.transform(getHandle().dimensionType().infiniburn().getValues().iterator(), CraftMagicNumbers::getMaterial)); ++ } ++ // Paper end ++ + @Override + public Raid locateNearestRaid(Location location, int radius) { + Validate.notNull(location, "Location cannot be null"); diff --git a/patches/server/More-lightning-API.patch b/patches/server/More-lightning-API.patch new file mode 100644 index 0000000000..8f7f315443 --- /dev/null +++ b/patches/server/More-lightning-API.patch @@ -0,0 +1,38 @@ +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/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 this.spigot; + } + // Spigot end ++ ++ // Paper start ++ @Override ++ public int getFlashCount() { ++ return getHandle().flashes; ++ } ++ ++ @Override ++ public void setFlashCount(int flashes) { ++ com.google.common.base.Preconditions.checkArgument(flashes >= 0, "Flashes has to be a positive number!"); ++ getHandle().flashes = flashes; ++ } ++ ++ @Override ++ public int getLifeTicks() { ++ return getHandle().life; ++ } ++ ++ @Override ++ public void setLifeTicks(int lifeTicks) { ++ getHandle().life = lifeTicks; ++ } ++ // Paper end + } diff --git a/Spigot-Server-Patches/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch b/patches/server/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch similarity index 82% rename from Spigot-Server-Patches/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch rename to patches/server/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch index d623a5eb77..bda4803387 100644 --- a/Spigot-Server-Patches/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch +++ b/patches/server/Move-player-to-spawn-point-if-spawn-in-unloaded-worl.patch @@ -10,12 +10,12 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n bworld = server.getWorld(worldName); } - if (bworld == null) { -- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(World.OVERWORLD).getWorld(); +- bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getLevel(Level.OVERWORLD).getWorld(); - } + // Paper start - Move player to spawn point if spawn in unloaded world +// if (bworld == null) { @@ -23,5 +23,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +// } + // Paper end - Move player to spawn point if spawn in unloaded world - spawnIn(bworld == null ? null : ((CraftWorld) bworld).getHandle()); + ((ServerPlayer) this).setLevel(bworld == null ? null : ((CraftWorld) bworld).getHandle()); } diff --git a/patches/server/Move-range-check-for-block-placing-up.patch b/patches/server/Move-range-check-for-block-placing-up.patch new file mode 100644 index 0000000000..cbdebb889f --- /dev/null +++ b/patches/server/Move-range-check-for-block-placing-up.patch @@ -0,0 +1,37 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + BlockPos blockposition = movingobjectpositionblock.getBlockPos(); + Direction enumdirection = movingobjectpositionblock.getDirection(); + ++ // Paper start - move check up ++ Location eyeLoc = this.getCraftPlayer().getEyeLocation(); ++ double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); ++ if (reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? CREATIVE_PLACE_DISTANCE_SQUARED : SURVIVAL_PLACE_DISTANCE_SQUARED)) { ++ return; ++ } ++ // Paper end - move check up ++ + this.player.resetLastActionTime(); + int i = this.player.level.getMaxBuildHeight(); + + if (blockposition.getY() < i) { + if (this.awaitingPositionFromClient == null && this.player.distanceToSqr((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && worldserver.mayInteract((net.minecraft.world.entity.player.Player) this.player, blockposition)) { + // CraftBukkit start - Check if we can actually do something over this large a distance +- Location eyeLoc = this.getCraftPlayer().getEyeLocation(); +- double reachDistance = NumberConversions.square(eyeLoc.getX() - blockposition.getX()) + NumberConversions.square(eyeLoc.getY() - blockposition.getY()) + NumberConversions.square(eyeLoc.getZ() - blockposition.getZ()); +- if (reachDistance > (this.getCraftPlayer().getGameMode() == org.bukkit.GameMode.CREATIVE ? ServerGamePacketListenerImpl.CREATIVE_PLACE_DISTANCE_SQUARED : ServerGamePacketListenerImpl.SURVIVAL_PLACE_DISTANCE_SQUARED)) { +- return; +- } ++ // Paper - move check up + this.player.stopUsingItem(); // SPIGOT-4706 + // CraftBukkit end + InteractionResult enuminteractionresult = this.player.gameMode.useItemOn(this.player, worldserver, itemstack, enumhand, movingobjectpositionblock); diff --git a/patches/server/No-Tick-view-distance-implementation.patch b/patches/server/No-Tick-view-distance-implementation.patch new file mode 100644 index 0000000000..654f1fd40f --- /dev/null +++ b/patches/server/No-Tick-view-distance-implementation.patch @@ -0,0 +1,717 @@ +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.getChunkSource().chunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()), ++ pair("notick-viewdistance", world.getChunkSource().chunkMap.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 { + lightQueueSize = getInt("light-queue-size", lightQueueSize); + } + ++ public int noTickViewDistance; ++ private void viewDistance() { ++ this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); ++ } ++ + public boolean antiXray; + public EngineMode engineMode; + public int maxBlockHeight; +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.getChunkSource().chunkMap.getEffectiveViewDistance()); ++ worldData.addProperty("no-view-distance", world.getChunkSource().chunkMap.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/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + + boolean isUpdateQueued = false; // Paper + private final ChunkMap chunkMap; // Paper ++ // Paper start - no-tick view distance ++ public final LevelChunk getSendingChunk() { ++ // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used ++ // in Chunk's neighbour callback ++ LevelChunk ret = this.chunkMap.level.getChunkSource().getChunkAtIfLoadedImmediately(this.pos.x, this.pos.z); ++ if (ret != null && ret.areNeighboursLoaded(1)) { ++ return ret; ++ } ++ return null; ++ } ++ // Paper end - no-tick view distance + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +@@ -0,0 +0,0 @@ public class ChunkHolder { + } + + public void blockChanged(BlockPos pos) { +- LevelChunk chunk = this.getTickingChunk(); ++ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + int i = this.levelHeightAccessor.getSectionIndex(pos.getY()); +@@ -0,0 +0,0 @@ public class ChunkHolder { + } + + public void sectionLightChanged(LightLayer lightType, int y) { +- LevelChunk chunk = this.getTickingChunk(); ++ LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + chunk.setUnsaved(true); +@@ -0,0 +0,0 @@ public class ChunkHolder { + } + + public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { +- this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { +- entityplayer.connection.send(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.pos); ++ if (players == null) { ++ return; ++ } ++ ++ if (onlyOnWatchDistanceEdge) { // flag -> border only ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ ++ int viewDistance = viewDistanceMap.getLastViewDistance(player); ++ long lastPosition = viewDistanceMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(net.minecraft.server.MCUtil.getCoordinateX(lastPosition) - this.pos.x); ++ int distZ = Math.abs(net.minecraft.server.MCUtil.getCoordinateZ(lastPosition) - this.pos.z); ++ ++ if (Math.max(distX, distZ) == viewDistance) { ++ player.connection.send(packet); ++ } ++ } ++ } else { ++ Object[] backingSet = players.getBackingSet(); ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ player.connection.send(packet); ++ } ++ } ++ ++ return; ++ // Paper end - per player view distance + } + + public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private boolean modified; + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; +- private final ProcessorHandle> mainThreadMailbox; ++ public final ProcessorHandle> mainThreadMailbox; // Paper - private -> public + // Paper start + final ProcessorHandle> mailboxLight; + public void addLightTask(ChunkHolder playerchunk, Runnable run) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + // Paper start - distance maps + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); ++ // 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(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.skipPlayer(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(ServerPlayer player) { + ++ // 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(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated ++ // Paper start - no-tick view distance ++ int effectiveTickViewDistance = this.getEffectiveViewDistance(); ++ int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); ++ ++ if (!this.skipPlayer(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 ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.overworldDataStorage = persistentStateManagerFactory; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); ++ // Paper start - no-tick view distance ++ this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); ++ this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer 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; ++ } ++ LevelChunk chunk = ChunkMap.this.level.getChunkSource().getChunkAtIfLoadedMainThreadNoCache(rangeX, rangeZ); ++ if (chunk == null || !chunk.areNeighboursLoaded(2)) { ++ return; ++ } ++ ++ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ++ ChunkMap.this.level.getChunkSource().addTicketAtLevel(TicketType.PLAYER, chunkPos, 31, chunkPos); // entity ticking level, TODO check on update ++ }, ++ (ServerPlayer 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; ++ } ++ ChunkPos chunkPos = new ChunkPos(rangeX, rangeZ); ++ ChunkMap.this.level.getChunkSource().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, ++ (ServerPlayer 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.connection.send(new ClientboundSetChunkCacheCenterPacket(currPosX, currPosZ)); ++ } ++ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), new Packet[2], false, true); // unloaded, loaded ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkMap.this.updateChunkTracking(player, new ChunkPos(rangeX, rangeZ), null, true, false); // unloaded, loaded ++ }); ++ // Paper end - no-tick view distance + } + + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + completablefuture1.thenAcceptAsync((either) -> { + either.ifLeft((chunk) -> { + this.tickingGenerated.getAndIncrement(); +- Packet[] apacket = new Packet[2]; +- +- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { +- this.playerLoadedChunk(entityplayer, apacket, chunk); +- }); ++ // Paper - no-tick view distance - moved to Chunk neighbour update + }); + }, (runnable) -> { +- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); ++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, 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 ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + public void setViewDistance(int watchDistance) { +- int j = Mth.clamp(watchDistance + 1, 3, 33); ++ int j = Mth.clamp(watchDistance + 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.distanceManager.updatePlayerTickets(this.viewDistance); +- ObjectIterator objectiterator = this.updatingChunkMap.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()) { +- ChunkHolder playerchunk = (ChunkHolder) objectiterator.next(); +- ChunkPos chunkcoordintpair = playerchunk.getPos(); +- Packet[] apacket = new Packet[2]; ++ } + +- this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { +- int l = ChunkMap.checkerboardDistance(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 : Mth.clamp(viewDistance, 2, 32); + +- this.updateChunkTracking(entityplayer, chunkcoordintpair, apacket, flag, flag1); +- }); ++ this.noTickViewDistance = viewDistance; ++ int loadViewDistance = this.getLoadViewDistance(); ++ this.distanceManager.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.level != null && this.level.players != null) { // this can be called from constructor, where these aren't set ++ for (ServerPlayer player : this.level.players) { ++ net.minecraft.server.network.ServerGamePacketListenerImpl connection = player.connection; ++ if (connection != null) { ++ // moved in from PlayerList ++ connection.send(new net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); ++ } ++ this.updateMaps(player); ++ // Paper end - no-tick view distance + } + } + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); + + if (playerchunk != null) { +- LevelChunk chunk = playerchunk.getTickingChunk(); ++ LevelChunk chunk = playerchunk.getSendingChunk(); // Paper - no-tick view distance + + if (chunk != null) { + this.playerLoadedChunk(player, packets, chunk); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + + @Nullable +- public CompoundTag readChunk(ChunkPos pos) throws IOException { // Paper - private -> public ++ public CompoundTag readChunk(ChunkPos pos) throws IOException { + CompoundTag nbttagcompound = this.read(pos); + // Paper start - Cache chunk status on disk + if (nbttagcompound == null) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.removePlayerFromDistanceMaps(player); // 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) { +- ChunkPos chunkcoordintpair = new ChunkPos(k, l); +- +- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], !added, added); +- } +- } ++ // Paper - broadcast view distance map handles this (see remove/add calls above) + + } + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + SectionPos sectionposition = SectionPos.of((Entity) player); + + player.setLastSectionPos(sectionposition); +- player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); ++ // player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); // Paper - distance map handles this now + return sectionposition; + } + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + 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 ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + } + } ++ */ // Paper end - replaced by distance map + + this.updateMaps(player); // Paper - distance maps + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + @Override + public Stream getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) { +- return this.playerMap.getPlayers(chunkPos.toLong()).filter((entityplayer) -> { +- int i = ChunkMap.checkerboardDistance(chunkPos, entityplayer, true); +- +- return i > this.viewDistance ? false : !onlyOnWatchDistanceEdge || i == this.viewDistance; +- }); ++ // 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(chunkPos); ++ ++ 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 (onlyOnWatchDistanceEdge) { // flag -> border only ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object temp = backingSet[i]; ++ if (!(temp instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ int viewDistance = this.playerViewDistanceBroadcastMap.getLastViewDistance(player); ++ long lastPosition = this.playerViewDistanceBroadcastMap.getLastCoordinate(player); ++ ++ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - chunkPos.x); ++ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - chunkPos.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 ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer)temp; ++ players.add(player); ++ } ++ } ++ return players.stream(); ++ // Paper end - per player view distance + } + + public void addEntity(Entity entity) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ // Paper start ++ private static int getLightMask(final LevelChunk chunk) { ++ final net.minecraft.world.level.chunk.LevelChunkSection[] 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 |= (net.minecraft.world.level.chunk.LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ } ++ ++ return mask; ++ } ++ ++ private static int getCeilingLightMask(final LevelChunk 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 void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + if (packets[0] == null) { + packets[0] = new ClientboundLevelChunkPacket(chunk, chunk.level.chunkPacketBlockController.shouldModify(player, chunk)); // Paper - Ani-Xray - Bypass +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + return s; + } + +- protected void updatePlayerTickets(int viewDistance) { +- this.playerTicketManager.updateViewDistance(viewDistance); ++ protected void setNoTickViewDistance(int i) { // Paper - force abi breakage on usage change ++ this.playerTicketManager.updateViewDistance(i); + } + + public int getNaturalSpawnChunkCount() { +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + + private void onLevelChange(long pos, int distance, boolean oldWithinViewDistance, boolean withinViewDistance) { + if (oldWithinViewDistance != withinViewDistance) { +- Ticket ticket = new Ticket<>(TicketType.PLAYER, DistanceManager.PLAYER_TICKET_LEVEL, new ChunkPos(pos)); ++ Ticket ticket = new Ticket<>(TicketType.PLAYER, 33, new ChunkPos(pos)); // Paper - no-tick view distance + + if (withinViewDistance) { + DistanceManager.this.ticketThrottlerInput.tell(ChunkTaskPriorityQueueSorter.message(() -> { +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper ++ boolean needsChunkCenterUpdate; // Paper - no-tick view distance + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); +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.RULE_REDUCEDDEBUGINFO); + + // Spigot - view distance +- playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.spigotConfig.viewDistance, flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); ++ playerconnection.send(new ClientboundLoginPacket(player.getId(), player.gameMode.getGameModeForPlayer(), player.gameMode.getPreviousGameModeForPlayer(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), worlddata.isHardcore(), this.server.levelKeys(), this.registryHolder, worldserver1.dimensionType(), worldserver1.dimension(), this.getMaxPlayers(), worldserver1.getChunkSource().chunkMap.getLoadViewDistance(), flag1, !flag, worldserver1.isDebug(), worldserver1.isFlat())); // Paper - no-tick view distance + player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit + playerconnection.send(new ClientboundCustomPayloadPacket(ClientboundCustomPayloadPacket.BRAND, (new FriendlyByteBuf(Unpooled.buffer())).writeUtf(this.getServer().getServerModName()))); + playerconnection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); +@@ -0,0 +0,0 @@ public abstract class PlayerList { + // CraftBukkit start + LevelData worlddata = worldserver1.getLevelData(); + entityplayer1.connection.send(new ClientboundRespawnPacket(worldserver1.dimensionType(), worldserver1.dimension(), BiomeManager.obfuscateSeed(worldserver1.getSeed()), entityplayer1.gameMode.getGameModeForPlayer(), entityplayer1.gameMode.getPreviousGameModeForPlayer(), worldserver1.isDebug(), worldserver1.isFlat(), flag)); +- entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot ++ entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance + entityplayer1.setLevel(worldserver1); + entityplayer1.unsetRemoved(); + entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot())); +@@ -0,0 +0,0 @@ public abstract class PlayerList { + + public void setViewDistance(int viewDistance) { + this.viewDistance = viewDistance; +- this.broadcastAll(new ClientboundSetChunkCacheRadiusPacket(viewDistance)); ++ //this.sendAll(new PacketPlayOutViewDistance(i)); // Paper - move into setViewDistance + Iterator iterator = this.server.getAllLevels().iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.setBlocksDirty(blockposition, iblockdata1, iblockdata2); + } + +- if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.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.getFullStatus() != null && chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.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.sendBlockUpdated(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 || ((ServerLevel)this).getChunkSource().chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.getCoordinateKey(blockposition)) != null)) { ++ ((ServerLevel)this).getChunkSource().blockChanged(blockposition); ++ // Paper end - per player view distance + } + + if ((i & 1) != 0) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ import net.minecraft.core.Registry; + import net.minecraft.core.SectionPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.network.protocol.Packet; + import net.minecraft.server.level.ChunkHolder; ++import net.minecraft.server.level.ChunkMap; ++import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; + import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.util.profiling.ProfilerFiller; +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + } + + protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { ++ // Paper start - no-tick view distance ++ ServerChunkCache chunkProviderServer = ((ServerLevel)this.level).getChunkSource(); ++ ChunkMap chunkMap = chunkProviderServer.chunkMap; ++ // 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.mainThreadProcessor.execute(() -> { ++ // double check that this condition still holds. ++ if (LevelChunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(LevelChunk.this.coordinateKey) != null) { ++ chunkProviderServer.addTicketAtLevel(net.minecraft.server.level.TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 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.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(chunkMap.getUpdatingChunkIfPresent(this.coordinateKey), (() -> { // Copied frm PlayerChunkMap ++ // double check that this condition still holds. ++ if (!LevelChunk.this.areNeighboursLoaded(1)) { ++ return; ++ } ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.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 net.minecraft.server.level.ServerPlayer)) { ++ continue; ++ } ++ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer)temp; ++ chunkMap.playerLoadedChunk(player, chunkPackets, LevelChunk.this); ++ } ++ }))); ++ } ++ } ++ // Paper end - no-tick view distance + } + + public final boolean isAnyNeighborsLoaded() { +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + BlockState iblockdata = this.getBlockState(blockposition); + BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.level, blockposition); + +- this.level.setBlock(blockposition, iblockdata1, 20); ++ this.level.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here + } + + this.postProcessing[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 @@ public class CraftWorld implements World { + // Spigot start + @Override + public int getViewDistance() { +- return world.spigotConfig.viewDistance; ++ return getHandle().getChunkSource().chunkMap.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]"); ++ } ++ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ if (viewDistance != chunkMap.getEffectiveViewDistance()) { ++ chunkMap.setViewDistance(viewDistance); ++ } ++ } ++ ++ @Override ++ public int getNoTickViewDistance() { ++ return getHandle().getChunkSource().chunkMap.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]"); ++ } ++ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ 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 @@ 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( ( ((net.minecraft.server.level.ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance + + for ( Player player : world.players() ) + { diff --git a/Spigot-Server-Patches/Ocelot-despawns-should-honor-nametags-and-leash.patch b/patches/server/Ocelot-despawns-should-honor-nametags-and-leash.patch similarity index 56% rename from Spigot-Server-Patches/Ocelot-despawns-should-honor-nametags-and-leash.patch rename to patches/server/Ocelot-despawns-should-honor-nametags-and-leash.patch index d6c6fdbd13..6c1a88feed 100644 --- a/Spigot-Server-Patches/Ocelot-despawns-should-honor-nametags-and-leash.patch +++ b/patches/server/Ocelot-despawns-should-honor-nametags-and-leash.patch @@ -4,16 +4,16 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java b/src/main/java/net/minecraft/world/entity/animal/Ocelot.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 { +--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java +@@ -0,0 +0,0 @@ public class Ocelot extends Animal { @Override - public boolean isTypeNotPersistent(double d0) { + public boolean removeWhenFarAway(double distanceSquared) { - 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() { + public static AttributeSupplier.Builder createAttributes() { diff --git a/Spigot-Server-Patches/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch similarity index 69% rename from Spigot-Server-Patches/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch rename to patches/server/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch index b8bc848766..149610d8a3 100644 --- a/Spigot-Server-Patches/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ b/patches/server/Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch @@ -21,9 +21,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + private void preventMovingIntoUnloadedChunks() { + preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); } - ++ + public boolean countAllMobsForSpawning = false; + private void countAllMobsForSpawning() { + countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); @@ -33,25 +34,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.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(); +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + MobCategory enumcreaturetype = entity.getType().getCategory(); - if (enumcreaturetype != EnumCreatureType.MISC) { + if (enumcreaturetype != MobCategory.MISC) { + // Paper start - Only count natural spawns -+ if (!entity.world.paperConfig.countAllMobsForSpawning && ++ if (!entity.level.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); + BlockPos blockposition = entity.blockPosition(); + long j = ChunkPos.asLong(SectionPos.blockToSectionCoord(blockposition.getX()), SectionPos.blockToSectionCoord(blockposition.getZ())); diff --git a/patches/server/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch new file mode 100644 index 0000000000..bdf4d6c2b8 --- /dev/null +++ b/patches/server/Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch @@ -0,0 +1,95 @@ +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 ReentrantBlockableEventLoop 0; // Paper + + this.profiler.push(() -> { + return worldserver + " " + worldserver.dimension().location(); +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + private int tickPosition; + public final LevelStorageSource.LevelStorageAccess convertable; + public final UUID uuid; ++ public boolean hasPhysicsEvent = true; // Paper + + @Override public LevelChunk getChunkIfLoaded(int x, int z) { // Paper - this was added in world too but keeping here for NMS ABI + return this.chunkSource.getChunk(x, z, false); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit start + iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam + CraftWorld world = ((ServerLevel) this).getWorld(); +- if (world != null) { ++ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); + this.getCraftServer().getPluginManager().callEvent(event); + +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + // CraftBukkit start + CraftWorld world = ((ServerLevel) this).getWorld(); +- if (world != null) { ++ if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper + BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(iblockdata), world.getBlockAt(neighborPos.getX(), neighborPos.getY(), neighborPos.getZ())); + this.getCraftServer().getPluginManager().callEvent(event); + +diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BushBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java +@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; +@@ -0,0 +0,0 @@ public class BushBlock extends Block { + public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { + // CraftBukkit start + if (!state.canSurvive(world, pos)) { +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { ++ if (!(world instanceof ServerLevel && ((ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper + return Blocks.AIR.defaultBlockState(); + } + } +diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +@@ -0,0 +0,0 @@ import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.util.Mth; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; +@@ -0,0 +0,0 @@ public class DoublePlantBlock extends BushBlock { + + protected static void preventCreativeDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) { + // CraftBukkit start +- if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { ++ if (((ServerLevel)world).hasPhysicsEvent && org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper + return; + } + // CraftBukkit end diff --git a/Spigot-Server-Patches/Only-refresh-abilities-if-needed.patch b/patches/server/Only-refresh-abilities-if-needed.patch similarity index 69% rename from Spigot-Server-Patches/Only-refresh-abilities-if-needed.patch rename to patches/server/Only-refresh-abilities-if-needed.patch index 7a8b95aef3..e991d4f899 100644 --- a/Spigot-Server-Patches/Only-refresh-abilities-if-needed.patch +++ b/patches/server/Only-refresh-abilities-if-needed.patch @@ -12,14 +12,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void setFlying(boolean value) { -+ boolean needsUpdate = getHandle().abilities.isFlying != value; // Paper - Only refresh abilities if needed - if (!getAllowFlight() && value) { ++ boolean needsUpdate = getHandle().getAbilities().flying != value; // Paper - Only refresh abilities if needed + if (!this.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 + this.getHandle().getAbilities().flying = value; +- this.getHandle().onUpdateAbilities(); ++ if (needsUpdate) this.getHandle().onUpdateAbilities(); // Paper - Only refresh abilities if needed } @Override diff --git a/Spigot-Server-Patches/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch b/patches/server/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch similarity index 55% rename from Spigot-Server-Patches/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch rename to patches/server/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch index e414bb728e..e7fe5a3b28 100644 --- a/Spigot-Server-Patches/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch +++ b/patches/server/Only-send-Dragon-Wither-Death-sounds-to-same-world.patch @@ -5,35 +5,35 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.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()) { +--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java ++++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java +@@ -0,0 +0,0 @@ public class EnderDragon extends Mob implements Enemy { + if (this.dragonDeathTime == 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 = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; +- for (net.minecraft.server.level.ServerPlayer player : this.level.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 (net.minecraft.server.level.EntityPlayer player : (List) ((WorldServer)world).getPlayers()) { ++ for (net.minecraft.server.level.ServerPlayer player : (List) ((ServerLevel)level).players()) { + final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); 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 +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.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 { +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -0,0 +0,0 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob 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 = ((ServerLevel) this.level).getCraftServer().getViewDistance() * 16; +- for (ServerPlayer 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()) { ++ for (ServerPlayer player : (List)this.level.players()) { + final int viewDistance = player.getViewDistance(); // TODO apply view distance api patch - double deltaX = this.locX() - player.locX(); - double deltaZ = this.locZ() - player.locZ(); + double deltaX = this.getX() - player.getX(); + double deltaZ = this.getZ() - player.getZ(); double distanceSquared = deltaX * deltaX + deltaZ * deltaZ; diff --git a/patches/server/Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch b/patches/server/Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch new file mode 100644 index 0000000000..afa74a6379 --- /dev/null +++ b/patches/server/Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch @@ -0,0 +1,58 @@ +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/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType 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(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType 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(EntityType.getKey(this).getPath()); + if (type != null) { +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + } + // Paper end + T t0 = this.create(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/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java +@@ -0,0 +0,0 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill + + public WanderingTrader(EntityType type, Level world) { + super(type, world); +- 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/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java ++++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +@@ -0,0 +0,0 @@ public class WanderingTraderSpawner implements CustomSpawner { + return false; + } + +- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawnCreature(world, (CompoundTag) null, (Component) null, (Player) null, blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit ++ WanderingTrader entityvillagertrader = EntityType.WANDERING_TRADER.spawnCreature(world, null, null, null, blockposition2, MobSpawnType.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/patches/server/Optimise-ArraySetSorted-removeIf.patch similarity index 54% rename from Spigot-Server-Patches/Optimise-ArraySetSorted-removeIf.patch rename to patches/server/Optimise-ArraySetSorted-removeIf.patch index 127972a778..1fbcab69d8 100644 --- a/Spigot-Server-Patches/Optimise-ArraySetSorted-removeIf.patch +++ b/patches/server/Optimise-ArraySetSorted-removeIf.patch @@ -5,31 +5,20 @@ 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 +diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.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 { +--- a/src/main/java/net/minecraft/util/SortedArraySet.java ++++ b/src/main/java/net/minecraft/util/SortedArraySet.java +@@ -0,0 +0,0 @@ public class SortedArraySet extends AbstractSet { + this.contents = (T[])castRawArray(new Object[initialCapacity]); } } - + // 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(); ++ int i = 0, len = this.size; ++ T[] backingArray = this.contents; + + for (;;) { + if (i >= len) { @@ -55,11 +44,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // cleanup end + Arrays.fill(backingArray, lastIndex, len, null); -+ this.setSize(lastIndex); ++ this.size = lastIndex; + return true; + } + // Paper end - optimise removeIf -+ - public static > ArraySetSorted a(int i) { - return new ArraySetSorted<>(i, (Comparator)Comparator.naturalOrder()); // Paper - decompile fix - } + + public static > SortedArraySet create() { + return create(10); diff --git a/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch b/patches/server/Optimise-BlockState-s-hashCode-equals.patch similarity index 50% rename from Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch rename to patches/server/Optimise-BlockState-s-hashCode-equals.patch index cc23459ed0..0e4c1cd8d5 100644 --- a/Spigot-Server-Patches/Optimise-BlockState-s-hashCode-equals.patch +++ b/patches/server/Optimise-BlockState-s-hashCode-equals.patch @@ -8,12 +8,12 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.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(); +--- a/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/BooleanProperty.java +@@ -0,0 +0,0 @@ public class BooleanProperty extends Property { + return value.toString(); } - @Override @@ -21,13 +21,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + } else if (object instanceof BooleanProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.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(); +--- a/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/EnumProperty.java +@@ -0,0 +0,0 @@ public class EnumProperty & StringRepresentable> extends Prope + return value.getSerializedName(); } - @Override @@ -35,13 +35,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + } else if (object instanceof EnumProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.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; +--- a/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/IntegerProperty.java +@@ -0,0 +0,0 @@ public class IntegerProperty extends Property { + return this.values; } - @Override @@ -49,36 +49,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + } else if (object instanceof IntegerProperty && super.equals(object)) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java b/src/main/java/net/minecraft/world/level/block/state/properties/Property.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> { - } +--- a/src/main/java/net/minecraft/world/level/block/state/properties/Property.java ++++ b/src/main/java/net/minecraft/world/level/block/state/properties/Property.java +@@ -0,0 +0,0 @@ public abstract class Property> { + @Override public boolean equals(Object object) { - if (this == object) { - return true; -- } else if (!(object instanceof IBlockState)) { +- } else if (!(object instanceof Property)) { - return false; - } else { -- IBlockState iblockstate = (IBlockState) object; -- -- return this.a.equals(iblockstate.a) && this.b.equals(iblockstate.b); +- Property property = (Property)object; +- return this.clazz.equals(property.clazz) && this.name.equals(property.name); - } -+ return this == object; // Paper - only one instance per configuration ++ return this == object; } -+ 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() { + @Override diff --git a/patches/server/Optimise-Chunk-getFluid.patch b/patches/server/Optimise-Chunk-getFluid.patch new file mode 100644 index 0000000000..6e3f02463f --- /dev/null +++ b/patches/server/Optimise-Chunk-getFluid.patch @@ -0,0 +1,63 @@ +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/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + } + + public FluidState getFluidState(int x, int y, int z) { +- try { +- int l = this.getSectionIndex(y); +- +- if (l >= 0 && l < this.sections.length) { +- LevelChunkSection chunksection = this.sections[l]; +- +- if (!LevelChunkSection.isEmpty(chunksection)) { +- return chunksection.getFluidState(x & 15, y & 15, z & 15); ++ // try { // Paper - remove try catch ++ // Paper start - reduce the number of ops in this call ++ int index = this.getSectionIndex(y); ++ if (index >= 0 && index < this.sections.length) { ++ LevelChunkSection chunksection = this.sections[index]; ++ ++ if (chunksection != null) { ++ return chunksection.states.get((y & 15) << 8 | (z & 15) << 4 | x & 15).getFluidState(); + } ++ // Paper end + } + + return Fluids.EMPTY.defaultFluidState(); ++ /* // Paper - remove try catch + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got"); +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + }); + throw new ReportedException(crashreport); + } ++ */ // Paper - remove try catch + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -0,0 +0,0 @@ public class LevelChunkSection { + } + + public FluidState getFluidState(int x, int y, int z) { +- return this.states.get(x, y, z).getFluidState(); ++ return this.states.get(x, y, z).getFluidState(); // 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 acquire() { diff --git a/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch new file mode 100644 index 0000000000..1284311196 --- /dev/null +++ b/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch @@ -0,0 +1,26 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; + // Paper end + ++ // Paper start - optimise getPlayerByUUID ++ @Nullable ++ @Override ++ public Player getPlayerByUUID(UUID uuid) { ++ return this.getServer().getPlayerList().getPlayer(uuid); ++ } ++ // Paper end ++ + // Add env and gen to constructor, WorldData -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error diff --git a/Spigot-Server-Patches/Optimise-TickListServer-by-rewriting-it.patch b/patches/server/Optimise-TickListServer-by-rewriting-it.patch similarity index 50% rename from Spigot-Server-Patches/Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/Optimise-TickListServer-by-rewriting-it.patch index 490d3eac81..0960ce08fc 100644 --- a/Spigot-Server-Patches/Optimise-TickListServer-by-rewriting-it.patch +++ b/patches/server/Optimise-TickListServer-by-rewriting-it.patch @@ -69,13 +69,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import java.util.function.Function; +import net.minecraft.CrashReport; -+import net.minecraft.CrashReportSystemDetails; ++import net.minecraft.CrashReportCategory; +import net.minecraft.ReportedException; -+import net.minecraft.core.BlockPosition; -+import net.minecraft.nbt.NBTTagList; -+import net.minecraft.resources.MinecraftKey; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MCUtil; +import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.ChunkPos; ++import net.minecraft.world.level.ServerTickList; ++import net.minecraft.world.level.TickNextTickData; ++import net.minecraft.world.level.TickPriority; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.levelgen.structure.BoundingBox; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; @@ -87,16 +95,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 ++public final class PaperTickList extends ServerTickList { // extend to avoid breaking ABI + + // in the order the state is expected to change (mostly) + public static final int STATE_UNSCHEDULED = 1 << 0; @@ -108,11 +108,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds + -+ private final WorldServer world; ++ private final ServerLevel world; + private final Predicate excludeFromScheduling; -+ private final Function getMinecraftKeyFrom; ++ private final Function getMinecraftKeyFrom; + //private final Function getObjectFronMinecraftKey; -+ private final Consumer> tickFunction; ++ private final Consumer> tickFunction; + + private final co.aikar.timings.Timing timingCleanup; // Paper + private final co.aikar.timings.Timing timingTicking; // Paper @@ -120,14 +120,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // 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); ++ 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 ObjectRBTreeSet> longScheduled = new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); + -+ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); ++ private final ArrayDeque> toTickThisTick = new ArrayDeque<>(); + + private final TickListServerInterval[] shortScheduled = new TickListServerInterval[SHORT_SCHEDULE_TICK_THRESHOLD]; + { @@ -153,8 +153,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return next < length ? next : 0; + } + -+ public PaperTickList(final WorldServer world, final Predicate excludeFromScheduling, final Function getMinecraftKeyFrom, -+ final Consumer> tickFunction, final String timingsType) { ++ public PaperTickList(final ServerLevel 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; @@ -163,12 +163,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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(); ++ this.currentTick = this.world.getGameTime(); + } + -+ private void queueEntryForTick(final NextTickListEntry entry, final ChunkProviderServer chunkProvider) { ++ private void queueEntryForTick(final TickNextTickData entry, final ServerChunkCache chunkProvider) { + if (entry.tickState == STATE_SCHEDULED) { -+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) { ++ if (chunkProvider.isTickingReadyMainThread(entry.pos)) { + this.toTickThisTick.add(entry); + entry.tickState = STATE_PENDING_TICK; + } else { @@ -178,14 +178,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private void addToNotTickingReady(final NextTickListEntry entry) { -+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> { ++ private void addToNotTickingReady(final TickNextTickData entry) { ++ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (long keyInMap) -> { + return new ArrayList<>(); + }).add(entry); + } + -+ private void addToSchedule(final NextTickListEntry entry) { -+ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ private void addToSchedule(final TickNextTickData entry) { ++ long delay = entry.triggerTick - (this.currentTick + 1); + if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) { + if (delay < 0) { + // longScheduled orders by tick time, short scheduled does not @@ -198,14 +198,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private void removeEntry(final NextTickListEntry entry) { ++ private void removeEntry(final TickNextTickData entry) { + entry.tickState = STATE_CANCELLED_TICK; + // short/long scheduled will skip the entry + -+ final BlockPosition pos = entry.getPosition(); ++ final BlockPos pos = entry.pos; + final long blockKey = MCUtil.getBlockKey(pos); + -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); + + if (currentEntries.size() == 1) { + // it should contain our entry @@ -213,7 +213,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } 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); ++ final TickNextTickData currentEntry = currentEntries.get(i); + if (currentEntry == entry) { + currentEntries.remove(i); + break; @@ -221,9 +221,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + + set.remove(entry); + @@ -231,7 +231,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.entriesByChunk.remove(chunkKey); + } + -+ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); ++ ArrayList> pendingTickingLoad = this.pendingChunkTickLoad.get(chunkKey); + + if (pendingTickingLoad != null) { + for (int i = 0, len = pendingTickingLoad.size(); i < len; ++i) { @@ -246,20 +246,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ long delay = entry.getTargetTick() - (this.currentTick + 1); ++ long delay = entry.triggerTick - (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)); ++ 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); ++ final TickNextTickData entry = pending.get(i); + // already in all the relevant reference maps, just need to add to longScheduled or shortScheduled + this.addToSchedule(entry); + } @@ -268,17 +268,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private void prepare() { + final long currentTick = this.currentTick; + -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); ++ final ServerChunkCache chunkProvider = this.world.getChunkSource(); + + // 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) { ++ if (this.longScheduled.isEmpty() || this.longScheduled.first().triggerTick > 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();) { ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { + this.queueEntryForTick(iterator.next(), chunkProvider); + } + } @@ -286,13 +286,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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(); ++ final Comparator> comparator = (Comparator)TickListServerInterval.ENTRY_COMPARATOR; ++ final Iterator> longScheduledIterator = this.longScheduled.iterator(); ++ TickNextTickData 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(); ++ for (final Iterator> iterator = interval.byPriority[i].iterator(); iterator.hasNext();) { ++ final TickNextTickData shortCurrent = iterator.next(); + if (longCurrent != null) { + // drain longCurrent until we can add shortCurrent + while (comparator.compare(longCurrent, shortCurrent) <= 0) { @@ -300,7 +300,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + longScheduledIterator.remove(); + if (longScheduledIterator.hasNext()) { + longCurrent = longScheduledIterator.next(); -+ if (longCurrent.getTargetTick() > currentTick) { ++ if (longCurrent.triggerTick > currentTick) { + longCurrent = null; + break; + } @@ -316,7 +316,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // add remaining from long scheduled + for (;;) { -+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) { ++ if (longCurrent == null || longCurrent.triggerTick > currentTick) { + break; + } + longScheduledIterator.remove(); @@ -336,10 +336,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public void nextTick() { + ++this.currentTick; -+ if (this.currentTick != this.world.getTime()) { ++ if (this.currentTick != this.world.getGameTime()) { + 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("World tick desync detected! Expected " + this.currentTick + " ticks, but got " + this.world.getGameTime() + " ticks for world '" + this.world.getWorld().getName() + "'", new Throwable()); + MinecraftServer.LOGGER.error("Preventing redstone from breaking by refusing to accept new tick time"); + } + } @@ -347,9 +347,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public void tick() { -+ final ChunkProviderServer chunkProvider = this.world.getChunkProvider(); ++ final ServerChunkCache chunkProvider = this.world.getChunkSource(); + -+ this.world.getMethodProfiler().enter("cleaning"); ++ this.world.getProfiler().push("cleaning"); + this.timingCleanup.startTiming(); + + this.prepare(); @@ -359,16 +359,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.shortScheduledIndex = getNextIndex(this.shortScheduledIndex, SHORT_SCHEDULE_TICK_THRESHOLD); + + this.timingCleanup.stopTiming(); -+ this.world.getMethodProfiler().exitEnter("ticking"); ++ this.world.getProfiler().popPush("ticking"); + this.timingTicking.startTiming(); + -+ for (final NextTickListEntry toTick : this.toTickThisTick) { ++ for (final TickNextTickData toTick : this.toTickThisTick) { + if (toTick.tickState != STATE_PENDING_TICK) { + // onTickEnd gets called at end of tick + continue; + } + try { -+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) { ++ if (chunkProvider.isTickingReadyMainThread(toTick.pos)) { + toTick.tickState = STATE_TICKING; + this.tickFunction.accept(toTick); + if (toTick.tickState == STATE_TICKING) { @@ -381,22 +381,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } 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"); ++ CrashReport crashreport = CrashReport.forThrowable(thr, "Exception while ticking"); ++ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being ticked"); + -+ CrashReportSystemDetails.a(crashreportsystemdetails, toTick.getPosition(), (IBlockData) null); ++ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.world, toTick.pos, (BlockState) null); + throw new ReportedException(crashreport); + // end copy from TickListServer + } + } + + this.timingTicking.stopTiming(); -+ this.world.getMethodProfiler().exit(); ++ this.world.getProfiler().pop(); + 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(); ++ final TickNextTickData 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 @@ -407,16 +407,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.timingFinished.stopTiming(); + } + -+ private void onTickEnd(final NextTickListEntry entry) { ++ private void onTickEnd(final TickNextTickData entry) { + if (entry.tickState == STATE_CANCELLED_TICK) { + return; + } + entry.tickState = STATE_UNSCHEDULED; + -+ final BlockPosition pos = entry.getPosition(); ++ final BlockPos pos = entry.pos; + final long blockKey = MCUtil.getBlockKey(pos); + -+ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); ++ final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); + + if (currentEntries.size() == 1) { + // it should contain our entry @@ -424,7 +424,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } 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); ++ final TickNextTickData currentEntry = currentEntries.get(i); + if (currentEntry == entry) { + currentEntries.remove(i); + break; @@ -432,9 +432,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + -+ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); ++ ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + + set.remove(entry); + @@ -446,16 +446,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public boolean isPendingTickThisTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ public boolean willTickThisTick(final BlockPos 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) { ++ final TickNextTickData entry = entries.get(i); ++ if (entry.getType() == data && entry.tickState == STATE_PENDING_TICK) { + return true; + } + } @@ -464,16 +464,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public boolean isScheduledForTick(final BlockPosition blockposition, final T data) { -+ final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); ++ public boolean hasScheduledTick(final BlockPos 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) { ++ final TickNextTickData entry = entries.get(i); ++ if (entry.getType() == data && entry.tickState == STATE_SCHEDULED) { + return true; + } + } @@ -482,22 +482,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public void schedule(BlockPosition blockPosition, T t, int i, TickListPriority tickListPriority) { ++ public void scheduleTick(BlockPos blockPosition, T t, int i, TickPriority 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 TickNextTickData entry) { ++ this.schedule(entry.pos, entry.getType(), entry.triggerTick, entry.priority); + } + -+ 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())) { ++ public void schedule(final BlockPos pos, final T data, final long targetTick, final TickPriority priority) { ++ final TickNextTickData entry = new TickNextTickData<>(pos, data, targetTick, priority); ++ if (this.excludeFromScheduling.test(entry.getType())) { + return; + } + + if (WARN_ON_EXCESSIVE_DELAY) { -+ final long delay = entry.getTargetTick() - this.currentTick; ++ final long delay = entry.triggerTick - this.currentTick; + if (delay >= EXCESSIVE_DELAY_THRESHOLD) { + MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); + } @@ -505,16 +505,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + final long blockKey = MCUtil.getBlockKey(pos); + -+ final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); ++ 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); ++ final TickNextTickData 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) { ++ if (currentEntry.getType() == entry.getType() && currentEntry.tickState == STATE_SCHEDULED) { + // can't add + return; + } @@ -524,14 +524,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + entry.tickState = STATE_SCHEDULED; + -+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> { ++ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (final long keyInMap) -> { + return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR); + }).add(entry); + + this.addToSchedule(entry); + } + -+ public void scheduleAll(final Iterator> iterator) { ++ public void scheduleAll(final Iterator> iterator) { + while (iterator.hasNext()) { + this.schedule(iterator.next()); + } @@ -540,25 +540,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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(); ++ private static boolean isBlockInSortof(final BoundingBox boundingBox, final BlockPos pos) { ++ return pos.getX() >= boundingBox.minX() && pos.getX() < boundingBox.maxX() && pos.getZ() >= boundingBox.minZ() && pos.getZ() < boundingBox.maxZ(); + } + + @Override -+ public List> getEntriesInBoundingBox(final StructureBoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { ++ public List> fetchTicksInArea(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { ++ if (structureboundingbox.minX() == structureboundingbox.maxX() || structureboundingbox.minZ() == structureboundingbox.maxZ()) { + 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 lowerChunkX = structureboundingbox.minX() >> 4; ++ final int upperChunkX = (structureboundingbox.maxX() - 1) >> 4; // subtract 1 since maxX is exclusive ++ final int lowerChunkZ = structureboundingbox.minZ() >> 4; ++ final int upperChunkZ = (structureboundingbox.maxZ() - 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 ObjectRBTreeSet>[] containingChunks = new ObjectRBTreeSet[xChunksLength * zChunksLength]; + + final int offset = (xChunksLength * -lowerChunkZ - lowerChunkX); + int totalEntries = 0; @@ -567,19 +567,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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)); ++ 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 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())) { ++ MCUtil.mergeSortedSets((TickNextTickData entry) -> { ++ if (!isBlockInSortof(structureboundingbox, entry.pos)) { + return; + } + final int tickState = entry.tickState; @@ -592,7 +592,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }, TickListServerInterval.ENTRY_COMPARATOR, containingChunks); + + if (removeReturned) { -+ for (NextTickListEntry entry : ret) { ++ for (TickNextTickData entry : ret) { + this.removeEntry(entry); + } + } @@ -601,40 +601,40 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public void copy(StructureBoundingBox structureboundingbox, BlockPosition blockposition) { ++ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); -+ Iterator> iterator = list.iterator(); ++ List> list = this.fetchTicksInArea(structureboundingbox, false, false); ++ Iterator> iterator = list.iterator(); + + while (iterator.hasNext()) { -+ NextTickListEntry nextticklistentry = iterator.next(); ++ TickNextTickData nextticklistentry = iterator.next(); + -+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) { -+ BlockPosition blockposition1 = nextticklistentry.getPosition().add(blockposition); -+ T t0 = nextticklistentry.getData(); ++ if (structureboundingbox.isInside( nextticklistentry.pos)) { ++ BlockPos blockposition1 = nextticklistentry.pos.offset(blockposition); ++ T t0 = nextticklistentry.getType(); + -+ this.schedule(new NextTickListEntry<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority())); ++ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority)); + } + } + // end copy from TickListServer + } + + @Override -+ public List> getEntriesInChunk(ChunkCoordIntPair chunkPos, boolean removeReturned, boolean excludeTicked) { ++ public List> fetchTicksInChunk(ChunkPos 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)); ++ final ObjectRBTreeSet> entries = this.entriesByChunk.get(MCUtil.getCoordinateKey(chunkPos)); + + if (entries == null) { + return Collections.emptyList(); + } + -+ final List> ret = new ArrayList<>(entries.size()); ++ final List> ret = new ArrayList<>(entries.size()); + -+ for (NextTickListEntry entry : entries) { ++ for (TickNextTickData entry : entries) { + if ((entry.tickState & matchOne) == 0) { + continue; + } @@ -642,7 +642,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + if (removeReturned) { -+ for (NextTickListEntry entry : ret) { ++ for (TickNextTickData entry : ret) { + this.removeEntry(entry); + } + } @@ -651,29 +651,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public NBTTagList serialize(ChunkCoordIntPair chunkcoordintpair) { ++ public ListTag save(ChunkPos chunkcoordintpair) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); ++ List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); + -+ return TickListServer.serialize(this.getMinecraftKeyFrom, list, this.currentTick); ++ return ServerTickList.saveTickList(this.getMinecraftKeyFrom, list, this.currentTick); + // end copy from TickListServer + } + + @Override -+ public int getTotalScheduledEntries() { ++ public int size() { + // good thing this is only used in debug reports // TODO check on update + int ret = 0; + -+ for (NextTickListEntry entry : this.longScheduled) { ++ for (TickNextTickData entry : this.longScheduled) { + if (entry.tickState == STATE_SCHEDULED) { + ++ret; + } + } + -+ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { -+ ArrayList> list = iterator.next().getValue(); ++ for (Iterator>>> iterator = this.pendingChunkTickLoad.long2ObjectEntrySet().iterator(); iterator.hasNext();) { ++ ArrayList> list = iterator.next().getValue(); + -+ for (NextTickListEntry entry : list) { ++ for (TickNextTickData entry : list) { + if (entry.tickState == STATE_SCHEDULED) { + ++ret; + } @@ -681,8 +681,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + for (TickListServerInterval interval : this.shortScheduled) { -+ for (Iterable> set : interval.byPriority) { -+ for (NextTickListEntry entry : set) { ++ for (Iterable> set : interval.byPriority) { ++ for (TickNextTickData entry : set) { + if (entry.tickState == STATE_SCHEDULED) { + ++ret; + } @@ -703,22 +703,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import com.destroystokyo.paper.util.set.LinkedSortedSet; +import java.util.Comparator; -+import net.minecraft.world.level.NextTickListEntry; -+import net.minecraft.world.level.TickListPriority; ++import net.minecraft.world.level.TickNextTickData; ++import net.minecraft.world.level.TickPriority; + +// 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) -> { ++ public static final int TOTAL_PRIORITIES = TickPriority.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(); ++ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.createTimeComparator(); + + // 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]; ++ public final LinkedSortedSet>[] byPriority = new LinkedSortedSet[TOTAL_PRIORITIES]; + + { + for (int i = 0, len = this.byPriority.length; i < len; ++i) { @@ -726,12 +726,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ public void addEntryLast(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); ++ public void addEntryLast(final TickNextTickData entry) { ++ this.byPriority[entry.priority.ordinal()].addLast(entry); + } + -+ public void addEntryFirst(final NextTickListEntry entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); ++ public void addEntryFirst(final TickNextTickData entry) { ++ this.byPriority[entry.priority.ordinal()].addFirst(entry); + } + + public void clear() { @@ -888,380 +888,225 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } +} -diff --git a/src/main/java/net/minecraft/core/BlockPosition.java b/src/main/java/net/minecraft/core/BlockPosition.java +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.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); +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + return null; } + // Paper end - no-tick view distance ++ // Paper start ++ public final boolean isEntityTickingReady() { ++ return this.isEntityTickingReady; ++ } ++ ++ public final boolean isTickingReady() { ++ return this.isTickingReady; ++ } ++ ++ public final boolean isFullChunkReady() { ++ return this.isFullChunkReady; ++ } ++ // Paper end -+ 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 + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +@@ -0,0 +0,0 @@ public class ChunkHolder { + either.ifLeft(chunk -> { + // note: Here is a very good place to add callbacks to logic waiting on this. + ChunkHolder.this.isTickingReady = true; ++ ++ // Paper start - rewrite ticklistserver ++ ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z); ++ // Paper end - rewrite ticklistserver + }); + }); + // Paper end +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.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 { +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + }, this.mainThreadProcessor); } // Paper end - + // Paper start - rewrite ticklistserver -+ public final boolean isTickingReadyMainThread(BlockPosition pos) { -+ PlayerChunk chunk = this.playerChunkMap.getUpdatingChunk(MCUtil.getCoordinateKey(pos)); ++ public final boolean isTickingReadyMainThread(BlockPos pos) { ++ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(net.minecraft.server.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 + + public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier supplier) { + this.level = world; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 { +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } // 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); ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.blockTicks).onChunkSetTicking(chunkX, chunkZ); ++ ((com.destroystokyo.paper.server.ticklist.PaperTickList) this.liquidTicks).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 + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + DefaultedRegistry registryblocks = Registry.BLOCK; + + Objects.requireNonNull(registryblocks); +- this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings ++ // this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings // Paper - copied down + Predicate predicate2 = (fluidtype) -> { // CraftBukkit - decompile error + return fluidtype == null || fluidtype == Fluids.EMPTY; + }; + registryblocks = Registry.FLUID; + Objects.requireNonNull(registryblocks); + 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 ++ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings ++ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "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.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings & copied from above + this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // CraftBukkit - decompile error // 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.navigatingMobs = new ObjectOpenHashSet(); + this.blockEvents = new ObjectLinkedOpenHashSet(); + this.dragonParts = new Int2ObjectOpenHashMap(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + if (this.tickTime) { + long i = this.levelData.getGameTime() + 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 +- this.serverLevelData.setGameTime(i); ++ this.serverLevelData.setGameTime(i); ; // Paper - diff on change, we want the below to be ran right after this ++ this.blockTicks.nextTick(); // Paper ++ this.liquidTicks.nextTick(); // Paper + this.serverLevelData.getScheduledEvents().tick(this.server, i); + if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + this.setDayTime(this.levelData.getDayTime() + 1L); +diff --git a/src/main/java/net/minecraft/world/level/ChunkTickList.java b/src/main/java/net/minecraft/world/level/ChunkTickList.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 { +--- a/src/main/java/net/minecraft/world/level/ChunkTickList.java ++++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java +@@ -0,0 +0,0 @@ public class ChunkTickList implements TickList { - 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 ChunkTickList(Function identifierProvider, List> scheduledTicks, long startTime) { + this(identifierProvider, scheduledTicks.stream().map((tickNextTickData) -> { +- return new ChunkTickList.ScheduledTick(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority); ++ return new ChunkTickList.ScheduledTick<>(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority); // Paper - decompile error + }).collect(Collectors.toList())); } - 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; +@@ -0,0 +0,0 @@ public class ChunkTickList implements TickList { + return listTag; } + 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(); + public static ChunkTickList create(ListTag ticks, Function function, Function function2) { + 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")))); +@@ -0,0 +0,0 @@ public class ChunkTickList implements TickList { + T object = function2.apply(new ResourceLocation(compoundTag.getString("i"))); + if (object != null) { + BlockPos blockPos = new BlockPos(compoundTag.getInt("x"), compoundTag.getInt("y"), compoundTag.getInt("z")); +- list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, compoundTag.getInt("t"), TickPriority.byValue(compoundTag.getInt("p")))); + // Paper start - clean up broken entries -+ int delay = nbttagcompound.getInt("t"); ++ int delay = compoundTag.getInt("t"); + if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) { -+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay); ++ net.minecraft.server.MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockPos + ", tick delay " + delay); + continue; + } -+ list.add(new TickListChunk.a<>(t0, blockposition, delay, TickListPriority.a(nbttagcompound.getInt("p")))); + // Paper end - clean up broken entries ++ list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, delay, TickPriority.byValue(compoundTag.getInt("p")))); } } -diff --git a/src/main/java/net/minecraft/world/level/TickListServer.java b/src/main/java/net/minecraft/world/level/TickListServer.java +diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.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 { +--- a/src/main/java/net/minecraft/world/level/ServerTickList.java ++++ b/src/main/java/net/minecraft/world/level/ServerTickList.java +@@ -0,0 +0,0 @@ public class ServerTickList 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(); + public void tick() { + int i = this.tickNextTickList.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)); +@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { + return ServerTickList.saveTickList(this.toId, list, this.level.getGameTime()); } - 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 { - } +- private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { ++ public static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { // Paper - private -> public + ListTag nbttaglist = new ListTag(); + Iterator iterator = scheduledTicks.iterator(); - 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 +diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.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; +--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java ++++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java +@@ -0,0 +0,0 @@ public class TickNextTickData { + public final BlockPos pos; + public final long triggerTick; + public final TickPriority priority; +- private final long c; ++ private final long c; @Deprecated public final long getId() { return this.c; } // Paper - OBFHELPER ++ private final int hash; // Paper ++ public int tickState; // Paper - 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 TickNextTickData(BlockPos pos, T t) { + this(pos, t, 0L, TickPriority.NORMAL); +@@ -0,0 +0,0 @@ public class TickNextTickData { + this.type = t; + this.triggerTick = time; + this.priority = priority; ++ this.hash = this.computeHash(); // Paper } -+ 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()); + @Override +@@ -0,0 +0,0 @@ public class TickNextTickData { + + @Override + public int hashCode() { ++ // Paper start - optimize hashcode ++ return this.hash; ++ } ++ public final int computeHash() { ++ // Paper end - optimize hashcode + return this.pos.hashCode(); } -+ 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; + public static Comparator> createTimeComparator() { +- return Comparator.>comparingLong((tickNextTickData) -> { // Paper - decompile fix +- return tickNextTickData.triggerTick; +- }).thenComparing((tickNextTickData) -> { +- return tickNextTickData.priority; +- }).thenComparingLong((tickNextTickData) -> { +- return tickNextTickData.c; +- }); ++ // Paper start - let's not use more functional code for no reason. ++ return (Comparator) (Comparator) (TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { ++ int i = Long.compare(nextticklistentry.triggerTick, nextticklistentry1.triggerTick); ++ ++ if (i != 0) { ++ return i; ++ } else { ++ i = nextticklistentry.priority.compareTo(nextticklistentry1.priority); ++ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId()); ++ } ++ }; ++ // Paper end - let's not use more functional code for no reason. } + + @Override diff --git a/patches/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch new file mode 100644 index 0000000000..28344e744c --- /dev/null +++ b/patches/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch @@ -0,0 +1,66 @@ +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/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + return this.getChunk(x, z, leastStatus, create); + }, this.mainThreadProcessor).join(); + } else { ++ // Paper start - optimise for loaded chunks ++ LevelChunk ifLoaded = this.getChunkAtIfLoadedMainThread(x, z); ++ if (ifLoaded != null) { ++ return ifLoaded; ++ } ++ // Paper end + ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + + gameprofilerfiller.incrementCounter("getChunk"); +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + if (Thread.currentThread() != this.mainThread) { + return null; + } else { +- this.level.getProfiler().incrementCounter("getChunkNow"); +- long k = ChunkPos.asLong(chunkX, chunkZ); +- +- for (int l = 0; l < 4; ++l) { +- if (k == this.lastChunkPos[l] && this.lastChunkStatus[l] == ChunkStatus.FULL) { +- ChunkAccess ichunkaccess = this.lastChunk[l]; +- +- return ichunkaccess instanceof LevelChunk ? (LevelChunk) ichunkaccess : null; +- } +- } +- +- ChunkHolder playerchunk = this.getVisibleChunkIfPresent(k); +- +- if (playerchunk == null) { +- return null; +- } else { +- Either either = (Either) playerchunk.getFutureIfPresent(ChunkStatus.FULL).getNow(null); // CraftBukkit - decompile error +- +- if (either == null) { +- return null; +- } else { +- ChunkAccess ichunkaccess1 = (ChunkAccess) either.left().orElse(null); // CraftBukkit - decompile error +- +- if (ichunkaccess1 != null) { +- this.storeInCache(k, ichunkaccess1, ChunkStatus.FULL); +- if (ichunkaccess1 instanceof LevelChunk) { +- return (LevelChunk) ichunkaccess1; +- } +- } +- +- return null; +- } +- } ++ return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - optimise for loaded chunks + } + } + diff --git a/Spigot-Server-Patches/Optimise-getType-calls.patch b/patches/server/Optimise-getType-calls.patch similarity index 68% rename from Spigot-Server-Patches/Optimise-getType-calls.patch rename to patches/server/Optimise-getType-calls.patch index d9da966e5b..8a97a1575d 100644 --- a/Spigot-Server-Patches/Optimise-getType-calls.patch +++ b/patches/server/Optimise-getType-calls.patch @@ -5,15 +5,14 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockState.java b/src/main/java/net/minecraft/world/level/block/state/BlockState.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 { +--- a/src/main/java/net/minecraft/world/level/block/state/BlockState.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockState.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.properties.Property; + public class BlockState extends BlockBehaviour.BlockStateBase { + public static final Codec CODEC = codec(Registry.BLOCK, Block::defaultBlockState).stable(); - public static final Codec b = a((Codec) IRegistry.BLOCK, Block::getBlockData).stable(); - -+ + // Paper start - optimise getType calls + org.bukkit.Material cachedMaterial; + @@ -25,9 +24,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return this.cachedMaterial; + } + // Paper end - optimise getType calls -+ - public IBlockData(Block block, ImmutableMap, Comparable> immutablemap, MapCodec mapcodec) { - super(block, immutablemap, mapcodec); + public BlockState(Block block, ImmutableMap, Comparable> propertyMap, MapCodec codec) { + super(block, propertyMap, codec); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java b/src/main/java/org/bukkit/craftbukkit/CraftChunkSnapshot.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -35,10 +33,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + this.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 +- return CraftMagicNumbers.getMaterial(this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBlock()); ++ return this.blockids[this.getSectionIndex(y)].get(x, y & 0xF, z).getBukkitMaterial(); // Paper - optimise getType calls } @Override @@ -50,8 +48,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Material getType() { -- return CraftMagicNumbers.getMaterial(world.getType(position).getBlock()); -+ return world.getType(position).getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.world.getBlockState(position).getBlock()); ++ return this.world.getBlockState(this.position).getBukkitMaterial(); // Paper - optimise getType calls } @Override @@ -63,8 +61,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Material getType() { -- return CraftMagicNumbers.getMaterial(data.getBlock()); -+ return data.getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.data.getBlock()); ++ return this.data.getBukkitMaterial(); // Paper - optimise getType calls } public void setFlag(int flag) { @@ -76,11 +74,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Material getMaterial() { -- return CraftMagicNumbers.getMaterial(state.getBlock()); -+ return state.getBukkitMaterial(); // Paper - optimise getType calls +- return CraftMagicNumbers.getMaterial(this.state.getBlock()); ++ return this.state.getBukkitMaterial(); // Paper - optimise getType calls } - public IBlockData getState() { + public BlockState 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 @@ -89,8 +87,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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 +- return CraftMagicNumbers.getMaterial(this.getTypeId(x, y, z).getBlock()); ++ return this.getTypeId(x, y, z).getBukkitMaterial(); // Paper - optimise getType calls } @Override diff --git a/patches/server/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch b/patches/server/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch new file mode 100644 index 0000000000..ebf886f2c3 --- /dev/null +++ b/patches/server/Optimize-Biome-Mob-Lookups-for-Mob-Spawning.patch @@ -0,0 +1,57 @@ +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/MobSpawnSettings.java b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java ++++ b/src/main/java/net/minecraft/world/level/biome/MobSpawnSettings.java +@@ -0,0 +0,0 @@ public class MobSpawnSettings { + } + + public static class Builder { +- private final Map> spawners = Stream.of(MobCategory.values()).collect(ImmutableMap.toImmutableMap((mobCategory) -> { ++ // 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(MobSpawnSettings.SpawnerData BiomeSettingsMobs) { ++ biomes.add(BiomeSettingsMobs); ++ return super.add(BiomeSettingsMobs); ++ } ++ ++ @Override ++ public MobSpawnSettings.SpawnerData remove(int index) { ++ MobSpawnSettings.SpawnerData 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> spawners = (Map) Stream.of(MobCategory.values()).collect(Maps.toImmutableEnumMap((mobCategory) -> { + return mobCategory; + }, (mobCategory) -> { +- return Lists.newArrayList(); ++ return new MobList(); // Use MobList instead of ArrayList + })); ++ // Paper end + private final Map, MobSpawnSettings.MobSpawnCost> mobSpawnCosts = Maps.newLinkedHashMap(); + private float creatureGenerationProbability = 0.1F; + private boolean playerCanSpawn; diff --git a/patches/server/Optimize-Bit-Operations-by-inlining.patch b/patches/server/Optimize-Bit-Operations-by-inlining.patch new file mode 100644 index 0000000000..1e6da24bb7 --- /dev/null +++ b/patches/server/Optimize-Bit-Operations-by-inlining.patch @@ -0,0 +1,213 @@ +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/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + }).stable(); + private static final Logger LOGGER = LogManager.getLogger(); + public static final BlockPos ZERO = new BlockPos(0, 0, 0); +- private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000)); +- private static final int PACKED_Z_LENGTH = PACKED_X_LENGTH; +- public static final int PACKED_Y_LENGTH = 64 - PACKED_X_LENGTH - PACKED_Z_LENGTH; +- private static final long PACKED_X_MASK = (1L << PACKED_X_LENGTH) - 1L; +- private static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L; +- private static final long PACKED_Z_MASK = (1L << PACKED_Z_LENGTH) - 1L; +- private static final int Y_OFFSET = 0; +- private static final int Z_OFFSET = PACKED_Y_LENGTH; +- private static final int X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH; ++ // Paper start - static constants ++ private static final int PACKED_X_LENGTH = 26; ++ private static final int PACKED_Z_LENGTH = 26; ++ public static final int PACKED_Y_LENGTH = 12; ++ private static final long PACKED_X_MASK = 67108863; ++ private static final long PACKED_Y_MASK = 4095; ++ private static final long PACKED_Z_MASK = 67108863; ++ private static final int Z_OFFSET = 12; ++ private static final int X_OFFSET = 38; ++ // Paper end + + public BlockPos(int x, int y, int z) { + super(x, y, z); +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + this(pos.getX(), pos.getY(), pos.getZ()); + } + ++ public static long getAdjacent(int baseX, int baseY, int baseZ, Direction enumdirection) { return asLong(baseX + enumdirection.getStepX(), baseY + enumdirection.getStepY(), baseZ + enumdirection.getStepZ()); } // Paper + public static long offset(long value, Direction direction) { + return offset(value, direction.getStepX(), direction.getStepY(), direction.getStepZ()); + } + + public static long offset(long value, int x, int y, int z) { +- return asLong(getX(value) + x, getY(value) + y, getZ(value) + z); ++ return asLong((int) (value >> 38) + x, (int) ((value << 52) >> 52) + y, (int) ((value << 26) >> 38) + z); // Paper - simplify/inline + } + + public static int getX(long packedPos) { +- return (int)(packedPos << 64 - X_OFFSET - PACKED_X_LENGTH >> 64 - PACKED_X_LENGTH); ++ return (int) (packedPos >> 38); // Paper - simplify/inline + } + + public static int getY(long packedPos) { +- return (int)(packedPos << 64 - PACKED_Y_LENGTH >> 64 - PACKED_Y_LENGTH); ++ return (int) ((packedPos << 52) >> 52); // Paper - simplify/inline + } + + public static int getZ(long packedPos) { +- return (int)(packedPos << 64 - Z_OFFSET - PACKED_Z_LENGTH >> 64 - PACKED_Z_LENGTH); ++ return (int) ((packedPos << 26) >> 38); // Paper - simplify/inline + } + + public static BlockPos of(long packedPos) { +- return new BlockPos(getX(packedPos), getY(packedPos), getZ(packedPos)); ++ return new BlockPos((int) (packedPos >> 38), (int) ((packedPos << 52) >> 52), (int) ((packedPos << 26) >> 38)); // Paper - simplify/inline + } + + public long asLong() { +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + } + + public static long asLong(int x, int y, int z) { +- long l = 0L; +- l = l | ((long)x & PACKED_X_MASK) << X_OFFSET; +- l = l | ((long)y & PACKED_Y_MASK) << 0; +- return l | ((long)z & PACKED_Z_MASK) << Z_OFFSET; ++ return (((long) x & (long) 67108863) << 38) | (((long) y & (long) 4095)) | (((long) z & (long) 67108863) << 12); // Paper - inline constants and simplify + } + + public static long getFlatIndex(long y) { +diff --git a/src/main/java/net/minecraft/core/SectionPos.java b/src/main/java/net/minecraft/core/SectionPos.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/SectionPos.java ++++ b/src/main/java/net/minecraft/core/SectionPos.java +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + } + + public static SectionPos of(BlockPos pos) { +- return new SectionPos(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ())); ++ return new SectionPos(pos.getX() >> 4, pos.getY() >> 4, pos.getZ() >> 4); // Paper + } + + public static SectionPos of(ChunkPos chunkPos, int y) { +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + } + + public static SectionPos of(long packed) { +- return new SectionPos(x(packed), y(packed), z(packed)); ++ return new SectionPos((int) (packed >> 42), (int) (packed << 44 >> 44), (int) (packed << 22 >> 42)); // Paper + } + + public static SectionPos bottomOf(ChunkAccess chunk) { +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + return offset(packed, direction.getStepX(), direction.getStepY(), direction.getStepZ()); + } + ++ // Paper start ++ public static long getAdjacentFromBlockPos(int x, int y, int z, Direction enumdirection) { ++ return (((long) ((x >> 4) + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y >> 4) + enumdirection.getStepY()) & 1048575L)) | (((long) ((z >> 4) + enumdirection.getStepZ()) & 4194303L) << 20); ++ } ++ public static long getAdjacentFromSectionPos(int x, int y, int z, Direction enumdirection) { ++ return (((long) (x + enumdirection.getStepX()) & 4194303L) << 42) | (((long) ((y) + enumdirection.getStepY()) & 1048575L)) | (((long) (z + enumdirection.getStepZ()) & 4194303L) << 20); ++ } ++ // Paper end + public static long offset(long packed, int x, int y, int z) { +- return asLong(x(packed) + x, y(packed) + y, z(packed) + z); ++ return (((long) ((int) (packed >> 42) + x) & 4194303L) << 42) | (((long) ((int) (packed << 44 >> 44) + y) & 1048575L)) | (((long) ((int) (packed << 22 >> 42) + z) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static int posToSectionCoord(double coord) { +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + } + + public static short sectionRelativePos(BlockPos pos) { +- int i = sectionRelative(pos.getX()); +- int j = sectionRelative(pos.getY()); +- int k = sectionRelative(pos.getZ()); +- return (short)(i << 8 | k << 4 | j << 0); ++ return (short) ((pos.getX() & 15) << 8 | (pos.getZ() & 15) << 4 | pos.getY() & 15); // Paper - simplify/inline + } + + public static int sectionRelativeX(short packedLocalPos) { +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + return this.getZ(); + } + +- public int minBlockX() { +- return sectionToBlockCoord(this.x()); ++ public final int minBlockX() { // Paper - make final ++ return this.getX() << 4; // Paper - inline + } + +- public int minBlockY() { +- return sectionToBlockCoord(this.y()); ++ public final int minBlockY() { // Paper - make final ++ return this.getY() << 4; // Paper - inline + } + +- public int minBlockZ() { +- return sectionToBlockCoord(this.z()); ++ public int minBlockZ() { // Paper - make final ++ return this.getZ() << 4; // Paper - inline + } + + public int maxBlockX() { +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + } + + public static long blockToSection(long blockPos) { +- return asLong(blockToSectionCoord(BlockPos.getX(blockPos)), blockToSectionCoord(BlockPos.getY(blockPos)), blockToSectionCoord(BlockPos.getZ(blockPos))); ++ // b(a(BlockPosition.b(i)), a(BlockPosition.c(i)), a(BlockPosition.d(i))); ++ return (((long) (int) (blockPos >> 42) & 4194303L) << 42) | (((long) (int) ((blockPos << 52) >> 56) & 1048575L)) | (((long) (int) ((blockPos << 26) >> 42) & 4194303L) << 20); // Simplify to reduce instruction count + } + + public static long getZeroNode(long pos) { +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + return asLong(blockToSectionCoord(pos.getX()), blockToSectionCoord(pos.getY()), blockToSectionCoord(pos.getZ())); + } + ++ // 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 x, int y, int z) { +- long l = 0L; +- l = l | ((long)x & 4194303L) << 42; +- l = l | ((long)y & 1048575L) << 0; +- return l | ((long)z & 4194303L) << 20; ++ return (((long) x & 4194303L) << 42) | (((long) y & 1048575L)) | (((long) z & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + public long asLong() { +- return asLong(this.x(), this.y(), this.z()); ++ return (((long) getX() & 4194303L) << 42) | (((long) getY() & 1048575L)) | (((long) getZ() & 4194303L) << 20); // Paper - Simplify to reduce instruction count + } + + @Override +@@ -0,0 +0,0 @@ public class SectionPos extends Vec3i { + } + + public static Stream cube(SectionPos center, int radius) { +- int i = center.x(); +- int j = center.y(); +- int k = center.z(); +- return betweenClosedStream(i - radius, j - radius, k - radius, i + radius, j + radius, k + radius); ++ return betweenClosedStream(center.getX() - radius, center.getY() - radius, center.getZ() - radius, center.getX() + radius, center.getY() + radius, center.getZ() + radius); // Paper - simplify/inline + } + + public static Stream aroundChunk(ChunkPos center, int radius, int minY, int maxY) { +- int i = center.x; +- int j = center.z; +- return betweenClosedStream(i - radius, minY, j - radius, i + radius, maxY - 1, j + radius); ++ return betweenClosedStream(center.x - radius, 0, center.z - radius, center.x + radius, 15, center.z + radius); // Paper - simplify/inline + } + + public static Stream betweenClosedStream(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { diff --git a/patches/server/Optimize-BlockPosition-helper-methods.patch b/patches/server/Optimize-BlockPosition-helper-methods.patch new file mode 100644 index 0000000000..202a43456c --- /dev/null +++ b/patches/server/Optimize-BlockPosition-helper-methods.patch @@ -0,0 +1,108 @@ +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/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + + @Override + public BlockPos above() { +- return this.relative(Direction.UP); ++ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos above(int distance) { +- return this.relative(Direction.UP, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY() + distance, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos below() { +- return this.relative(Direction.DOWN); ++ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos below(int i) { +- return this.relative(Direction.DOWN, i); ++ return i == 0 ? this : new BlockPos(this.getX(), this.getY() - i, this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos north() { +- return this.relative(Direction.NORTH); ++ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos north(int distance) { +- return this.relative(Direction.NORTH, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() - distance); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos south() { +- return this.relative(Direction.SOUTH); ++ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos south(int distance) { +- return this.relative(Direction.SOUTH, distance); ++ return distance == 0 ? this : new BlockPos(this.getX(), this.getY(), this.getZ() + distance); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos west() { +- return this.relative(Direction.WEST); ++ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos west(int distance) { +- return this.relative(Direction.WEST, distance); ++ return distance == 0 ? this : new BlockPos(this.getX() - distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos east() { +- return this.relative(Direction.EAST); ++ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos east(int distance) { +- return this.relative(Direction.EAST, distance); ++ return distance == 0 ? this : new BlockPos(this.getX() + distance, this.getY(), this.getZ()); // Paper - Optimize BlockPosition + } + + @Override + public BlockPos relative(Direction direction) { ++ // Paper Start - Optimize BlockPosition ++ switch(direction) { ++ case UP: ++ return new BlockPos(this.getX(), this.getY() + 1, this.getZ()); ++ case DOWN: ++ return new BlockPos(this.getX(), this.getY() - 1, this.getZ()); ++ case NORTH: ++ return new BlockPos(this.getX(), this.getY(), this.getZ() - 1); ++ case SOUTH: ++ return new BlockPos(this.getX(), this.getY(), this.getZ() + 1); ++ case WEST: ++ return new BlockPos(this.getX() - 1, this.getY(), this.getZ()); ++ case EAST: ++ return new BlockPos(this.getX() + 1, this.getY(), this.getZ()); ++ default: + return new BlockPos(this.getX() + direction.getStepX(), this.getY() + direction.getStepY(), this.getZ() + direction.getStepZ()); ++ } ++ // Paper End + } + + @Override diff --git a/patches/server/Optimize-Captured-TileEntity-Lookup.patch b/patches/server/Optimize-Captured-TileEntity-Lookup.patch new file mode 100644 index 0000000000..4aa94be0fb --- /dev/null +++ b/patches/server/Optimize-Captured-TileEntity-Lookup.patch @@ -0,0 +1,30 @@ +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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + @Nullable + public BlockEntity getTileEntity(BlockPos blockposition, boolean validate) { +- if (this.capturedTileEntities.containsKey(blockposition)) { +- return this.capturedTileEntities.get(blockposition); ++ // Paper start - Optimize capturedTileEntities lookup ++ net.minecraft.world.level.block.entity.BlockEntity blockEntity; ++ if (!this.capturedTileEntities.isEmpty() && (blockEntity = this.capturedTileEntities.get(blockposition)) != null) { ++ return blockEntity; + } ++ // Paper end + // CraftBukkit end + return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); + } diff --git a/patches/server/Optimize-Collision-to-not-load-chunks.patch b/patches/server/Optimize-Collision-to-not-load-chunks.patch new file mode 100644 index 0000000000..2eb1a719a7 --- /dev/null +++ b/patches/server/Optimize-Collision-to-not-load-chunks.patch @@ -0,0 +1,114 @@ +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 @@ public abstract class PlayerList { + entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + // CraftBukkit end + ++ worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper + while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) { + entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ()); + } +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 Nameable, EntityAccess, CommandSource, n + // Paper end + + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper ++ public boolean collisionLoadChunks = false; // Paper + private CraftEntity bukkitEntity; + + public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper +diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java ++++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java +@@ -0,0 +0,0 @@ public interface CollisionGetter extends BlockGetter { + } + + default boolean noCollision(@Nullable Entity entity, AABB box, Predicate filter) { ++ try { if (entity != null) entity.collisionLoadChunks = true; // Paper + return this.getCollisions(entity, box, filter).allMatch(VoxelShape::isEmpty); ++ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper + } + + Stream getEntityCollisions(@Nullable Entity entity, AABB box, Predicate predicate); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -0,0 +0,0 @@ public class CollisionSpliterator extends AbstractSpliterator { + boolean collisionCheck(Consumer action) { + while(true) { + if (this.cursor.advance()) { +- int i = this.cursor.nextX(); +- int j = this.cursor.nextY(); +- int k = this.cursor.nextZ(); ++ int i = this.cursor.nextX(); final int x = i; ++ int j = this.cursor.nextY(); final int y = j; ++ int k = this.cursor.nextZ(); final int z = k; + int l = this.cursor.getNextType(); + if (l == 3) { + continue; + } + +- BlockGetter blockGetter = this.getChunk(i, k); +- if (blockGetter == null) { ++ // Paper start - ensure we don't load chunks ++ boolean far = this.source != null && net.minecraft.server.MCUtil.distanceSq(this.source.getX(), y, this.source.getZ(), x, y, z) > 14; ++ this.pos.set(x, y, z); ++ ++ boolean isRegionLimited = this.collisionGetter instanceof net.minecraft.server.level.WorldGenRegion; ++ BlockState blockState = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && this.source instanceof net.minecraft.server.level.ServerPlayer) || (this.source != null && this.source.collisionLoadChunks) ++ ? this.collisionGetter.getBlockState(this.pos) ++ : this.collisionGetter.getTypeIfLoaded(this.pos) ++ ); ++ ++ if (blockState == null) { ++ if (!(this.source instanceof net.minecraft.server.level.ServerPlayer) || this.source.level.paperConfig.preventMovingIntoUnloadedChunks) { ++ VoxelShape voxelshape3 = Shapes.create(far ? this.source.getBoundingBox() : new AABB(new BlockPos(x, y, z))); ++ action.accept(voxelshape3); ++ return true; ++ } + continue; + } ++ // Paper - moved up ++ // Paper end + +- this.pos.set(i, j, k); +- BlockState blockState = blockGetter.getBlockState(this.pos); + if (!this.predicate.test(blockState, this.pos) || l == 1 && !blockState.hasLargeCollisionShape() || l == 2 && !blockState.is(Blocks.MOVING_PISTON)) { + continue; + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -0,0 +0,0 @@ public final class Shapes { + + if (s < 3) { + mutableBlockPos.set(axisCycle, q, r, p); +- BlockState blockState = world.getBlockState(mutableBlockPos); ++ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper ++ if (blockState == null) return 0.0D; // Paper + if ((s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) { + initial = blockState.getCollisionShape(world, mutableBlockPos, context).collide(axis3, box.move((double)(-mutableBlockPos.getX()), (double)(-mutableBlockPos.getY()), (double)(-mutableBlockPos.getZ())), initial); + if (Math.abs(initial) < 1.0E-7D) { diff --git a/Spigot-Server-Patches/Optimize-CraftBlockData-Creation.patch b/patches/server/Optimize-CraftBlockData-Creation.patch similarity index 71% rename from Spigot-Server-Patches/Optimize-CraftBlockData-Creation.patch rename to patches/server/Optimize-CraftBlockData-Creation.patch index 7c430a4990..36cba33186 100644 --- a/Spigot-Server-Patches/Optimize-CraftBlockData-Creation.patch +++ b/patches/server/Optimize-CraftBlockData-Creation.patch @@ -6,25 +6,25 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java 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; +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { + this.hasPostProcess = blockbase_info.hasPostProcess; + this.emissiveRendering = blockbase_info.emissiveRendering; } + // 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()); ++ if (cachedCraftBlockData == null) cachedCraftBlockData = org.bukkit.craftbukkit.block.data.CraftBlockData.createData(asState()); + return (org.bukkit.craftbukkit.block.data.CraftBlockData) cachedCraftBlockData.clone(); + } + // Paper end - public void a() { - if (!this.getBlock().o()) { + public void initCache() { + if (!this.getBlock().hasDynamicShape()) { 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 @@ -36,14 +36,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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); ++ Block.BLOCK_STATE_REGISTRY.iterator().forEachRemaining(BlockState::createCraftBlockData); + } - public static CraftBlockData fromData(IBlockData data) { + public static CraftBlockData fromData(BlockState data) { + return data.createCraftBlockData(); + } + -+ public static CraftBlockData createData(IBlockData data) { ++ public static CraftBlockData createData(BlockState data) { + // Paper end - return MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); + return CraftBlockData.MAP.getOrDefault(data.getBlock().getClass(), CraftBlockData::new).apply(data); } diff --git a/patches/server/Optimize-DataBits.patch b/patches/server/Optimize-DataBits.patch new file mode 100644 index 0000000000..3f951cda5b --- /dev/null +++ b/patches/server/Optimize-DataBits.patch @@ -0,0 +1,82 @@ +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/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/util/BitStorage.java ++++ b/src/main/java/net/minecraft/util/BitStorage.java +@@ -0,0 +0,0 @@ public class BitStorage { + private final long mask; + private final int size; + private final int valuesPerLong; +- private final int divideMul; +- private final int divideAdd; ++ private final int divideMul; private final long divideMulUnsigned; // Paper - referenced in b(int) with 2 Integer.toUnsignedLong calls ++ private final int divideAdd; private final long divideAddUnsigned; // Paper + private final int divideShift; + + public BitStorage(int elementBits, int size) { +@@ -0,0 +0,0 @@ public class BitStorage { + this.mask = (1L << elementBits) - 1L; + this.valuesPerLong = (char)(64 / elementBits); + int i = 3 * (this.valuesPerLong - 1); +- this.divideMul = MAGIC[i + 0]; +- this.divideAdd = MAGIC[i + 1]; ++ this.divideMul = BitStorage.MAGIC[i + 0]; this.divideMulUnsigned = Integer.toUnsignedLong(this.divideMul); // Paper ++ this.divideAdd = BitStorage.MAGIC[i + 1]; this.divideAddUnsigned = Integer.toUnsignedLong(this.divideAdd); // Paper + this.divideShift = MAGIC[i + 2]; + int j = (size + this.valuesPerLong - 1) / this.valuesPerLong; + if (storage != null) { +@@ -0,0 +0,0 @@ public class BitStorage { + } + + private int cellIndex(int index) { +- long l = Integer.toUnsignedLong(this.divideMul); +- long m = Integer.toUnsignedLong(this.divideAdd); +- return (int)((long)index * l + m >> 32 >> this.divideShift); ++ //long l = Integer.toUnsignedLong(this.divideMul); // Paper ++ //long m = Integer.toUnsignedLong(this.divideAdd); // Paper ++ return (int) ((long) index * this.divideMulUnsigned + this.divideAddUnsigned >> 32 >> this.divideShift); // Paper + } + +- public int getAndSet(int index, int value) { +- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); +- Validate.inclusiveBetween(0L, this.mask, (long)value); ++ public final int getAndSet(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper ++ //Validate.inclusiveBetween(0L, this.mask, (long)value); // Paper + int i = this.cellIndex(index); + long l = this.data[i]; + int j = (index - i * this.valuesPerLong) * this.bits; +@@ -0,0 +0,0 @@ public class BitStorage { + return k; + } + +- public void set(int index, int value) { +- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); +- Validate.inclusiveBetween(0L, this.mask, (long)value); ++ public final void set(int index, int value) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); // Paper ++ //Validate.inclusiveBetween(0L, this.mask, (long)value); // Paper + int i = this.cellIndex(index); + long l = this.data[i]; + int j = (index - i * this.valuesPerLong) * this.bits; + this.data[i] = l & ~(this.mask << j) | ((long)value & this.mask) << j; + } + +- public int get(int index) { +- Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); ++ public final int get(int index) { // Paper - make final for inline ++ //Validate.inclusiveBetween(0L, (long)(this.size - 1), (long)index); + int i = this.cellIndex(index); + long l = this.data[i]; + int j = (index - i * this.valuesPerLong) * this.bits; diff --git a/Spigot-Server-Patches/Optimize-Dynamic-get-Missing-Keys.patch b/patches/server/Optimize-Dynamic-get-Missing-Keys.patch similarity index 100% rename from Spigot-Server-Patches/Optimize-Dynamic-get-Missing-Keys.patch rename to patches/server/Optimize-Dynamic-get-Missing-Keys.patch diff --git a/patches/server/Optimize-Hoppers.patch b/patches/server/Optimize-Hoppers.patch new file mode 100644 index 0000000000..f5e3505355 --- /dev/null +++ b/patches/server/Optimize-Hoppers.patch @@ -0,0 +1,500 @@ +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 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper ++ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + + this.profiler.push(() -> { + return worldserver + " " + worldserver.dimension().location(); +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java +@@ -0,0 +0,0 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper + this.enabled = enabled; + } + ++ // Paper start - add back getLevel ++ @Override ++ public net.minecraft.world.level.Level getLevel() { ++ return this.level; ++ } ++ // Paper end ++ + @Override + public double getLevelX() { + return this.getX(); +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().interactLivingEntity(this, user, entity, hand); + } + +- public ItemStack copy() { +- if (this.isEmpty()) { ++ public ItemStack copy() { return cloneItemStack(false); } // Paper ++ public ItemStack cloneItemStack(boolean origItem) { // Paper ++ if (!origItem && this.isEmpty()) { // Paper + return ItemStack.EMPTY; + } else { +- ItemStack itemstack = new ItemStack(this.getItem(), this.count); ++ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper + + itemstack.setPopTime(this.getPopTime()); + if (this.tag != null) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + getMinecraftKey(); // Try to load if it doesn't exists. + return tileEntityKeyString; + } ++ static boolean IGNORE_TILE_UPDATES = false; + // Paper end + + @Nullable +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + + public void setChanged() { + if (this.level != null) { ++ if (IGNORE_TILE_UPDATES) return; // Paper + BlockEntity.setChanged(this.level, this.worldPosition, this.blockState); + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +@@ -0,0 +0,0 @@ public interface Hopper extends Container { + return SUCK; + } + ++ net.minecraft.world.level.Level getLevel(); // Paper ++ ++ default net.minecraft.core.BlockPos getBlockPosition() { return new net.minecraft.core.BlockPos(getLevelX(), getLevelY(), getLevelZ()); } // Paper ++ + double getLevelX(); + + double getLevelY(); +diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -0,0 +0,0 @@ package net.minecraft.world.level.block.entity; + import java.util.Iterator; + import java.util.List; + import java.util.function.BooleanSupplier; +-import java.util.stream.Collectors; + import java.util.stream.IntStream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; +-import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.HumanEntity; +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + + return false; + } ++ // Paper start - Optimize Hoppers ++ private static boolean skipPullModeEventFire = false; ++ private static boolean skipPushModeEventFire = false; ++ public static boolean skipHopperEvents = false; ++ ++ private static boolean hopperPush(Level level, BlockPos pos, Container destination, Direction enumdirection, HopperBlockEntity hopper) { ++ skipPushModeEventFire = skipHopperEvents; ++ boolean foundItem = false; ++ for (int i = 0; i < hopper.getContainerSize(); ++i) { ++ ItemStack item = hopper.getItem(i); ++ if (!item.isEmpty()) { ++ foundItem = true; ++ ItemStack origItemStack = item; ++ ItemStack itemstack = origItemStack; ++ ++ final int origCount = origItemStack.getCount(); ++ final int moved = Math.min(level.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(destination, itemstack, hopper); ++ if (itemstack == null) { // cancelled ++ origItemStack.setCount(origCount); ++ return false; ++ } ++ } ++ final ItemStack itemstack2 = addItem(hopper, destination, 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); ++ } ++ hopper.setItem(i, origItemStack); ++ destination.setChanged(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ } ++ } ++ if (foundItem && level.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown ++ hopper.setCooldown(level.spigotConfig.hopperTransfer); ++ } ++ return false; ++ } ++ ++ private static boolean hopperPull(Hopper ihopper, Container iinventory, ItemStack origItemStack, int i) { ++ ItemStack itemstack = origItemStack; ++ final int origCount = origItemStack.getCount(); ++ final Level world = ihopper.getLevel(); ++ 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.setChanged(); ++ return true; ++ } ++ origItemStack.setCount(origCount); ++ ++ if (world.paperConfig.cooldownHopperWhenFull) { ++ cooldownHopper(ihopper); ++ } ++ ++ return false; ++ } ++ ++ private static ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack, HopperBlockEntity hopper) { ++ Inventory destinationInventory = getInventory(iinventory); ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(hopper.getOwner(false).getInventory(), ++ CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); ++ boolean result = event.callEvent(); ++ if (!event.calledGetItem && !event.calledSetItem) { ++ skipPushModeEventFire = true; ++ } ++ if (!result) { ++ cooldownHopper(hopper); ++ return null; ++ } ++ ++ if (event.calledSetItem) { ++ return CraftItemStack.asNMSCopy(event.getItem()); ++ } else { ++ return itemstack; ++ } ++ } ++ ++ private static ItemStack callPullMoveEvent(Hopper hopper, Container 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(Container iinventory) { ++ Inventory sourceInventory;// Have to special case large chests as they work oddly ++ if (iinventory instanceof CompoundContainer) { ++ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); ++ } else if (iinventory instanceof BlockEntity) { ++ sourceInventory = ((BlockEntity) iinventory).getOwner(false).getInventory(); ++ } else { ++ sourceInventory = iinventory.getOwner().getInventory(); ++ } ++ return sourceInventory; ++ } ++ ++ private static void cooldownHopper(Hopper hopper) { ++ if (hopper instanceof HopperBlockEntity) { ++ ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); ++ } else if (hopper instanceof MinecartHopper) { ++ ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); ++ } ++ } ++ // Paper end + + private static boolean a(Level world, BlockPos blockposition, BlockState iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit + Container iinventory1 = HopperBlockEntity.getAttachedContainer(world, blockposition, iblockdata); +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + if (HopperBlockEntity.isFullContainer(iinventory1, enumdirection)) { + return false; + } else { ++ return hopperPush(world, blockposition, iinventory1, enumdirection, hopper); /* // Paper - disable rest + for (int i = 0; i < iinventory.getContainerSize(); ++i) { + if (!iinventory.getItem(i).isEmpty()) { + ItemStack itemstack = iinventory.getItem(i).copy(); +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + } + +- return false; ++ return false;*/ // Paper - end commenting out replaced block for Hopper Optimizations + } + } + } +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + + private static boolean isFullContainer(Container inventory, Direction direction) { +- return HopperBlockEntity.getSlots(inventory, direction).allMatch((i) -> { +- ItemStack itemstack = inventory.getItem(i); +- +- return itemstack.getCount() >= itemstack.getMaxStackSize(); +- }); ++ return allMatch(inventory, direction, STACK_SIZE_TEST); // Paper - no streams + } + + private static boolean isEmptyContainer(Container inv, Direction facing) { +- return HopperBlockEntity.getSlots(inv, facing).allMatch((i) -> { +- return inv.getItem(i).isEmpty(); +- }); ++ // Paper start ++ return allMatch(inv, facing, IS_EMPTY_TEST); ++ } ++ private static boolean allMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof WorldlyContainer) { ++ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } else { ++ int size = iinventory.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ if (!test.test(iinventory.getItem(i), i)) { ++ return false; ++ } ++ } ++ } ++ return true; + } + ++ private static boolean anyMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { ++ if (iinventory instanceof WorldlyContainer) { ++ for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { ++ if (test.test(iinventory.getItem(i), i)) { ++ return true; ++ } ++ } ++ } else { ++ int size = iinventory.getContainerSize(); ++ 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 ++ + public static boolean suckInItems(Level world, Hopper hopper) { + Container iinventory = HopperBlockEntity.getSourceContainer(world, hopper); + + if (iinventory != null) { + Direction enumdirection = Direction.DOWN; + +- return HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) ? false : HopperBlockEntity.getSlots(iinventory, enumdirection).anyMatch((i) -> { +- return HopperBlockEntity.a(hopper, iinventory, i, enumdirection, world); // Spigot ++ // Paper start - optimize hoppers and remove streams ++ skipPullModeEventFire = skipHopperEvents; ++ return !HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { ++ // Logic copied from below to avoid extra getItem calls ++ if (!item.isEmpty() && canTakeItemFromContainer(iinventory, item, i, enumdirection)) { ++ return hopperPull(hopper, iinventory, item, i); ++ } else { ++ return false; ++ } ++ // Paper end + }); + } else { + Iterator iterator = HopperBlockEntity.getItemsAtAndAbove(world, hopper).iterator(); +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + } + ++ // Paper - method unused as logic is inlined above + private static boolean a(Hopper ihopper, Container iinventory, int i, Direction enumdirection, Level world) { // Spigot + ItemStack itemstack = iinventory.getItem(i); + +- if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(iinventory, itemstack, i, enumdirection)) { ++ if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(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.copy(); + // 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 HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + + itemstack1.shrink(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 HopperBlockEntity extends RandomizableContainerBlockEntity implemen + public static boolean addItem(Container inventory, ItemEntity itemEntity) { + boolean flag = false; + // CraftBukkit start +- InventoryPickupItemEvent event = new InventoryPickupItemEvent(inventory.getOwner().getInventory(), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(inventory), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation + itemEntity.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + boolean flag1 = to.isEmpty(); + + if (itemstack1.isEmpty()) { ++ IGNORE_TILE_UPDATES = true; // Paper + to.setItem(slot, stack); ++ IGNORE_TILE_UPDATES = false; // Paper + stack = ItemStack.EMPTY; + flag = true; + } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) { +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + + public static List getItemsAtAndAbove(Level world, Hopper hopper) { +- return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { +- return world.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); +- }).collect(Collectors.toList()); ++ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! ++ double d0 = hopper.getLevelX(); ++ double d1 = hopper.getLevelY(); ++ double d2 = hopper.getLevelZ(); ++ AABB bb = new AABB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); ++ return world.getEntitiesOfClass(ItemEntity.class, bb, Entity::isAlive); ++ // Paper end + } + + @Nullable + public static Container getContainerAt(Level world, BlockPos pos) { +- return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D); ++ return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true); // Paper + } + ++ public static Container getContainerAt(Level world, double x, double y, double z) { return getContainerAt(world, x, y, z, false); } // Paper - overload to default false + @Nullable +- private static Container getContainerAt(Level world, double x, double y, double z) { ++ private static Container getContainerAt(Level world, double x, double y, double z, boolean optimizeEntities) { + Object object = null; + BlockPos blockposition = new BlockPos(x, y, z); + if ( !world.hasChunkAt( blockposition ) ) return null; // Spigot +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + } + +- if (object == null) { ++ if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper + List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + + if (!list.isEmpty()) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -0,0 +0,0 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + @Override + public boolean isEmpty() { + this.unpackLootTable((Player)null); +- return this.getItems().stream().allMatch(ItemStack::isEmpty); ++ // Paper start ++ for (ItemStack itemStack : this.getItems()) { ++ if (!itemStack.isEmpty()) { ++ return false; ++ } ++ } ++ // Paper end ++ return true; + } + + @Override + public ItemStack getItem(int slot) { +- this.unpackLootTable((Player)null); ++ if (slot == 0) this.unpackLootTable((Player) null); // Paper + return this.getItems().get(slot); + } + diff --git a/patches/server/Optimize-IntIdentityHashBiMiap-nextId.patch b/patches/server/Optimize-IntIdentityHashBiMiap-nextId.patch new file mode 100644 index 0000000000..a6de08f3bb --- /dev/null +++ b/patches/server/Optimize-IntIdentityHashBiMiap-nextId.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrew Steinborn +Date: Mon, 23 Jul 2018 13:08:19 -0400 +Subject: [PATCH] Optimize IntIdentityHashBiMiap#nextId() + +Optimizes CrudeIncrementalIntIdentityHashBiMap#nextId() + +This is a frequent hotspot for world loading/saving. + +diff --git a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java ++++ b/src/main/java/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java +@@ -0,0 +0,0 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + private K[] byId; + private int nextId; + private int size; ++ private java.util.BitSet usedIds; // Paper + + public CrudeIncrementalIntIdentityHashBiMap(int size) { + size = (int)((float)size / 0.8F); + this.keys = (K[])(new Object[size]); + this.values = new int[size]; + this.byId = (K[])(new Object[size]); ++ this.usedIds = new java.util.BitSet(); // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + } + + private int nextId() { ++ /* // Paper start + while(this.nextId < this.byId.length && this.byId[this.nextId] != null) { + ++this.nextId; + } ++ */ ++ this.nextId = this.usedIds.nextClearBit(0); ++ // Paper end + + return this.nextId; + } +@@ -0,0 +0,0 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + this.byId = (K[])(new Object[newSize]); + this.nextId = 0; + this.size = 0; ++ this.usedIds.clear(); // Paper + + for(int i = 0; i < objects.length; ++i) { + if (objects[i] != null) { +@@ -0,0 +0,0 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + this.keys[k] = value; + this.values[k] = id; + this.byId[id] = value; ++ this.usedIds.set(id); // Paper + ++this.size; + if (id == this.nextId) { + ++this.nextId; +@@ -0,0 +0,0 @@ public class CrudeIncrementalIntIdentityHashBiMap implements IdMap { + Arrays.fill(this.byId, (Object)null); + this.nextId = 0; + this.size = 0; ++ this.usedIds.clear(); // Paper + } + + public int size() { diff --git a/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch b/patches/server/Optimize-ItemStack.isEmpty.patch similarity index 70% rename from Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch rename to patches/server/Optimize-ItemStack.isEmpty.patch index 68a8013e17..27801c1510 100644 --- a/Spigot-Server-Patches/Optimize-ItemStack.isEmpty.patch +++ b/patches/server/Optimize-ItemStack.isEmpty.patch @@ -13,8 +13,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } 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 +- return this == ItemStack.EMPTY ? true : (this.getItem() != null && !this.is(Items.AIR) ? this.count <= 0 : true); ++ return this == ItemStack.EMPTY || this.item == null || this.item == Items.AIR || this.count <= 0; // Paper } - public ItemStack cloneAndSubtract(int i) { + public ItemStack split(int amount) { diff --git a/patches/server/Optimize-MappedRegistry.patch b/patches/server/Optimize-MappedRegistry.patch new file mode 100644 index 0000000000..e2fee46601 --- /dev/null +++ b/patches/server/Optimize-MappedRegistry.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 26 Aug 2018 20:49:50 -0400 +Subject: [PATCH] Optimize MappedRegistry + +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/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/MappedRegistry.java ++++ b/src/main/java/net/minecraft/core/MappedRegistry.java +@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; + public class MappedRegistry extends WritableRegistry { + protected static final Logger LOGGER = LogManager.getLogger(); + private final ObjectList byId = new ObjectArrayList<>(256); +- private final Object2IntMap toId = new Object2IntOpenCustomHashMap<>(Util.identityStrategy()); ++ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map + private final BiMap storage; + private final BiMap, T> keyStorage; + private final Map lifecycles; +@@ -0,0 +0,0 @@ public class MappedRegistry extends WritableRegistry { + public MappedRegistry(ResourceKey> key, Lifecycle lifecycle) { + super(key, lifecycle); + this.toId.defaultReturnValue(-1); +- this.storage = HashBiMap.create(); +- this.keyStorage = HashBiMap.create(); +- this.lifecycles = Maps.newIdentityHashMap(); ++ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions ++ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions + this.elementsLifecycle = lifecycle; + } + diff --git a/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch new file mode 100644 index 0000000000..a67e6eb993 --- /dev/null +++ b/patches/server/Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -0,0 +1,323 @@ +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/Connection.java b/src/main/java/net/minecraft/network/Connection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/Connection.java ++++ b/src/main/java/net/minecraft/network/Connection.java +@@ -0,0 +0,0 @@ public class Connection 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 ConnectionProtocol protocol; + // Paper end + + public Connection(PacketFlow side) { +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + } + + public void setProtocol(ConnectionProtocol state) { ++ protocol = state; // Paper + this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).set(state); + this.channel.config().setAutoRead(true); + Connection.LOGGER.debug("Enabled auto read"); +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + Validate.notNull(listener, "packetListener", new Object[0]); + this.packetListener = listener; + } ++ // Paper start ++ public net.minecraft.server.level.ServerPlayer getPlayer() { ++ if (packetListener instanceof ServerGamePacketListenerImpl) { ++ return ((ServerGamePacketListenerImpl) 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(Connection networkManager, Packet packet) { ++ return networkManager.isPending || networkManager.protocol != ConnectionProtocol.PLAY || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundKeepAlivePacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundChatPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundClearTitlesPacket || ++ packet instanceof net.minecraft.network.protocol.game.ClientboundBossEventPacket; ++ } ++ // Paper end ++ } ++ // Paper end + + public void send(Packet packet) { + this.send(packet, (GenericFutureListener) null); + } + + public void send(Packet packet, @Nullable GenericFutureListener> callback) { +- if (this.isConnected()) { +- this.flushQueue(); ++ // 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) || ( ++ net.minecraft.server.MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && ++ (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) ++ ))) { + this.sendPacket(packet, callback); +- } else { +- this.queue.add(new Connection.PacketHolder(packet, callback)); ++ 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.queue.add(new Connection.PacketHolder(packet, callback)); ++ } else { ++ java.util.List packets = new java.util.ArrayList<>(1 + extraPackets.size()); ++ packets.add(new Connection.PacketHolder(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 Connection.PacketHolder(extra, end ? callback : null)); // append listener to the end ++ } ++ this.queue.addAll(packets); // atomic ++ } ++ this.flushQueue(); ++ // Paper end + } + + private void sendPacket(Packet packet, @Nullable GenericFutureListener> callback) { +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + this.setProtocol(enumprotocol); + } + ++ // Paper start ++ net.minecraft.server.level.ServerPlayer player = getPlayer(); ++ 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); ++ disconnect(new net.minecraft.network.chat.TranslatableComponent("disconnect.genericReason", "Internal Exception: " + e.getMessage())); ++ packet.onPacketDispatchFinish(player, null); ++ } ++ // Paper end + } + + private ConnectionProtocol getCurrentProtocol() { + return (ConnectionProtocol) this.channel.attr(Connection.ATTRIBUTE_PROTOCOL).get(); + } + +- private void flushQueue() { +- if (this.channel != null && this.channel.isOpen()) { +- Queue queue = this.queue; +- ++ // Paper start - rewrite this to be safer if ran off main thread ++ private boolean flushQueue() { // void -> boolean ++ if (!isConnected()) { ++ return true; ++ } ++ if (net.minecraft.server.MCUtil.isMainThread()) { ++ return processQueue(); ++ } else if (isPending) { ++ // Should only happen during login/status stages + synchronized (this.queue) { +- Connection.PacketHolder networkmanager_queuedpacket; +- +- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) { +- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener); +- } ++ return this.processQueue(); ++ } ++ } ++ return false; ++ } ++ private boolean processQueue() { ++ if (this.queue.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.queue.iterator(); ++ while (iterator.hasNext()) { ++ PacketHolder queued = iterator.next(); // poll -> peek ++ ++ // Fix NPE (Spigot bug caused by handleDisconnection()) ++ if (queued == null) { ++ return true; ++ } + ++ Packet packet = queued.packet; ++ if (!packet.isReady()) { ++ return false; ++ } else { ++ iterator.remove(); ++ this.sendPacket(packet, queued.listener); + } + } ++ return true; + } ++ // Paper end + + public void tick() { + this.flushQueue(); +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + return this.address; + } + ++ // Paper start ++ public void clearPacketQueue() { ++ net.minecraft.server.level.ServerPlayer player = getPlayer(); ++ queue.forEach(queuedPacket -> { ++ Packet packet = queuedPacket.packet; ++ if (packet.hasFinishListener()) { ++ packet.onPacketDispatchFinish(player, null); ++ } ++ }); ++ queue.clear(); ++ } ++ // Paper end + public void disconnect(Component disconnectReason) { + // 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 Connection extends SimpleChannelInboundHandler> { + public void handleDisconnection() { + if (this.channel != null && !this.channel.isOpen()) { + if (this.disconnectionHandled) { +- Connection.LOGGER.warn("handleDisconnection() called twice"); ++ //Connection.LOGGER.warn("handleDisconnection() called twice"); // Paper - Do not log useless message + } else { + this.disconnectionHandled = true; + if (this.getDisconnectedReason() != null) { +@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler> { + } else if (this.getPacketListener() != null) { + this.getPacketListener().onDisconnect(new TranslatableComponent("multiplayer.disconnect.generic")); + } +- this.queue.clear(); // Free up packet queue. ++ clearPacketQueue(); // Paper + // Paper start - Add PlayerConnectionCloseEvent + final PacketListener packetListener = this.getPacketListener(); + if (packetListener instanceof ServerGamePacketListenerImpl) { +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 handle(T listener); + + // Paper start ++ /** ++ * @param player Null if not at PLAY stage yet ++ */ ++ default void onPacketDispatch(@javax.annotation.Nullable net.minecraft.server.level.ServerPlayer 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 net.minecraft.server.level.ServerPlayer player, @javax.annotation.Nullable io.netty.channel.ChannelFuture future) {} ++ default boolean hasFinishListener() { return false; } ++ default boolean isReady() { return true; } ++ default java.util.List getExtraPackets() { return null; } + default boolean packetTooLarge(net.minecraft.network.Connection manager) { + return false; + } +diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java ++++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + final List connections = 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 final void addPending() { + Connection manager = null; + while ((manager = pending.poll()) != null) { + connections.add(manager); ++ manager.isPending = false; + } + } + // Paper end +@@ -0,0 +0,0 @@ public class ServerConnectionListener { + ; + } + ++ if (!disableFlushConsolidation) channel.pipeline().addFirst(new io.netty.handler.flush.FlushConsolidationHandler()); // Paper + channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this)).addLast("splitter", new Varint21FrameDecoder()).addLast("decoder", new PacketDecoder(PacketFlow.SERVERBOUND)).addLast("prepender", new Varint21LengthFieldPrepender()).addLast("encoder", new PacketEncoder(PacketFlow.CLIENTBOUND)); + int j = ServerConnectionListener.this.server.getRateLimitPacketsPerSecond(); + Object object = j > 0 ? new RateKickingConnection(j) : new Connection(PacketFlow.SERVERBOUND); diff --git a/patches/server/Optimize-NetworkManager-Exception-Handling.patch b/patches/server/Optimize-NetworkManager-Exception-Handling.patch new file mode 100644 index 0000000000..6047abf763 --- /dev/null +++ b/patches/server/Optimize-NetworkManager-Exception-Handling.patch @@ -0,0 +1,79 @@ +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/ConnectionProtocol.java b/src/main/java/net/minecraft/network/ConnectionProtocol.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/ConnectionProtocol.java ++++ b/src/main/java/net/minecraft/network/ConnectionProtocol.java +@@ -0,0 +0,0 @@ public enum ConnectionProtocol { + + @Nullable + public Packet createPacket(int id, FriendlyByteBuf buf) { ++ if (id < 0 || id >= this.idToDeserializer.size()) return null; // Paper + Function> function = this.idToDeserializer.get(id); + return function != null ? function.apply(buf) : null; + } +diff --git a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/Varint21FrameDecoder.java ++++ b/src/main/java/net/minecraft/network/Varint21FrameDecoder.java +@@ -0,0 +0,0 @@ import io.netty.handler.codec.CorruptedFrameException; + import java.util.List; + + public class Varint21FrameDecoder extends ByteToMessageDecoder { ++ private final byte[] lenBuf = new byte[3]; // Paper + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) { ++ // Paper start - if channel is not active just discard the packet ++ if (!channelHandlerContext.channel().isActive()) { ++ byteBuf.skipBytes(byteBuf.readableBytes()); ++ return; ++ } ++ // Paper end + byteBuf.markReaderIndex(); ++ // Paper start - reuse temporary length buffer ++ byte[] abyte = lenBuf; ++ java.util.Arrays.fill(abyte, (byte) 0); ++ // Paper end + byte[] bs = new byte[3]; + + for(int i = 0; i < bs.length; ++i) { +diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +@@ -0,0 +0,0 @@ + package net.minecraft.network.protocol; + ++import net.minecraft.network.Connection; + import net.minecraft.network.PacketListener; ++import net.minecraft.network.chat.TextComponent; ++import net.minecraft.network.protocol.game.ClientboundDisconnectPacket; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import co.aikar.timings.MinecraftTimings; // Paper +@@ -0,0 +0,0 @@ public class PacketUtils { + try (Timing ignored = timing.startTiming()) { // Paper - timings + packet.handle(listener); + } // Paper - timings ++ // Paper start ++ catch (Exception e) { ++ Connection networkmanager = listener.getConnection(); ++ if (networkmanager.getPlayer() != null) { ++ LOGGER.error("Error whilst processing packet {} for {}[{}]", packet, networkmanager.getPlayer().getScoreboardName(), networkmanager.getRemoteAddress(), e); ++ } else { ++ LOGGER.error("Error whilst processing packet {} for connection from {}", packet, networkmanager.getRemoteAddress(), e); ++ } ++ TextComponent error = new TextComponent("Packet processing error"); ++ networkmanager.send(new ClientboundDisconnectPacket(error), (future) -> { ++ networkmanager.disconnect(error); ++ }); ++ networkmanager.setReadOnly(); ++ } ++ // Paper end + } else { + PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet); + } diff --git a/patches/server/Optimize-NibbleArray-to-use-pooled-buffers.patch b/patches/server/Optimize-NibbleArray-to-use-pooled-buffers.patch new file mode 100644 index 0000000000..f31a39624e --- /dev/null +++ b/patches/server/Optimize-NibbleArray-to-use-pooled-buffers.patch @@ -0,0 +1,329 @@ +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/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java +@@ -0,0 +0,0 @@ package net.minecraft.network.protocol.game; + + import com.google.common.collect.Lists; + import java.util.BitSet; ++import io.netty.channel.ChannelFuture; // Paper + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.SectionPos; + import net.minecraft.network.FriendlyByteBuf; + import net.minecraft.network.protocol.Packet; ++import net.minecraft.server.MCUtil; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.level.ChunkPos; + import net.minecraft.world.level.LightLayer; + import net.minecraft.world.level.chunk.DataLayer; +@@ -0,0 +0,0 @@ public class ClientboundLightUpdatePacket implements Packet skyUpdates; + private final List blockUpdates; + private final boolean trustEdges; ++ // 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(ServerPlayer player) { ++ remainingSends.incrementAndGet(); ++ } ++ ++ @Override ++ public void onPacketDispatchFinish(ServerPlayer 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 ClientboundLightUpdatePacket(ChunkPos chunkPos, LevelLightEngine lightProvider, @Nullable BitSet bitSet, @Nullable BitSet bitSet2, boolean nonEdge) { + this.x = chunkPos.x; +@@ -0,0 +0,0 @@ public class ClientboundLightUpdatePacket implements Packet BYTE_2048 = new com.destroystokyo.paper.util.pooled.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 DataLayer markPoolSafe(byte[] bytes) { ++ if (bytes != EMPTY_NIBBLE) this.data = bytes; ++ return markPoolSafe(); ++ } ++ public DataLayer markPoolSafe() { ++ poolSafe = true; ++ return this; ++ } ++ public byte[] getIfSet() { ++ return this.data != null ? this.data : EMPTY_NIBBLE; ++ } ++ public byte[] getCloneIfSet() { ++ if (data == null) { ++ return EMPTY_NIBBLE; ++ } ++ byte[] ret = BYTE_2048.acquire(); ++ System.arraycopy(getIfSet(), 0, ret, 0, 2048); ++ return ret; ++ } ++ ++ public DataLayer cloneAndSet(byte[] bytes) { ++ if (bytes != null && bytes != EMPTY_NIBBLE) { ++ this.data = BYTE_2048.acquire(); ++ System.arraycopy(bytes, 0, this.data, 0, 2048); ++ } ++ return this; ++ } ++ boolean poolSafe = false; ++ public java.lang.Runnable cleaner; ++ private void registerCleaner() { ++ if (!poolSafe) { ++ cleaner = net.minecraft.server.MCUtil.registerCleaner(this, this.data, DataLayer::releaseBytes); ++ } else { ++ cleaner = net.minecraft.server.MCUtil.once(() -> DataLayer.releaseBytes(this.data)); ++ } ++ } + public DataLayer() {} + + public DataLayer(byte[] bytes) { ++ // Paper start ++ this(bytes, false); ++ } ++ public DataLayer(byte[] bytes, boolean isSafe) { + this.data = bytes; ++ if (!isSafe) this.data = getCloneIfSet(); // Paper - clone for safety ++ registerCleaner(); ++ // Paper end + if (bytes.length != 2048) { + throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + bytes.length))); + } +@@ -0,0 +0,0 @@ public class DataLayer { + + public void set(int index, int value) { // PAIL: private -> public + if (this.data == null) { +- this.data = new byte[2048]; ++ this.data = BYTE_2048.acquire(); // Paper ++ registerCleaner();// Paper + } + + int k = this.getPosition(index); +@@ -0,0 +0,0 @@ public class DataLayer { + public byte[] getData() { + if (this.data == null) { + this.data = 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.data = this.data.clone(); ++ cleaner.run(); // release the previously pooled value ++ this.cleaner = null; ++ } + } ++ // Paper end + + return this.data; + } + ++ @javax.annotation.Nonnull ++ public byte[] asBytesPoolSafe() { ++ if (this.data == null) { ++ this.data = BYTE_2048.acquire(); // Paper ++ registerCleaner(); // Paper ++ } ++ ++ return this.data; ++ } ++ // Paper end + public DataLayer copy() { +- return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); ++ return this.data == null ? new DataLayer() : new DataLayer(this.data); // Paper - clone in ctor + } + + public String toString() { +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { + } + + if (nibblearray != null && !nibblearray.isEmpty()) { +- nbttagcompound2.putByteArray("BlockLight", nibblearray.getData()); ++ nbttagcompound2.putByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper + } + + if (nibblearray1 != null && !nibblearray1.isEmpty()) { +- nbttagcompound2.putByteArray("SkyLight", nibblearray1.getData()); ++ nbttagcompound2.putByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper + } + + nbttaglist.add(nbttagcompound2); +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { + + public void copyDataLayer(long pos) { + if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data +- this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data ++ DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles ++ this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone ++ if (updating.cleaner != null) net.minecraft.server.MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it + this.clearCache(); + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java ++++ b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java +@@ -0,0 +0,0 @@ public class FlatDataLayer extends DataLayer { + + public FlatDataLayer(DataLayer chunkNibbleArray, int offset) { + super(128); +- System.arraycopy(chunkNibbleArray.getData(), offset * 128, this.data, 0, 128); ++ System.arraycopy(chunkNibbleArray.getIfSet(), offset * 128, this.data, 0, 128); // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class FlatDataLayer extends DataLayer { + + @Override + public byte[] getData() { +- byte[] bs = new byte[2048]; ++ byte[] bs = BYTE_2048.acquire(); // Paper + + for(int i = 0; i < 16; ++i) { + System.arraycopy(this.data, 0, bs, i * 128, 128); +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> + + protected DataLayer createDataLayer(long sectionPos) { + DataLayer dataLayer = this.queuedSections.get(sectionPos); +- return dataLayer != null ? dataLayer : new DataLayer(); ++ return dataLayer != null ? dataLayer : new DataLayer().markPoolSafe(); // Paper + } + + protected void clearQueuedSectionBlocks(LayerLightEngine storage, long sectionPos) { +@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> + + protected void queueSectionData(long sectionPos, @Nullable DataLayer array, boolean bl) { + if (array != null) { +- this.queuedSections.put(sectionPos, array); ++ DataLayer remove = this.queuedSections.put(sectionPos, array); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed + if (!bl) { + this.untrustedSections.add(sectionPos); + } + } else { +- this.queuedSections.remove(sectionPos); ++ DataLayer remove = this.queuedSections.remove(sectionPos); 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/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage +Date: Tue, 4 Aug 2020 22:24:15 +0200 +Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections + +1.17 Update: Please do this k thx bb +I utilized the IDE to convert streams to non streams code, so shouldn't +be any risk of behavior change. Only did minor optimization of the +generated code set to remove unnecessary things. + +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.openSet.clear(); + this.nodeEvaluator.prepare(world, mob); + Node node = this.nodeEvaluator.getStart(); +- Map map = positions.stream().collect(Collectors.toMap((blockPos) -> { +- return this.nodeEvaluator.getGoal((double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ()); +- }, Function.identity())); ++ // Paper start - remove streams - and optimize collection ++ List> map = Lists.newArrayList(); ++ for (BlockPos blockPos : positions) { ++ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(blockPos.getX(), blockPos.getY(), blockPos.getZ()), blockPos)); ++ } ++ // Paper end + Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier); + this.nodeEvaluator.done(); + return path; + } + + @Nullable +- private Path findPath(ProfilerFiller profiler, Node startNode, Map positions, float followRange, int distance, float rangeMultiplier) { ++ // Paper start - optimize collection ++ private Path findPath(ProfilerFiller profiler, Node startNode, List> positions, float followRange, int distance, float rangeMultiplier) { + profiler.push("find_path"); + profiler.markForCharting(MetricCategory.PATH_FINDING); +- Set set = positions.keySet(); ++ //Set set = positions.keySet(); + startNode.g = 0.0F; +- startNode.h = this.getBestH(startNode, set); ++ startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection + startNode.f = startNode.h; + this.openSet.clear(); + this.openSet.insert(startNode); +- Set set2 = ImmutableSet.of(); ++ //Set set2 = ImmutableSet.of(); // Paper - unused - diff on change + int i = 0; +- Set set3 = Sets.newHashSetWithExpectedSize(set.size()); ++ List> entryList = Lists.newArrayListWithExpectedSize(positions.size()); // Paper - optimize collection + int j = (int)((float)this.maxVisitedNodes * rangeMultiplier); + + while(!this.openSet.isEmpty()) { +@@ -0,0 +0,0 @@ public class PathFinder { + Node node = this.openSet.pop(); + node.closed = true; + +- for(Target target : set) { ++ // Paper start - optimize collection ++ for(int i1 = 0; i1 < positions.size(); i1++) { ++ final Map.Entry entry = positions.get(i1); ++ Target target = entry.getKey(); + if (node.distanceManhattan(target) <= (float)distance) { + target.setReached(); +- set3.add(target); ++ entryList.add(entry); ++ // Paper end + } + } + +- if (!set3.isEmpty()) { ++ if (!entryList.isEmpty()) { // Paper - rename variable + break; + } + +@@ -0,0 +0,0 @@ public class PathFinder { + if (node2.walkedDistance < followRange && (!node2.inOpenSet() || g < node2.g)) { + node2.cameFrom = node; + node2.g = g; +- node2.h = this.getBestH(node2, set) * 1.5F; ++ node2.h = this.getBestH(node2, positions) * 1.5F; // Paper - list instead of set + if (node2.inOpenSet()) { + this.openSet.changeCost(node2, node2.g + node2.h); + } else { +@@ -0,0 +0,0 @@ public class PathFinder { + } + } + +- Optional optional = !set3.isEmpty() ? set3.stream().map((target) -> { +- return this.reconstructPath(target.getBestNode(), positions.get(target), true); +- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((target) -> { +- return this.reconstructPath(target.getBestNode(), positions.get(target), false); +- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)); +- profiler.pop(); +- return !optional.isPresent() ? null : optional.get(); ++ // Paper start - remove streams - and optimize collection ++ Path best = null; ++ boolean entryListIsEmpty = entryList.isEmpty(); ++ Comparator comparator = entryListIsEmpty ? Comparator.comparingInt(Path::getNodeCount) ++ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount); ++ for (Map.Entry entry : entryListIsEmpty ? positions : entryList) { ++ Path path = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !entryListIsEmpty); ++ if (best == null || comparator.compare(path, best) < 0) ++ best = path; ++ } ++ return best; ++ // Paper end + } + +- private float getBestH(Node node, Set targets) { ++ private float getBestH(Node node, List> targets) { // Paper - optimize collection - Set -> List> + float f = Float.MAX_VALUE; + +- for(Target target : targets) { ++ // Paper start - optimize collection ++ for (int i = 0, targetsSize = targets.size(); i < targetsSize; i++) { ++ final Target target = targets.get(i).getKey(); ++ // Paper end + float g = node.distanceTo(target); + target.updateBest(g, node); + f = Math.min(g, f); diff --git a/patches/server/Optimize-Pathfinding.patch b/patches/server/Optimize-Pathfinding.patch new file mode 100644 index 0000000000..f32745f2c0 --- /dev/null +++ b/patches/server/Optimize-Pathfinding.patch @@ -0,0 +1,43 @@ +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/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -0,0 +0,0 @@ public abstract class PathNavigation { + return this.moveTo(this.createPath(x, y, z, 1), speed); + } + ++ // Paper start - optimise pathfinding ++ private int lastFailure = 0; ++ private int pathfindFailures = 0; ++ // Paper end ++ + public boolean moveTo(Entity entity, double speed) { ++ // Paper start - Pathfinding optimizations ++ if (this.pathfindFailures > 10 && this.path == null && net.minecraft.server.MinecraftServer.currentTick < this.lastFailure + 40) { ++ return false; ++ } ++ // Paper end + Path path = this.createPath(entity, 1); +- return path != null && this.moveTo(path, speed); ++ // Paper start - Pathfinding optimizations ++ if (path != null && this.moveTo(path, speed)) { ++ this.lastFailure = 0; ++ this.pathfindFailures = 0; ++ return true; ++ } else { ++ this.pathfindFailures++; ++ this.lastFailure = net.minecraft.server.MinecraftServer.currentTick; ++ return false; ++ } ++ // Paper end + } + + public boolean moveTo(@Nullable Path path, double speed) { diff --git a/patches/server/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch new file mode 100644 index 0000000000..0d2ac828b9 --- /dev/null +++ b/patches/server/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -0,0 +1,299 @@ +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 { + + ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle(); + ChunkMap chunkMap = world.getChunkSource().chunkMap; +- Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.visibleChunkMap; ++ Long2ObjectLinkedOpenHashMap visibleChunks = chunkMap.getVisibleChunks(); + DistanceManager chunkMapDistance = chunkMap.distanceManager; + List allChunks = new ArrayList<>(visibleChunks.values()); + List players = world.players; +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private static final int MIN_VIEW_DISTANCE = 3; + public static final int MAX_VIEW_DISTANCE = 33; + public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance(); ++ // Paper start - faster copying ++ public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying ++ public final Long2ObjectLinkedOpenHashMap visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying ++ ++ private class ProtectedVisibleChunksMap extends com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy { ++ @Override ++ public ChunkHolder put(long k, ChunkHolder playerChunk) { ++ throw new UnsupportedOperationException("Updating visible Chunks"); ++ } ++ ++ @Override ++ public ChunkHolder remove(long k) { ++ throw new UnsupportedOperationException("Removing visible Chunks"); ++ } ++ ++ @Override ++ public ChunkHolder get(long k) { ++ return ChunkMap.this.getVisibleChunkIfPresent(k); ++ } ++ ++ public ChunkHolder 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 + public static final int FORCED_TICKET_LEVEL = 31; +- public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); +- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ // public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); // Paper - moved up ++ // public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; // Paper - moved up + private final Long2ObjectLinkedOpenHashMap pendingUnloads; + public final LongSet entitiesInLevel; + public final ServerLevel level; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { + super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync); +- this.visibleChunkMap = this.updatingChunkMap.clone(); ++ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning + this.pendingUnloads = new Long2ObjectLinkedOpenHashMap(); + this.entitiesInLevel = new LongOpenHashSet(); + this.toDrop = new LongOpenHashSet(); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return (ChunkHolder) this.updatingChunkMap.get(pos); + } + ++ // 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 (ChunkHolder value : this.visibleChunkMap.values()) { ++ consumer.accept(value); ++ } ++ } finally { ++ this.isIterating = prev; ++ if (!this.isIterating && this.hasPendingVisibleUpdate) { ++ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom(this.pendingVisibleChunks); ++ this.pendingVisibleChunks.clear(); ++ this.hasPendingVisibleUpdate = false; ++ } ++ } ++ } ++ public Long2ObjectLinkedOpenHashMap getVisibleChunks() { ++ if (Thread.currentThread() == this.level.thread) { ++ return this.visibleChunkMap; ++ } else { ++ synchronized (this.visibleChunkMap) { ++ if (DEBUG_ASYNC_VISIBLE_CHUNKS) new Throwable("Async getVisibleChunks").printStackTrace(); ++ if (this.visibleChunksClone == null) { ++ this.visibleChunksClone = this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.clone() : ((ProtectedVisibleChunksMap)this.visibleChunkMap).clone(); ++ } ++ return this.visibleChunksClone; ++ } ++ } ++ } ++ // Paper end ++ + @Nullable + public ChunkHolder getVisibleChunkIfPresent(long pos) { +- return (ChunkHolder) this.visibleChunkMap.get(pos); ++ // Paper start - mt safe get ++ if (Thread.currentThread() != this.level.thread) { ++ synchronized (this.visibleChunkMap) { ++ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); ++ } ++ } ++ return (ChunkHolder) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(pos) : ((ProtectedVisibleChunksMap)this.visibleChunkMap).safeGet(pos)); ++ // Paper end + } + + protected IntSupplier getChunkQueueLevel(long pos) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + protected void saveAllChunks(boolean flush) { ++ Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) + if (flush) { +- List list = (List) this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); ++ List list = (List) visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper - remove cloning of visible chunks + MutableBoolean mutableboolean = new MutableBoolean(); + + do { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // this.i(); // Paper - nuke IOWorker + ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName()); + } else { +- this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { ++ visibleChunks.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { + ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error + + if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!this.modified) { + return false; + } else { +- this.visibleChunkMap = this.updatingChunkMap.clone(); ++ // Paper start - stop cloning visibleChunks ++ synchronized (this.visibleChunkMap) { ++ if (isIterating) { ++ hasPendingVisibleUpdate = true; ++ this.pendingVisibleChunks.copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); ++ } else { ++ hasPendingVisibleUpdate = false; ++ this.pendingVisibleChunks.clear(); ++ ((ProtectedVisibleChunksMap)this.visibleChunkMap).copyFrom((com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy)this.updatingChunkMap); ++ this.visibleChunksClone = null; ++ } ++ } ++ // Paper end ++ + this.modified = false; + return true; + } +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } + + protected Iterable getChunks() { +- return Iterables.unmodifiableIterable(this.visibleChunkMap.values()); ++ return Iterables.unmodifiableIterable(this.getVisibleChunks().values()); // Paper + } + + void dumpChunks(Writer writer) throws IOException { + CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").build(writer); +- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator(); ++ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper + + while (objectbidirectionaliterator.hasNext()) { + Entry entry = (Entry) objectbidirectionaliterator.next(); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + }; + // Paper end + this.level.timings.chunkTicks.startTiming(); // Paper +- this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... ++ this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + + if (optional.isPresent()) { +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 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.getChunkSource().chunkMap.visibleChunkMap; + int size = 0; +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + size += chunk.blockEntities.size(); + } + return size; ++ }); + } + + @Override +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + + @Override + public int getChunkCount() { ++ return net.minecraft.server.MCUtil.ensureMain(() -> { + int ret = 0; + + for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + } + } + +- return ret; ++ return ret; }); + } + + @Override +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + + @Override + public Chunk[] getLoadedChunks() { ++ // Paper start ++ if (Thread.currentThread() != world.getLevel().thread) { ++ synchronized (world.getChunkSource().chunkMap.visibleChunkMap) { ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); ++ } ++ } ++ // Paper end + Long2ObjectLinkedOpenHashMap chunks = this.world.getChunkSource().chunkMap.visibleChunkMap; + return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new); + } diff --git a/patches/server/Optimize-ServerLevels-chunk-level-checking-methods.patch b/patches/server/Optimize-ServerLevels-chunk-level-checking-methods.patch new file mode 100644 index 0000000000..81488f2648 --- /dev/null +++ b/patches/server/Optimize-ServerLevels-chunk-level-checking-methods.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 16 Apr 2020 16:13:59 -0700 +Subject: [PATCH] Optimize ServerLevels chunk level checking 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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + public boolean isPositionTickingWithEntitiesLoaded(BlockPos blockposition) { + long i = ChunkPos.asLong(blockposition); + +- return this.chunkSource.isPositionTicking(i) && this.areEntitiesLoaded(i); ++ // Paper start - optimize is ticking ready type functions ++ ChunkHolder chunkHolder = this.chunkSource.chunkMap.getVisibleChunkIfPresent(i); ++ return chunkHolder != null && chunkHolder.isTickingReady() && this.areEntitiesLoaded(i); ++ // Paper end + } + + public boolean isPositionEntityTicking(BlockPos blockposition) { +- return this.entityManager.isPositionTicking(blockposition); ++ return this.entityManager.isPositionTicking(ChunkPos.asLong(blockposition)); // Paper + } + + public boolean isPositionEntityTicking(ChunkPos chunkcoordintpair) { +- return this.entityManager.isPositionTicking(chunkcoordintpair); ++ return this.entityManager.isPositionTicking(chunkcoordintpair.toLong()); // Paper + } + + private final class EntityCallbacks implements LevelCallback { +diff --git a/src/main/java/net/minecraft/world/level/ChunkPos.java b/src/main/java/net/minecraft/world/level/ChunkPos.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/ChunkPos.java ++++ b/src/main/java/net/minecraft/world/level/ChunkPos.java +@@ -0,0 +0,0 @@ public class ChunkPos { + } + + public static long asLong(BlockPos blockPos) { +- return asLong(SectionPos.blockToSectionCoord(blockPos.getX()), SectionPos.blockToSectionCoord(blockPos.getZ())); ++ return (((long)blockPos.getX() >> 4) & 4294967295L) | ((((long)blockPos.getZ() >> 4) & 4294967295L) << 32); // Paper - inline + } + + public static int getX(long pos) { +diff --git a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java ++++ b/src/main/java/net/minecraft/world/level/entity/PersistentEntitySectionManager.java +@@ -0,0 +0,0 @@ public class PersistentEntitySectionManager implements A + public LevelEntityGetter getEntityGetter() { + return this.entityGetter; + } ++ // Paper start ++ public final boolean isPositionTicking(long position) { ++ return this.chunkVisibility.get(position).isTicking(); ++ } ++ // Paper end + + public boolean isPositionTicking(BlockPos blockPos) { + return this.chunkVisibility.get(ChunkPos.asLong(blockPos)).isTicking(); diff --git a/patches/server/Optimize-UserCache-Thread-Safe.patch b/patches/server/Optimize-UserCache-Thread-Safe.patch new file mode 100644 index 0000000000..a5d1e16a9e --- /dev/null +++ b/patches/server/Optimize-UserCache-Thread-Safe.patch @@ -0,0 +1,111 @@ +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. + +1.17: TODO does this need the synchronized blocks anymore? + +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 ReentrantBlockableEventLoop { // Paper + + try { + BufferedWriter bufferedwriter = Files.newWriter(this.file, StandardCharsets.UTF_8); +@@ -0,0 +0,0 @@ public class GameProfileCache { + } catch (IOException ioexception) { + ; + } ++ // Paper start ++ }; ++ if (asyncSave) { ++ net.minecraft.server.MCUtil.scheduleAsyncTask(save); ++ } else { ++ save.run(); ++ } ++ // Paper end + + } + diff --git a/patches/server/Optimize-Voxel-Shape-Merging.patch b/patches/server/Optimize-Voxel-Shape-Merging.patch new file mode 100644 index 0000000000..4cfb49cc32 --- /dev/null +++ b/patches/server/Optimize-Voxel-Shape-Merging.patch @@ -0,0 +1,121 @@ +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/IndirectMerger.java b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/IndirectMerger.java +@@ -0,0 +0,0 @@ public class IndirectMerger implements IndexMerger { + private final int[] firstIndices; + private final int[] secondIndices; + private final int resultLength; ++ // Paper start ++ private static final int[] INFINITE_B_1 = new int[]{1, 1}; ++ private static final int[] INFINITE_B_0 = new int[]{0, 0}; ++ private static final int[] INFINITE_C = new int[]{0, 1}; ++ // Paper end + + public IndirectMerger(DoubleList first, DoubleList second, boolean includeFirstOnly, boolean includeSecondOnly) { + double d = Double.NaN; + int i = first.size(); + int j = second.size(); + int k = i + j; ++ // Paper start - optimize common path of infinity doublelist ++ int size = first.size(); ++ double tail = first.getDouble(size - 1); ++ double head = first.getDouble(0); ++ if (head == Double.NEGATIVE_INFINITY && tail == Double.POSITIVE_INFINITY && !includeFirstOnly && !includeSecondOnly && (size == 2 || size == 4)) { ++ this.result = second.toDoubleArray(); ++ this.resultLength = second.size(); ++ if (size == 2) { ++ this.firstIndices = INFINITE_B_0; ++ } else { ++ this.firstIndices = INFINITE_B_1; ++ } ++ this.secondIndices = INFINITE_C; ++ return; ++ } ++ // Paper end + this.result = new double[k]; + this.firstIndices = new int[k]; + this.secondIndices = new int[k]; +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -0,0 +0,0 @@ public final class Shapes { + } + + @VisibleForTesting +- protected static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { ++ private static IndexMerger createIndexMerger(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { // 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 (first.getDouble(0) == Double.NEGATIVE_INFINITY && first.getDouble(first.size() - 1) == Double.POSITIVE_INFINITY) { ++ return new IndirectMerger(first, second, includeFirst, includeSecond); ++ } ++ // Split out rest to hopefully inline the above ++ return lessCommonMerge(size, first, second, includeFirst, includeSecond); ++ } ++ ++ private static IndexMerger lessCommonMerge(int size, DoubleList first, DoubleList second, boolean includeFirst, boolean includeSecond) { + int i = first.size() - 1; + int j = second.size() - 1; ++ // Paper note - Rewrite below as optimized order if instead of nasty ternary + if (first instanceof CubePointRange && second instanceof CubePointRange) { + long l = lcm(i, j); + if ((long)size * l <= 256L) { +@@ -0,0 +0,0 @@ public final class Shapes { + } + } + +- if (first.getDouble(i) < second.getDouble(0) - 1.0E-7D) { ++ // Paper start - Identical happens more often than Disjoint ++ if (i == j && Objects.equals(first, second)) { ++ if (first instanceof IdenticalMerger) { ++ return (IndexMerger) first; ++ } else if (second instanceof IdenticalMerger) { ++ return (IndexMerger) second; ++ } ++ return new IdenticalMerger(first); ++ } else if (first.getDouble(i) < second.getDouble(0) - 1.0E-7D) { + return new NonOverlappingMerger(first, second, false); + } else if (second.getDouble(j) < first.getDouble(0) - 1.0E-7D) { + return new NonOverlappingMerger(second, first, true); + } else { +- return (IndexMerger)(i == j && Objects.equals(first, second) ? new IdenticalMerger(first) : new IndirectMerger(first, second, includeFirst, includeSecond)); ++ return new IndirectMerger(first, second, includeFirst, includeSecond); + } ++ // Paper end + } + + public interface DoubleLineConsumer { diff --git a/Spigot-Server-Patches/Optimize-World-Time-Updates.patch b/patches/server/Optimize-World-Time-Updates.patch similarity index 54% rename from Spigot-Server-Patches/Optimize-World-Time-Updates.patch rename to patches/server/Optimize-World-Time-Updates.patch index 3bd8bdf92b..f18326615b 100644 --- a/Spigot-Server-Patches/Optimize-World-Time-Updates.patch +++ b/patches/server/Optimize-World-Time-Updates.patch @@ -11,29 +11,29 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return chunk == null ? null : chunk.getFluidState(blockposition); + } + ++ @Override ++ public final boolean hasChunkAt(BlockPos pos) { ++ return getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4) != null; // Paper ++ } ++ + public final boolean isLoadedAndInBounds(BlockPos blockposition) { // Paper - final for inline + return getWorldBorder().isWithinBounds(blockposition) && getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) != null; + } diff --git a/patches/server/Optimize-WorldBorder-collision-checks-and-air.patch b/patches/server/Optimize-WorldBorder-collision-checks-and-air.patch new file mode 100644 index 0000000000..e6b6259ce7 --- /dev/null +++ b/patches/server/Optimize-WorldBorder-collision-checks-and-air.patch @@ -0,0 +1,50 @@ +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 Nameable, EntityAccess, CommandSource, n + AABB axisalignedbb = this.getBoundingBox(); + CollisionContext voxelshapecollision = CollisionContext.of(this); + VoxelShape voxelshape = this.level.getWorldBorder().getCollisionShape(); +- Stream stream = Shapes.joinIsNotEmpty(voxelshape, Shapes.create(axisalignedbb.deflate(1.0E-7D)), BooleanOp.AND) ? Stream.empty() : Stream.of(voxelshape); ++ Stream stream = !this.level.getWorldBorder().isWithinBounds(axisalignedbb) ? Stream.empty() : Stream.of(voxelshape); // Paper + Stream stream1 = this.level.getEntityCollisions(this, axisalignedbb.expandTowards(movement), (entity) -> { + return true; + }); +diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java ++++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +@@ -0,0 +0,0 @@ public class CollisionSpliterator extends AbstractSpliterator { + WorldBorder worldBorder = this.collisionGetter.getWorldBorder(); + AABB aABB = this.source.getBoundingBox(); + if (!isBoxFullyWithinWorldBorder(worldBorder, aABB)) { +- VoxelShape voxelShape = worldBorder.getCollisionShape(); +- if (!isOutsideBorder(voxelShape, aABB) && isCloseToBorder(voxelShape, aABB)) { +- action.accept(voxelShape); ++ // Paper start ++ if (worldBorder.isWithinBounds(aABB.deflate(1.0E-7D)) && !worldBorder.isWithinBounds(aABB.inflate(1.0E-7D))) { ++ action.accept(worldBorder.getCollisionShape()); ++ // Paper end + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java ++++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +@@ -0,0 +0,0 @@ public final class Shapes { + mutableBlockPos.set(axisCycle, q, r, p); + BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper + if (blockState == null) return 0.0D; // Paper +- if ((s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) { ++ if (!blockState.isAir() && (s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) { // Paper + initial = blockState.getCollisionShape(world, mutableBlockPos, context).collide(axis3, box.move((double)(-mutableBlockPos.getX()), (double)(-mutableBlockPos.getY()), (double)(-mutableBlockPos.getZ())), initial); + if (Math.abs(initial) < 1.0E-7D) { + return 0.0D; diff --git a/Spigot-Server-Patches/Optimize-brigadier-child-sorting-performance.patch b/patches/server/Optimize-brigadier-child-sorting-performance.patch similarity index 76% rename from Spigot-Server-Patches/Optimize-brigadier-child-sorting-performance.patch rename to patches/server/Optimize-brigadier-child-sorting-performance.patch index dd9ac2d9e7..50600fdade 100644 --- a/Spigot-Server-Patches/Optimize-brigadier-child-sorting-performance.patch +++ b/patches/server/Optimize-brigadier-child-sorting-performance.patch @@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 + import net.minecraft.commands.CommandSourceStack; public abstract class CommandNode implements Comparable> { - private Map> children = Maps.newLinkedHashMap(); @@ -18,12 +18,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 + +- this.children = this.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/patches/server/Optimize-call-to-getFluid-for-explosions.patch similarity index 57% rename from Spigot-Server-Patches/Optimize-call-to-getFluid-for-explosions.patch rename to patches/server/Optimize-call-to-getFluid-for-explosions.patch index 367c44a186..a76c97decb 100644 --- a/Spigot-Server-Patches/Optimize-call-to-getFluid-for-explosions.patch +++ b/patches/server/Optimize-call-to-getFluid-for-explosions.patch @@ -10,10 +10,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + BlockPos blockposition = new BlockPos(d4, d5, d6); + BlockState iblockdata = this.level.getBlockState(blockposition); +- FluidState fluid = this.level.getFluidState(blockposition); ++ FluidState fluid = iblockdata.getFluidState(); // Paper - if (optional.isPresent()) { + if (!this.level.isInWorldBounds(blockposition)) { + break; diff --git a/Spigot-Server-Patches/Optimize-explosions.patch b/patches/server/Optimize-explosions.patch similarity index 81% rename from Spigot-Server-Patches/Optimize-explosions.patch rename to patches/server/Optimize-explosions.patch index bc2ddb1253..395ba7eb16 100644 --- a/Spigot-Server-Patches/Optimize-explosions.patch +++ b/patches/server/Optimize-explosions.patch @@ -28,14 +28,14 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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: 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/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + } + // Paper end + ++ // 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.pos); ++ this.playersInMobSpawnRange = this.chunkMap.playerMobSpawnMap.getObjectsInRange(key); ++ this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); ++ } ++ // Paper end - optimise isOutsideOfRange ++ + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); + this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; +@@ -0,0 +0,0 @@ public class ChunkHolder { + this.setTicketLevel(level); + this.changedBlocksPerSection = new ShortSet[world.getSectionsCount()]; + this.chunkMap = (ChunkMap)playersWatchingChunkProvider; // Paper ++ this.updateRanges(); // Paper - optimise isOutsideOfRange + } + + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return MinecraftServer.getServer().getScaledTrackingDistance(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(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + 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.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange ++ // Paper start - optimise PlayerChunkMap#isOutsideRange ++ this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.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); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + 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 + // Paper start - no-tick view distance + this.playerViewDistanceBroadcastMap.remove(player); + this.playerViewDistanceTickMap.remove(player); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + 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, DistanceManager.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); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); + this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper + this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); +- this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); ++ this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper + this.overworldDataStorage = persistentStateManagerFactory; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + 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, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInChunkTickRange = newState; ++ } ++ }); ++ this.playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }, ++ (ServerPlayer player, int rangeX, int rangeZ, int currPosX, int currPosZ, int prevPosX, int prevPosZ, ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet newState) -> { ++ ChunkHolder playerChunk = ChunkMap.this.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(rangeX, rangeZ)); ++ if (playerChunk != null) { ++ playerChunk.playersInMobSpawnRange = newState; ++ } ++ }); ++ // Paper end - optimise PlayerChunkMap#isOutsideRange + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + } else { + if (holder != null) { + holder.setTicketLevel(level); ++ holder.updateRanges(); // Paper - optimise isOutsideOfRange + } + + if (holder != null) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + return this.isOutsideOfRange(chunkPos, false); + } + +- boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { +- int chunkRange = level.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; +- chunkRange = (chunkRange > 8) ? 8 : chunkRange; +- +- 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.toLong(); ++ // Paper start - optimise isOutsideOfRange ++ final boolean isOutsideOfRange(ChunkPos chunkcoordintpair, boolean reducedRange) { ++ return this.isOutsideOfRange(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); ++ } ++ final boolean isOutsideOfRange(ChunkHolder playerchunk, ChunkPos 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; ++ if (playersInRange == null) { ++ return true; ++ } ++ Object[] backingSet = playersInRange.getBackingSet(); + +- return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.getPlayers(i).noneMatch((entityplayer) -> { +- // Paper start - add PlayerNaturallySpawnCreaturesEvent +- 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 (reducedRange) { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (player.lastEntitySpawnRadiusSquared > euclideanDistanceSquared(chunkcoordintpair, player)) { ++ return false; // in range ++ } + } +- // Paper end +- return !entityplayer.isSpectator() && ChunkMap.euclideanDistanceSquared(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot +- }); ++ } else { ++ final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.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 ServerPlayer)) { ++ continue; ++ } ++ ServerPlayer player = (ServerPlayer) raw; ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (range > euclideanDistanceSquared(chunkcoordintpair, player)) { ++ return false; // in range ++ } ++ } ++ } ++ // no players in range ++ return true; + } ++ // Paper end - optimise isOutsideOfRange + + private boolean skipPlayer(ServerPlayer player) { + return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); +diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/DistanceManager.java ++++ b/src/main/java/net/minecraft/server/level/DistanceManager.java +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + final Long2ObjectMap> playersPerChunk = new Long2ObjectOpenHashMap(); + public final Long2ObjectOpenHashMap>> tickets = new Long2ObjectOpenHashMap(); + private final DistanceManager.ChunkTicketTracker ticketTracker = new DistanceManager.ChunkTicketTracker(); +- private final DistanceManager.FixedPlayerDistanceChunkTracker naturalSpawnChunkCounter = new DistanceManager.FixedPlayerDistanceChunkTracker(8); ++ public static final int MOB_SPAWN_RANGE = 8; // private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used + private final DistanceManager.PlayerTicketTracker playerTicketManager = new DistanceManager.PlayerTicketTracker(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 DistanceManager { + final Executor mainThreadExecutor; + private long ticketTickCounter; + ++ ChunkMap chunkMap; // Paper ++ + protected DistanceManager(Executor workerExecutor, Executor mainThreadExecutor) { + Objects.requireNonNull(mainThreadExecutor); + ProcessorHandle mailbox = ProcessorHandle.of("player ticket throttler", mainThreadExecutor::execute); +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + protected abstract ChunkHolder updateChunkScheduling(long pos, int level, @Nullable ChunkHolder holder, int k); + + public boolean runAllUpdates(ChunkMap playerchunkmap) { +- this.naturalSpawnChunkCounter.runAllUpdates(); ++ //this.f.a(); // Paper - no longer used + this.playerTicketManager.runAllUpdates(); + int i = Integer.MAX_VALUE - this.ticketTracker.runDistanceUpdates(Integer.MAX_VALUE); + boolean flag = i != 0; +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + ((ObjectSet) this.playersPerChunk.computeIfAbsent(i, (j) -> { + return new ObjectOpenHashSet(); + })).add(player); +- this.naturalSpawnChunkCounter.update(i, 0, true); ++ //this.f.update(i, 0, true); // Paper - no longer used + this.playerTicketManager.update(i, 0, true); + } + +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + if (objectset != null) objectset.remove(player); // Paper - some state corruption happens here, don't crash, clean up gracefully. + if (objectset == null || objectset.isEmpty()) { // Paper + this.playersPerChunk.remove(i); +- this.naturalSpawnChunkCounter.update(i, Integer.MAX_VALUE, false); ++ //this.f.update(i, Integer.MAX_VALUE, false); // Paper - no longer used + this.playerTicketManager.update(i, Integer.MAX_VALUE, false); + } + +@@ -0,0 +0,0 @@ public abstract class DistanceManager { + } + + public int getNaturalSpawnChunkCount() { +- this.naturalSpawnChunkCounter.runAllUpdates(); +- return this.naturalSpawnChunkCounter.chunks.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 hasPlayersNearby(long i) { +- this.naturalSpawnChunkCounter.runAllUpdates(); +- return this.naturalSpawnChunkCounter.chunks.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 getDebugStatus() { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + boolean flag1 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit + + if (!flag) { ++ // Paper start - optimize isOutisdeRange ++ ChunkMap playerChunkMap = this.chunkMap; ++ for (ServerPlayer player : this.level.players) { ++ if (!player.affectsSpawning || player.isSpectator()) { ++ playerChunkMap.playerMobSpawnMap.remove(player); ++ continue; ++ } ++ ++ int viewDistance = this.chunkMap.getEffectiveViewDistance(); ++ ++ // copied and modified from isOutisdeRange ++ int chunkRange = level.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > viewDistance) ? (byte)viewDistance : chunkRange; ++ chunkRange = (chunkRange > DistanceManager.MOB_SPAWN_RANGE) ? DistanceManager.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.getX()); ++ int chunkZ = net.minecraft.server.MCUtil.getChunkCoordinate(player.getZ()); ++ ++ 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.level.getProfiler().push("pollingChunks"); + int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); + boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper +- //Paper start - call player naturally spawn event +- int chunkRange = level.spigotConfig.mobSpawnRange; +- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; +- chunkRange = Math.min(chunkRange, 8); +- for (ServerPlayer entityPlayer : this.level.players()) { +- entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); +- entityPlayer.playerNaturallySpawnedEvent.callEvent(); +- }; +- // Paper end ++ // Paper - moved up + this.level.timings.chunkTicks.startTiming(); // Paper + final int[] chunksTicked = {0}; this.chunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + ChunkPos chunkcoordintpair = chunk.getPos(); + +- if (this.level.isPositionEntityTicking(chunkcoordintpair) && !this.chunkMap.noPlayersCloseForSpawning(chunkcoordintpair)) { ++ if (this.level.isPositionEntityTicking(chunkcoordintpair) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange + chunk.setInhabitedTime(chunk.getInhabitedTime() + j); +- if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot ++ if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper + } +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + // CraftBukkit end + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + ++ public double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + boolean needsChunkCenterUpdate; // Paper - no-tick view distance + diff --git a/patches/server/Optimize-isValidLocation-getType-and-getBlockData-fo.patch b/patches/server/Optimize-isValidLocation-getType-and-getBlockData-fo.patch new file mode 100644 index 0000000000..731ed0c46d --- /dev/null +++ b/patches/server/Optimize-isValidLocation-getType-and-getBlockData-fo.patch @@ -0,0 +1,193 @@ +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/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/Vec3i.java ++++ b/src/main/java/net/minecraft/core/Vec3i.java +@@ -0,0 +0,0 @@ public class Vec3i implements Comparable { + private int y; + private int z; + ++ // Paper start ++ public boolean isValidLocation(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) { ++ return getX() >= -30000000 && getZ() >= -30000000 && getX() < 30000000 && getZ() < 30000000 && !levelHeightAccessor.isOutsideBuildHeight(getY()); ++ } ++ public boolean isInvalidYLocation(net.minecraft.world.level.LevelHeightAccessor levelHeightAccessor) { ++ return levelHeightAccessor.isOutsideBuildHeight(getY()); ++ } ++ // Paper end ++ + public Vec3i(int x, int y, int z) { + this.x = x; + this.y = y; +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + public boolean isInWorldBounds(BlockPos pos) { +- return !this.isOutsideBuildHeight(pos) && Level.isInWorldBoundsHorizontal(pos); ++ return pos.isValidLocation(this); // Paper - use better/optimized check + } + + public static boolean isInSpawnableBounds(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -0,0 +0,0 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + return GameEventDispatcher.NOOP; + } + ++ BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/EmptyLevelChunk.java +@@ -0,0 +0,0 @@ public class EmptyLevelChunk extends LevelChunk { + super(world, pos, new EmptyLevelChunk.EmptyChunkBiomeContainer(world)); + } + ++ // Paper start ++ @Override public BlockState getType(int x, int y, int z) { ++ return Blocks.VOID_AIR.defaultBlockState(); ++ } ++ // Paper end + @Override + public BlockState getBlockState(BlockPos pos) { + return Blocks.VOID_AIR.defaultBlockState(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -0,0 +0,0 @@ public class ImposterProtoChunk extends ProtoChunk { + public BlockState getBlockState(BlockPos pos) { + return this.wrapped.getBlockState(pos); + } ++ // Paper start ++ public final BlockState getType(final int x, final int y, final int z) { ++ return this.wrapped.getBlockData(x, y, z); ++ } ++ // Paper end + + @Override + public FluidState getFluidState(BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + return this.sections; + } + ++ // Paper start - Optimize getBlockData to reduce instructions + @Override + public BlockState getBlockState(BlockPos pos) { +- int i = pos.getX(); +- int j = pos.getY(); +- int k = pos.getZ(); ++ return this.getBlockData(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ ++ public BlockState getType(final int x, final int y, final int z) { ++ return this.getBlockData(x, y, z); ++ } ++ public final BlockState getBlockData(final int x, final int y, final int z) { ++ // Method body / logic copied from below ++ final int i = this.getSectionIndex(y); ++ if (i < 0 || i >= this.sections.length || this.sections[i] == null || this.sections[i].nonEmptyBlockCount == 0) { ++ return Blocks.AIR.defaultBlockState(); ++ } ++ // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) ++ return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15); + ++ } ++ ++ public BlockState getBlockData_unused(int i, int j, int k) { ++ // Paper end + if (this.level.isDebug()) { + BlockState iblockdata = null; + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -0,0 +0,0 @@ public class LevelChunkSection { + public static final int SECTION_SIZE = 4096; + public static final Palette GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState()); + private final int bottomBlockY; +- private short nonEmptyBlockCount; ++ short nonEmptyBlockCount; // Paper - package-private + private short tickingBlockCount; + private short tickingFluidCount; +- private final PalettedContainer states; ++ final PalettedContainer states; // Paper - package-private + + public LevelChunkSection(int yOffset) { + this(yOffset, (short)0, (short)0, (short)0); +@@ -0,0 +0,0 @@ public class LevelChunkSection { + } + + public BlockState getBlockState(int x, int y, int z) { +- return this.states.get(x, y, z); ++ return this.states.get(y << 8 | z << 4 | x); // Paper - inline + } + + public FluidState getFluidState(int x, int y, int z) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + } + + public T get(int x, int y, int z) { +- return this.get(getIndex(x, y, z)); ++ return this.get(y << 8 | z << 4 | x); // Paper - inline + } + + protected T get(int index) { +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 ChunkAccess { + + @Override + public BlockState getBlockState(BlockPos pos) { +- int i = pos.getY(); +- if (this.isOutsideBuildHeight(i)) { ++ // Paper start ++ return getType(pos.getX(), pos.getY(), pos.getZ()); ++ } ++ public BlockState getType(final int x, final int y, final int z) { ++ if (this.isOutsideBuildHeight(y)) { + return Blocks.VOID_AIR.defaultBlockState(); + } else { +- LevelChunkSection levelChunkSection = this.getSections()[this.getSectionIndex(i)]; +- return LevelChunkSection.isEmpty(levelChunkSection) ? Blocks.AIR.defaultBlockState() : levelChunkSection.getBlockState(pos.getX() & 15, i & 15, pos.getZ() & 15); ++ LevelChunkSection chunksection = this.getSections()[this.getSectionIndex(y)]; ++ return chunksection == LevelChunk.EMPTY_SECTION || chunksection.isEmpty() ? Blocks.AIR.defaultBlockState() : chunksection.getBlockState(x & 15, y & 15, z & 15); + } + } ++ // Paper end + + @Override + public FluidState getFluidState(BlockPos pos) { diff --git a/Spigot-Server-Patches/Optimize-redstone-algorithm.patch b/patches/server/Optimize-redstone-algorithm.patch similarity index 82% rename from Spigot-Server-Patches/Optimize-redstone-algorithm.patch rename to patches/server/Optimize-redstone-algorithm.patch index b140e10da6..dbe064cb2d 100644 --- a/Spigot-Server-Patches/Optimize-redstone-algorithm.patch +++ b/patches/server/Optimize-redstone-algorithm.patch @@ -23,10 +23,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); @@ -36,7 +35,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + log("Using vanilla redstone algorithm."); + } + } - } ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); 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 @@ -48,14 +50,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.util.List; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; -+ -+import net.minecraft.core.BlockPosition; ++import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; -+import net.minecraft.world.level.World; ++import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.BlockRedstoneWire; -+import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.block.RedStoneWireBlock; ++import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.event.block.BlockRedstoneEvent; + +import com.google.common.collect.Lists; @@ -130,7 +131,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ + + /* Reference to BlockRedstoneWire object, which uses this accelerator */ -+ private final BlockRedstoneWire wire; ++ private final RedStoneWireBlock wire; + + /* + * Implementation: @@ -163,7 +164,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private List updateQueue1 = Lists.newArrayList(); + private List updateQueue2 = Lists.newArrayList(); + -+ public RedstoneWireTurbo(BlockRedstoneWire wire) { ++ public RedstoneWireTurbo(RedStoneWireBlock wire) { + this.wire = wire; + } + @@ -178,42 +179,42 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * the direction of signal flow is identified, the ordering of updates is completely + * reorganized. + */ -+ public static BlockPosition[] computeAllNeighbors(final BlockPosition pos) { ++ public static BlockPos[] computeAllNeighbors(final BlockPos pos) { + final int x = pos.getX(); + final int y = pos.getY(); + final int z = pos.getZ(); -+ final BlockPosition[] n = new BlockPosition[24]; ++ final BlockPos[] n = new BlockPos[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); ++ n[0] = new BlockPos(x - 1, y, z); ++ n[1] = new BlockPos(x + 1, y, z); ++ n[2] = new BlockPos(x, y - 1, z); ++ n[3] = new BlockPos(x, y + 1, z); ++ n[4] = new BlockPos(x, y, z - 1); ++ n[5] = new BlockPos(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); ++ n[6] = new BlockPos(x - 2, y, z); ++ n[7] = new BlockPos(x - 1, y - 1, z); ++ n[8] = new BlockPos(x - 1, y + 1, z); ++ n[9] = new BlockPos(x - 1, y, z - 1); ++ n[10] = new BlockPos(x - 1, y, z + 1); ++ n[11] = new BlockPos(x + 2, y, z); ++ n[12] = new BlockPos(x + 1, y - 1, z); ++ n[13] = new BlockPos(x + 1, y + 1, z); ++ n[14] = new BlockPos(x + 1, y, z - 1); ++ n[15] = new BlockPos(x + 1, y, z + 1); ++ n[16] = new BlockPos(x, y - 2, z); ++ n[17] = new BlockPos(x, y - 1, z - 1); ++ n[18] = new BlockPos(x, y - 1, z + 1); ++ n[19] = new BlockPos(x, y + 2, z); ++ n[20] = new BlockPos(x, y + 1, z - 1); ++ n[21] = new BlockPos(x, y + 1, z + 1); ++ n[22] = new BlockPos(x, y, z - 2); ++ n[23] = new BlockPos(x, y, z + 2); + return n; + } + @@ -318,10 +319,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + UNKNOWN, REDSTONE, OTHER + } + -+ IBlockData currentState; // Keep track of redstone wire value ++ BlockState 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 ++ BlockPos self; // UpdateNode's own position ++ BlockPos 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 @@ -332,14 +333,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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(); ++ 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); ++ private void identifyNode(final Level worldIn, final UpdateNode upd1) { ++ final BlockPos pos = upd1.self; ++ final BlockState oldState = worldIn.getBlockState(pos); + upd1.currentState = oldState; + + // Some neighbors of redstone wire are other kinds of blocks. @@ -364,10 +365,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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)) { ++ if (!wire.canSurvive(null, worldIn, pos)) { + // Pop off the redstone dust -+ Block.a(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO -+ worldIn.setAir(pos); ++ Block.popResource(worldIn, pos, new ItemStack(Items.REDSTONE)); // TODO ++ worldIn.removeBlock(pos, false); + + // Mark this position as not being redstone wire + upd1.type = UpdateNode.Type.OTHER; @@ -459,8 +460,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + /* + * 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; ++ private void updateNode(final Level worldIn, final UpdateNode upd1, final int layer) { ++ final BlockPos pos = upd1.self; + + // Mark this redstone wire as having been visited so that it can be used + // to calculate direction of information flow. @@ -470,7 +471,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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; ++ final BlockState 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 @@ -478,7 +479,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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; ++ BlockState newState; + if (old_current_change) { + newState = wire.calculateCurrentChanges(worldIn, pos, pos, oldState); + } else { @@ -504,11 +505,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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; ++ private void findNeighbors(final Level worldIn, final UpdateNode upd1) { ++ final BlockPos pos = upd1.self; + + // Get the list of neighbor coordinates -+ final BlockPosition[] neighbors = computeAllNeighbors(pos); ++ final BlockPos[] neighbors = computeAllNeighbors(pos); + + // Temporary array of neighbors in cardinal ordering + final UpdateNode[] neighbor_nodes = new UpdateNode[24]; @@ -518,7 +519,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + for (int i=0; i<24; i++) { + // Look up each neighbor in the node cache -+ final BlockPosition pos2 = neighbors[i]; ++ final BlockPos pos2 = neighbors[i]; + UpdateNode upd2 = nodeCache.get(pos2); + if (upd2 == null) { + // If this is a previously unreached position, create @@ -595,13 +596,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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) { ++ private void propagateChanges(final Level 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; ++ final BlockPos pos = upd1.self; + + // All neighbors may be scheduled for layer N+1 + final int layer1 = layer + 1; @@ -662,7 +663,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * that is a function of distance from the initial call to + * this.neighborChanged. + */ -+ private void breadthFirstWalk(final World worldIn) { ++ private void breadthFirstWalk(final Level worldIn) { + shiftQueue(); + currentWalkLayer = 1; + @@ -729,7 +730,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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) { ++ private BlockState scheduleReentrantNeighborChanged(final Level worldIn, final BlockPos pos, final BlockState newState, final BlockPos 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. @@ -789,11 +790,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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) { ++ public BlockState updateSurroundingRedstone(final Level worldIn, final BlockPos pos, final BlockState state, final BlockPos 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); ++ final BlockState newState = wire.calculateCurrentChanges(worldIn, pos, pos, state); + + // If no change, exit + if (newState == state) { @@ -857,21 +858,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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(); ++ private BlockState calculateCurrentChanges(final Level worldIn, final UpdateNode upd) { ++ BlockState state = upd.currentState; ++ final int i = state.getValue(RedStoneWireBlock.POWER).intValue(); + int j = 0; + j = getMaxCurrentStrength(upd, j); + int l = 0; + -+ wire.setCanProvidePower(false); ++ wire.shouldSignal = 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); ++ final int k = worldIn.getBestNeighborSignal(upd.self); ++ wire.shouldSignal = 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 @@ -889,7 +890,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 ++ boolean center_up_is_cube = center_up.currentState.isRedstoneConductor(worldIn, center_up.self); // TODO + + for (int m = 0; m < 4; m++) { + // Get the neighbor array index of each of the four cardinal @@ -903,7 +904,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // Also check the positions above and below the cardinal + // neighbors -+ boolean neighbor_is_cube = neighbor.currentState.isOccluding(worldIn, neighbor.self); // TODO ++ boolean neighbor_is_cube = neighbor.currentState.isRedstoneConductor(worldIn, neighbor.self); // TODO + if (!neighbor_is_cube) { + UpdateNode neighbor_down = upd.neighbor_nodes[rs_neighbors_dn[m]]; + l = getMaxCurrentStrength(neighbor_down, l); @@ -928,7 +929,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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); ++ worldIn.getCraftServer().getPluginManager().callEvent(event); + j = event.getNewCurrent(); + } + @@ -937,10 +938,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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); ++ BlockPos pos = new BlockPos(upd.self.getX(), upd.self.getY(), upd.self.getZ()); ++ if (wire.canSurvive(null, worldIn, pos)) { ++ state = state.setValue(RedStoneWireBlock.POWER, Integer.valueOf(j)); ++ worldIn.setBlock(upd.self, state, 2); + } + } + @@ -953,34 +954,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + */ + 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(); ++ final int i = upd.currentState.getValue(RedStoneWireBlock.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 +diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.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 +--- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -0,0 +0,0 @@ package net.minecraft.world.level.block; @@ -989,17 +970,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); +@@ -0,0 +0,0 @@ public class RedStoneWireBlock extends Block { + return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER); } + // Paper start - Optimize redstone @@ -1011,12 +983,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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) { ++ private void updateSurroundingRedstone(Level worldIn, BlockPos pos, BlockState state, BlockPos source) { + if (worldIn.paperConfig.useEigencraftRedstone) { + turbo.updateSurroundingRedstone(worldIn, pos, state, source); + return; + } -+ a(worldIn, pos, state); ++ updatePowerStrength(worldIn, pos, state); + } + + /* @@ -1027,14 +999,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * 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); ++ public BlockState calculateCurrentChanges(Level worldIn, BlockPos pos1, BlockPos pos2, BlockState state) { ++ BlockState iblockstate = state; ++ int i = state.getValue(POWER); + int j = 0; -+ j = this.getPower(j, worldIn.getType(pos2)); -+ this.setCanProvidePower(false); -+ int k = worldIn.isBlockIndirectlyGettingPowered(pos1); -+ this.setCanProvidePower(true); ++ j = this.getPower(j, worldIn.getBlockState(pos2)); ++ this.shouldSignal = false; ++ int k = worldIn.getBestNeighborSignal(pos1); ++ this.shouldSignal = true; + + if (!worldIn.paperConfig.useEigencraftRedstone) { + // This code is totally redundant to if statements just below the loop. @@ -1051,20 +1023,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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); ++ for (Direction enumfacing : Direction.Plane.HORIZONTAL) { ++ BlockPos blockpos = pos1.relative(enumfacing); + boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); + + if (flag) { -+ l = this.getPower(l, worldIn.getType(blockpos)); ++ l = this.getPower(l, worldIn.getBlockState(blockpos)); + } + -+ if (worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && !worldIn.getType(pos1.up()).isOccluding(worldIn, pos1)) { ++ if (worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && !worldIn.getBlockState(pos1.above()).isRedstoneConductor(worldIn, pos1)) { + if (flag && pos1.getY() >= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.up())); ++ l = this.getPower(l, worldIn.getBlockState(blockpos.above())); + } -+ } else if (!worldIn.getType(blockpos).isOccluding(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { -+ l = this.getPower(l, worldIn.getType(blockpos.down())); ++ } else if (!worldIn.getBlockState(blockpos).isRedstoneConductor(worldIn, blockpos) && flag && pos1.getY() <= pos2.getY()) { ++ l = this.getPower(l, worldIn.getBlockState(blockpos.below())); + } + } + } @@ -1094,10 +1066,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + if (i != j) { -+ state = state.set(POWER, j); ++ state = state.setValue(POWER, j); + -+ if (worldIn.getType(pos1) == iblockstate) { -+ worldIn.setTypeAndData(pos1, state, 2); ++ if (worldIn.getBlockState(pos1) == iblockstate) { ++ worldIn.setBlock(pos1, state, 2); + } + + // 1.16(.1?) dropped the need for blocks needing updates. @@ -1117,42 +1089,41 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + - private void a(World world, BlockPosition blockposition, IBlockData iblockdata) { - int i = this.a(world, blockposition); + private void updatePowerStrength(Level world, BlockPos pos, BlockState state) { + int i = this.calculateTargetStrength(world, pos); -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { +@@ -0,0 +0,0 @@ public class RedStoneWireBlock 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; ++ private int getPower(int min, BlockState iblockdata) { return Math.max(min, getWireSignal(iblockdata)); } // Paper - Optimize redstone + private int getWireSignal(BlockState state) { + return state.is((Block) this) ? (Integer) state.getValue(RedStoneWireBlock.POWER) : 0; } -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { +@@ -0,0 +0,0 @@ public class RedStoneWireBlock 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(); + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.is(state.getBlock()) && !world.isClientSide) { +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone + Iterator iterator = Direction.Plane.VERTICAL.iterator(); while (iterator.hasNext()) { -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - world.applyPhysics(blockposition.shift(enumdirection), this); +@@ -0,0 +0,0 @@ public class RedStoneWireBlock extends Block { + world.updateNeighborsAt(pos.relative(enumdirection), this); } -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, null); // Paper - Optimize redstone - this.d(world, blockposition); +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone + this.updateNeighborsOfNeighboringWires(world, pos); } } -@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block { - public void doPhysics(IBlockData iblockdata, World world, BlockPosition blockposition, Block block, BlockPosition blockposition1, boolean flag) { +@@ -0,0 +0,0 @@ public class RedStoneWireBlock extends Block { + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { if (!world.isClientSide) { - if (iblockdata.canPlace(world, blockposition)) { -- this.a(world, blockposition, iblockdata); -+ this.updateSurroundingRedstone(world, blockposition, iblockdata, blockposition1); // Paper - Optimize redstone + if (state.canSurvive(world, pos)) { +- this.updatePowerStrength(world, pos, state); ++ this.updateSurroundingRedstone(world, pos, state, fromPos); // Paper - Optimize redstone } else { - c(iblockdata, world, blockposition); - world.a(blockposition, false); + dropResources(state, world, pos); + world.removeBlock(pos, false); diff --git a/Spigot-Server-Patches/Optimize-sending-packets-to-nearby-locations-sounds-.patch b/patches/server/Optimize-sending-packets-to-nearby-locations-sounds-.patch similarity index 58% rename from Spigot-Server-Patches/Optimize-sending-packets-to-nearby-locations-sounds-.patch rename to patches/server/Optimize-sending-packets-to-nearby-locations-sounds-.patch index 2fef302423..c0cfeb1f02 100644 --- a/Spigot-Server-Patches/Optimize-sending-packets-to-nearby-locations-sounds-.patch +++ b/patches/server/Optimize-sending-packets-to-nearby-locations-sounds-.patch @@ -17,28 +17,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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) { + public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, 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; +- ServerPlayer entityplayer = (ServerPlayer) this.players.get(i); ++ ServerLevel world = null; ++ if (player != null && player.level instanceof ServerLevel) { ++ world = (ServerLevel) player.level; + } - // 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())) { +- if (player != null && player instanceof ServerPlayer && !entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity())) { - continue; + // Paper start + if (world == null) { -+ world = server.getWorldServer(resourcekey); ++ world = server.getLevel(worldKey); + } -+ PlayerChunkMap chunkMap = world != null ? world.getChunkProvider().playerChunkMap : null; ++ net.minecraft.server.level.ChunkMap chunkMap = world != null ? world.getChunkSource().chunkMap : 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); ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet nearbyPlayers = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(MCUtil.fastFloor(x) >> 4, MCUtil.fastFloor(z) >> 4); + if (nearbyPlayers == null) { + return; } @@ -46,8 +46,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + for (Object object : backingSet) { -+ if (!(object instanceof EntityPlayer)) continue; -+ EntityPlayer entityplayer = (EntityPlayer) object; ++ if (!(object instanceof ServerPlayer)) continue; ++ ServerPlayer entityplayer = (ServerPlayer) object; + // Paper end + + // CraftBukkit start - Test if player receiving packet can see the source of the packet @@ -56,8 +56,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + //} // 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(); +- if (entityplayer != player && entityplayer.level.dimension() == worldKey) { ++ if (entityplayer != player && entityplayer.level.dimension() == worldKey && (!(player instanceof ServerPlayer) || entityplayer.getBukkitEntity().canSee(((ServerPlayer) player).getBukkitEntity()))) { // Paper + double d4 = x - entityplayer.getX(); + double d5 = y - entityplayer.getY(); + double d6 = z - entityplayer.getZ(); diff --git a/Spigot-Server-Patches/Optimize-the-advancement-data-player-iteration-to-be.patch b/patches/server/Optimize-the-advancement-data-player-iteration-to-be.patch similarity index 60% rename from Spigot-Server-Patches/Optimize-the-advancement-data-player-iteration-to-be.patch rename to patches/server/Optimize-the-advancement-data-player-iteration-to-be.patch index 5098b7151c..2fdb6042cc 100644 --- a/Spigot-Server-Patches/Optimize-the-advancement-data-player-iteration-to-be.patch +++ b/patches/server/Optimize-the-advancement-data-player-iteration-to-be.patch @@ -5,14 +5,14 @@ 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 +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.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 { +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -0,0 +0,0 @@ public class PlayerAdvancements { } - private void e(Advancement advancement) { + private void ensureVisibility(Advancement advancement) { + // Paper start + e(advancement, IterationEntryPoint.ROOT); + } @@ -23,17 +23,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + private void e(Advancement advancement, IterationEntryPoint entryPoint) { + // Paper end - boolean flag = this.f(advancement); - boolean flag1 = this.h.contains(advancement); + boolean flag = this.shouldBeVisible(advancement); + boolean flag1 = this.visible.contains(advancement); -@@ -0,0 +0,0 @@ public class AdvancementDataPlayer { +@@ -0,0 +0,0 @@ public class PlayerAdvancements { } - if (flag != flag1 && advancement.b() != null) { -- this.e(advancement.b()); + if (flag != flag1 && advancement.getParent() != null) { +- this.ensureVisibility(advancement.getParent()); + // 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); ++ this.e(advancement.getParent(), 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 @@ -42,12 +42,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } // Paper end + - Iterator iterator = advancement.e().iterator(); + Iterator iterator = advancement.getChildren().iterator(); while (iterator.hasNext()) { Advancement advancement1 = (Advancement) iterator.next(); -- this.e(advancement1); +- this.ensureVisibility(advancement1); + this.e(advancement1, IterationEntryPoint.ITERATOR); // Paper - Mark this call as being from iteration } diff --git a/Spigot-Server-Patches/Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/Option-for-maximum-exp-value-when-merging-orbs.patch similarity index 74% rename from Spigot-Server-Patches/Option-for-maximum-exp-value-when-merging-orbs.patch rename to patches/server/Option-for-maximum-exp-value-when-merging-orbs.patch index ecb9b4572d..f7350d4804 100644 --- a/Spigot-Server-Patches/Option-for-maximum-exp-value-when-merging-orbs.patch +++ b/patches/server/Option-for-maximum-exp-value-when-merging-orbs.patch @@ -9,22 +9,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + } - } ++ + public double squidMaxSpawnHeight; + private void squidMaxSpawnHeight() { + squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D); 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; + net.minecraft.world.entity.ExperienceOrb xp = (net.minecraft.world.entity.ExperienceOrb) 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 @@ -32,30 +34,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); + List entities = world.getEntities(entity, entity.getBoundingBox().inflate(radius, radius, radius)); for (Entity e : entities) { - if (e instanceof EntityExperienceOrb) { - EntityExperienceOrb loopItem = (EntityExperienceOrb) e; -- if (!loopItem.dead) { -- xp.value += loopItem.value; -- loopItem.die(); + if (e instanceof net.minecraft.world.entity.ExperienceOrb) { + net.minecraft.world.entity.ExperienceOrb loopItem = (net.minecraft.world.entity.ExperienceOrb) e; +- if (!loopItem.isRemoved()) { + // Paper start -+ if (!loopItem.dead && !(maxValue > 0 && loopItem.value >= maxValue)) { ++ if (!loopItem.isRemoved() && !(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 + xp.value += loopItem.value; + loopItem.discard(); ++ } // Paper end } } } -+ + } // Paper end - End iteration skip check - All tweaking ends here } // Spigot end - } else if (!(entity instanceof EntityPlayer)) { + } else if (!(entity instanceof ServerPlayer)) { diff --git a/patches/server/Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server/Option-to-prevent-armor-stands-from-doing-entity-loo.patch new file mode 100644 index 0000000000..ae004d6811 --- /dev/null +++ b/patches/server/Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -0,0 +1,50 @@ +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/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java +@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity { + + @Override + protected void pushEntities() { ++ if (!level.paperConfig.armorStandEntityLookups) return; // Paper + List list = this.level.getEntities(this, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); + + for (int i = 0; i < list.size(); ++i) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper end + } + } ++ // Paper start - Prevent armor stands from doing entity lookups ++ @Override ++ public boolean noCollision(@Nullable Entity entity, AABB box) { ++ if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level.paperConfig.armorStandEntityLookups) return false; ++ return LevelAccessor.super.noCollision(entity, box); ++ } ++ // Paper end + + public Explosion explode(@Nullable Entity entity, double x, double y, double z, float power, Explosion.BlockInteraction destructionType) { + return this.explode(entity, (DamageSource) null, (ExplosionDamageCalculator) null, x, y, z, power, false, destructionType); diff --git a/Spigot-Server-Patches/Option-to-remove-corrupt-tile-entities.patch b/patches/server/Option-to-remove-corrupt-tile-entities.patch similarity index 69% rename from Spigot-Server-Patches/Option-to-remove-corrupt-tile-entities.patch rename to patches/server/Option-to-remove-corrupt-tile-entities.patch index fcfdfda214..ff061abdb6 100644 --- a/Spigot-Server-Patches/Option-to-remove-corrupt-tile-entities.patch +++ b/patches/server/Option-to-remove-corrupt-tile-entities.patch @@ -18,18 +18,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.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)); +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16)); e.printStackTrace(); ServerInternalException.reportInternalException(e); + -+ if (this.world.paperConfig.removeCorruptTEs) { -+ this.removeTileEntity(tileentity.getPosition()); -+ this.markDirty(); ++ if (this.level.paperConfig.removeCorruptTEs) { ++ this.removeBlockEntity(blockEntity.getBlockPos()); ++ this.markUnsaved(); + org.bukkit.Bukkit.getLogger().info("Removing corrupt tile entity"); + } // Paper end diff --git a/Spigot-Server-Patches/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch similarity index 82% rename from Spigot-Server-Patches/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch rename to patches/server/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch index f32e2e0813..b901efd33f 100644 --- a/Spigot-Server-Patches/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ b/patches/server/Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -29,12 +29,12 @@ diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/m 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; +@@ -0,0 +0,0 @@ import net.kyori.adventure.text.TextReplacementConfig; + import net.kyori.adventure.text.event.ClickEvent; import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.EntityPlayer; -+import net.minecraft.world.scores.ScoreboardTeam; -+import net.minecraft.world.scores.ScoreboardTeamBase; + import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.scores.PlayerTeam; ++import net.minecraft.world.scores.Team; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.CraftWorld; @@ -46,9 +46,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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(); ++ final ServerPlayer ep = player.getHandle(); ++ net.minecraft.network.chat.Component name = ep.getName(); ++ final Team team = ep.getTeam(); + if (team != null) { + name = team.getFormattedName(name); + } @@ -59,7 +59,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 PaperAdventure.asAdventure(PlayerTeam.formatNameForTeam(player.getHandle().getTeam(), player.getHandle().getName())); + } return player.displayName(); } diff --git a/patches/server/Optional-TNT-doesn-t-move-in-water.patch b/patches/server/Optional-TNT-doesn-t-move-in-water.patch new file mode 100644 index 0000000000..c5764db659 --- /dev/null +++ b/patches/server/Optional-TNT-doesn-t-move-in-water.patch @@ -0,0 +1,82 @@ +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 @@ 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/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -0,0 +0,0 @@ public class ServerEntity { + private boolean wasRiding; + private boolean wasOnGround; + // CraftBukkit start +- private final Set trackedPlayers; ++ final Set trackedPlayers; // Paper - private -> package + + public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer> consumer, Set trackedPlayers) { + this.trackedPlayers = trackedPlayers; +diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java ++++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +@@ -0,0 +0,0 @@ public class PrimedTnt extends Entity { + } + } + ++ // Paper start - Optional prevent TNT from moving in water ++ if (!this.isRemoved() && this.wasTouchingWater && this.level.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. ++ net.minecraft.server.level.ChunkMap.TrackedEntity ete = ((net.minecraft.server.level.ServerLevel)this.level).getChunkSource().chunkMap.entityMap.get(this.getId()); ++ if (ete != null) { ++ net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket velocityPacket = new net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket(this); ++ net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket positionPacket = new net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket(this); ++ ++ ete.seenBy.stream() ++ .filter(viewer -> (viewer.getPlayer().getX() - this.getX()) * (viewer.getPlayer().getY() - this.getY()) * (viewer.getPlayer().getZ() - this.getZ()) < 16 * 16) ++ .forEach(viewer -> { ++ viewer.send(velocityPacket); ++ viewer.send(positionPacket); ++ }); ++ } ++ } ++ // Paper end + } + + private void explode() { +@@ -0,0 +0,0 @@ public class PrimedTnt extends Entity { + public Packet getAddEntityPacket() { + return new ClientboundAddEntityPacket(this); + } ++ ++ // Paper start - Optional prevent TNT from moving in water ++ @Override ++ public boolean isPushedByFluid() { ++ return !level.paperConfig.preventTntFromMovingInWater && super.isPushedByFluid(); ++ } ++ // Paper end + } diff --git a/Spigot-Server-Patches/Paper-Metrics.patch b/patches/server/Paper-Metrics.patch similarity index 99% rename from Spigot-Server-Patches/Paper-Metrics.patch rename to patches/server/Paper-Metrics.patch index 32d531b4cf..fbf853967f 100644 --- a/Spigot-Server-Patches/Paper-Metrics.patch +++ b/patches/server/Paper-Metrics.patch @@ -618,7 +618,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + })); + + 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("online_mode", () -> Bukkit.getOnlineMode() ? "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", () -> { @@ -722,7 +722,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + /* // Paper - Replace with our own - if ( metrics == null ) + if ( SpigotConfig.metrics == null ) { try @@ -0,0 +0,0 @@ public class SpigotConfig diff --git a/Spigot-Server-Patches/Paper-config-files.patch b/patches/server/Paper-config-files.patch similarity index 77% rename from Spigot-Server-Patches/Paper-config-files.patch rename to patches/server/Paper-config-files.patch index 80abac900e..ba1d2176c1 100644 --- a/Spigot-Server-Patches/Paper-config-files.patch +++ b/patches/server/Paper-config-files.patch @@ -19,13 +19,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; -+import net.minecraft.server.level.ChunkProviderServer; -+import net.minecraft.server.level.WorldServer; ++import net.minecraft.server.level.ServerChunkCache; ++import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; -+import net.minecraft.world.entity.EntityTypes; -+import net.minecraft.world.level.ChunkCoordIntPair; ++import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.level.ChunkPos; +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.Bukkit; @@ -65,7 +65,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + 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()); ++ commandSender.sendMessage(ChatColor.RED + "I'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."); // Sorry, kashike + return false; + } + @@ -80,7 +80,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)); ++ return getListMatchingLast(sender, args, EntityType.getEntityNameList().stream().map(ResourceLocation::toString).sorted().toArray(String[]::new)); + break; + } + return Collections.emptyList(); @@ -116,7 +116,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + while (iterator.hasNext()) { + Object object = iterator.next(); + -+ if (object instanceof MinecraftKey && matches(last, ((MinecraftKey) object).getKey())) { ++ if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) { + results.add(String.valueOf(object)); + } + } @@ -151,7 +151,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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"); ++ Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version"); + if (ver != null) { + ver.execute(sender, commandLabel, new String[0]); + break; @@ -185,7 +185,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + filter = args[2]; + } + final String cleanfilter = filter.replace("?", ".?").replace("*", ".*?"); -+ Set names = EntityTypes.getEntityNameList().stream() ++ Set names = EntityType.getEntityNameList().stream() + .filter(n -> n.toString().matches(cleanfilter)) + .collect(Collectors.toSet()); + @@ -207,34 +207,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return; + } + -+ Map>> list = Maps.newHashMap(); ++ 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(); ++ ServerLevel world = ((CraftWorld) Bukkit.getWorld(worldName)).getHandle(); + -+ Map nonEntityTicking = Maps.newHashMap(); -+ ChunkProviderServer chunkProviderServer = world.getChunkProvider(); ++ Map nonEntityTicking = Maps.newHashMap(); ++ ServerChunkCache chunkProviderServer = world.getChunkSource(); + -+ Collection entities = world.entitiesById.values(); -+ entities.forEach(e -> { -+ MinecraftKey key = new MinecraftKey(""); // TODO: update in next patch ++ world.getAllEntities().forEach(e -> { ++ ResourceLocation key = new ResourceLocation(""); // TODO: update in next patch + -+ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); -+ ChunkCoordIntPair chunk = new ChunkCoordIntPair(e.chunkX, e.chunkZ); ++ MutablePair> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap())); ++ ChunkPos chunk = e.chunkPosition(); + info.left++; + info.right.put(chunk, info.right.getOrDefault(chunk, 0) + 1); -+ if (!chunkProviderServer.isInEntityTickingChunk(e)) { ++ if (!chunkProviderServer.isPositionTicking(e)) { + nonEntityTicking.merge(key, Integer.valueOf(1), Integer::sum); + } + }); + + if (names.size() == 1) { -+ MinecraftKey name = names.iterator().next(); -+ Pair> info = list.get(name); ++ ResourceLocation 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."); @@ -243,9 +242,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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)"))); ++ .limit(10).forEach(e -> sender.sendMessage(" " + e.getValue() + ": " + e.getKey().x + ", " + e.getKey().z + (chunkProviderServer.isPositionTicking(e.getKey().toLong()) ? " (Ticking)" : " (Non-Ticking)"))); + } else { -+ List> info = list.entrySet().stream() ++ 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())) @@ -289,7 +288,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + MinecraftServer console = MinecraftServer.getServer(); + com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); -+ for (WorldServer world : console.getWorlds()) { ++ for (ServerLevel world : console.getAllLevels()) { + world.paperConfig.init(); + } + console.server.reloadCount++; @@ -567,17 +566,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 dedicatedserversettings = new DedicatedServerSettings(optionset); // CraftBukkit - CLI argument support - dedicatedserversettings.save(); + dedicatedserversettings.forceSave(); + // 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); + Path path1 = Paths.get("eula.txt"); + Eula eula = new Eula(path1); @@ -0,0 +0,0 @@ public class Main { @@ -597,14 +596,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // 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); + public static void forceUpgrade(LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, boolean eraseCache, BooleanSupplier booleansupplier, ImmutableSet> worlds) { // CraftBukkit + Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit + WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache); 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 +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface org.spigotmc.SpigotConfig.init((java.io.File) options.valueOf("spigot-settings")); org.spigotmc.SpigotConfig.registerCommands(); // Spigot end @@ -618,76 +617,77 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + this.setPvpAllowed(dedicatedserverproperties.pvp); + this.setFlightAllowed(dedicatedserverproperties.allowFlight); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.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 { +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos; + import net.minecraft.core.SectionPos; + import net.minecraft.network.protocol.Packet; + import net.minecraft.server.level.progress.ChunkProgressListener; ++import net.minecraft.util.Mth; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.util.profiling.ProfilerFiller; + import net.minecraft.util.thread.BlockableEventLoop; +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { } } -- @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 ++ // Paper start - helper ++ public boolean isPositionTicking(Entity entity) { ++ return this.isPositionTicking(ChunkPos.asLong(Mth.floor(entity.getX()) >> 4, Mth.floor(entity.getZ()) >> 4)); ++ } ++ // Paper end ++ + public boolean isPositionTicking(long i) { + return this.checkChunkFuture(i, (Function>>) ChunkHolder::getTickingChunkFuture); // 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 +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.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; +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -0,0 +0,0 @@ import com.google.common.collect.ImmutableSet; + import java.util.List; import java.util.Optional; + import java.util.Spliterator; +import java.util.Set; // Paper import java.util.UUID; + import java.util.function.Consumer; 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); - } +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + + T create(EntityType type, Level world); } + + // Paper start -+ public static Set getEntityNameList() { -+ return IRegistry.ENTITY_TYPE.keySet(); ++ public static Set getEntityNameList() { ++ return Registry.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 +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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 { +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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 + public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; -@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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 + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, final DimensionType 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.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot ++ this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName(), this.spigotConfig); // Paper this.generator = gen; - this.world = new CraftWorld((WorldServer) this, gen, env); - this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit + this.world = new CraftWorld((ServerLevel) this, gen, env); + this.ticksPerAnimalSpawns = this.getCraftServer().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 @@ -697,9 +697,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); + for (ServerLevel world : this.console.getAllLevels()) { + world.serverLevelData.setDifficulty(config.difficulty); + world.setSpawnSettings(config.spawnMonsters, config.spawnAnimals); @@ -0,0 +0,0 @@ public final class CraftServer implements Server { world.ticksPerAmbientSpawns = this.getTicksPerAmbientSpawns(); } @@ -707,17 +707,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + world.paperConfig.init(); // Paper } - pluginManager.clearPlugins(); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - resetRecipes(); - reloadData(); + this.pluginManager.clearPlugins(); + this.commandMap.clearCommands(); + this.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"); + this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); + this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); @@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return spigot; + return this.spigot; } // Spigot end + @@ -771,50 +770,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } }; -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/patches/server/Paper-dumpitem-command.patch similarity index 63% rename from Spigot-Server-Patches/Paper-dumpitem-command.patch rename to patches/server/Paper-dumpitem-command.patch index 60e484616c..8a62c96486 100644 --- a/Spigot-Server-Patches/Paper-dumpitem-command.patch +++ b/patches/server/Paper-dumpitem-command.patch @@ -9,14 +9,14 @@ diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/ 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 net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.ThreadedLevelLightEngine; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.level.ChunkPos; ++import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.MCUtil; + import org.apache.commons.lang3.tuple.MutablePair; @@ -0,0 +0,0 @@ import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; @@ -31,8 +31,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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(); +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight", "syncloadinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight", "syncloadinfo", "dumpitem").build(); public PaperCommand(String name) { super(name); @@ -47,17 +47,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 doDebug(sender, args); break; @@ -0,0 +0,0 @@ public class PaperCommand extends Command { - return true; - } + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); + } + private void doDumpItem(CommandSender sender) { ++ if (!(sender instanceof Player)) { ++ sender.sendMessage("Only players can use this command"); ++ return; ++ } + ItemStack itemInHand = ((CraftPlayer) sender).getItemInHand(); + net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(itemInHand); -+ NBTTagCompound tag = itemStack.getTag(); ++ net.minecraft.nbt.CompoundTag tag = itemStack.getTag(); + if (tag != null) { -+ String nbt = org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(tag.getNbtPrettyComponent()); -+ Bukkit.getConsoleSender().sendMessage(nbt); -+ sender.sendMessage(nbt); ++ net.kyori.adventure.text.Component nbtComponent = io.papermc.paper.adventure.PaperAdventure.asAdventure(net.minecraft.nbt.NbtUtils.toPrettyComponent(tag)); ++ Bukkit.getConsoleSender().sendMessage(nbtComponent); ++ sender.sendMessage(nbtComponent); + } else { + sender.sendMessage("Item does not have NBT"); + } @@ -66,15 +70,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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/patches/server/Per-Player-View-Distance-API-placeholders.patch b/patches/server/Per-Player-View-Distance-API-placeholders.patch new file mode 100644 index 0000000000..d9bd18fa55 --- /dev/null +++ b/patches/server/Per-Player-View-Distance-API-placeholders.patch @@ -0,0 +1,42 @@ +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/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ import org.bukkit.inventory.MainHand; + + public class ServerPlayer extends Player { + ++ public final int getViewDistance() { return this.getLevel().getChunkSource().chunkMap.viewDistance - 1; } // Paper - placeholder ++ + private static final Logger LOGGER = LogManager.getLogger(); + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; + private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; +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.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message); + } + } ++ ++ @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 + + @Override diff --git a/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch new file mode 100644 index 0000000000..40c2386349 --- /dev/null +++ b/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -0,0 +1,136 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public boolean wonGame; + 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.ClientboundSetHealthPacket queuedHealthUpdatePacket; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +@@ -0,0 +0,0 @@ import java.util.Random; + import net.minecraft.core.BlockPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.stats.Stats; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.monster.PatrollingMonster; +-import net.minecraft.world.entity.player.Player; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.CustomSpawner; + import net.minecraft.world.level.GameRules; +@@ -0,0 +0,0 @@ public class PatrolSpawner implements CustomSpawner { + + @Override + public int tick(ServerLevel world, boolean spawnMonsters, boolean spawnAnimals) { +- if (world.paperConfig.disablePillagerPatrols) return 0; // Paper ++ if (world.paperConfig.disablePillagerPatrols || world.paperConfig.patrolSpawnChance == 0) return 0; // Paper + if (!spawnMonsters) { + return 0; + } else if (!world.getGameRules().getBoolean(GameRules.RULE_DO_PATROL_SPAWNING)) { +@@ -0,0 +0,0 @@ public class PatrolSpawner implements CustomSpawner { + } else { + Random random = world.random; + +- --this.nextTick; +- if (this.nextTick > 0) { ++ // Paper start - Patrol settings ++ // Random player selection moved up for per player spawning and configuration ++ int j = world.players().size(); ++ if (j < 1) { + return 0; ++ } ++ ++ ServerPlayer entityhuman = world.players().get(random.nextInt(j)); ++ if (entityhuman.isSpectator()) { ++ return 0; ++ } ++ ++ int patrolSpawnDelay; ++ if (world.paperConfig.patrolPerPlayerDelay) { ++ --entityhuman.patrolSpawnDelay; ++ patrolSpawnDelay = entityhuman.patrolSpawnDelay; + } else { +- this.nextTick += 12000 + random.nextInt(1200); +- long i = world.getDayTime() / 24000L; ++ this.nextTick--; ++ patrolSpawnDelay = this.nextTick; ++ } ++ ++ if (patrolSpawnDelay > 0) { ++ return 0; ++ } else { ++ long days; ++ if (world.paperConfig.patrolPerPlayerStart) { ++ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_TIME)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang ++ } else { ++ days = world.getDayTime() / 24000L; ++ } ++ if (world.paperConfig.patrolPerPlayerDelay) { ++ entityhuman.patrolSpawnDelay += world.paperConfig.patrolDelay + random.nextInt(1200); ++ } else { ++ this.nextTick += world.paperConfig.patrolDelay + random.nextInt(1200); ++ } + +- if (i >= 5L && world.isDay()) { +- if (random.nextInt(5) != 0) { ++ if (days >= world.paperConfig.patrolStartDay && world.isDay()) { ++ if (random.nextDouble() >= world.paperConfig.patrolSpawnChance) { ++ // Paper end + return 0; + } else { +- int j = world.players().size(); + + if (j < 1) { + return 0; + } else { +- Player entityhuman = (Player) world.players().get(random.nextInt(j)); + + if (entityhuman.isSpectator()) { + return 0; diff --git a/patches/server/Player-Chunk-Load-Unload-Events.patch b/patches/server/Player-Chunk-Load-Unload-Events.patch new file mode 100644 index 0000000000..25e882d6e1 --- /dev/null +++ b/patches/server/Player-Chunk-Load-Unload-Events.patch @@ -0,0 +1,32 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public void trackChunk(ChunkPos chunkcoordintpair, Packet packet, Packet packet1) { + this.connection.send(packet1); + this.connection.send(packet); ++ // Paper start ++ if(io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkcoordintpair.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + public void untrackChunk(ChunkPos chunkPos) { + if (this.isAlive()) { + this.connection.send(new ClientboundForgetLevelChunkPacket(chunkPos.x, chunkPos.z)); ++ // Paper start ++ if(io.papermc.paper.event.packet.PlayerChunkUnloadEvent.getHandlerList().getRegisteredListeners().length > 0){ ++ new io.papermc.paper.event.packet.PlayerChunkUnloadEvent(this.getBukkitEntity().getWorld().getChunkAt(chunkPos.longKey), this.getBukkitEntity()).callEvent(); ++ } ++ // Paper end + } + + } diff --git a/Spigot-Server-Patches/Player-Tab-List-and-Title-APIs.patch b/patches/server/Player-Tab-List-and-Title-APIs.patch similarity index 56% rename from Spigot-Server-Patches/Player-Tab-List-and-Title-APIs.patch rename to patches/server/Player-Tab-List-and-Title-APIs.patch index 57580bbcbd..09eab38195 100644 --- a/Spigot-Server-Patches/Player-Tab-List-and-Title-APIs.patch +++ b/patches/server/Player-Tab-List-and-Title-APIs.patch @@ -4,65 +4,64 @@ 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 +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.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) { +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -0,0 +0,0 @@ public class FriendlyByteBuf extends ByteBuf { + public FriendlyByteBuf 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) { ++ public FriendlyByteBuf 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 + public FriendlyByteBuf writeComponent(Component text) { +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetSubtitleTextPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetSubtitleTextPacket.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 { + private final Component text; + public net.kyori.adventure.text.Component adventure$text; // Paper ++ public net.md_5.bungee.api.chat.BaseComponent[] components; // Paper -+ @Nullable public static IChatBaseComponent jsonToComponent(String json) { return a(json);} // Paper - OBFHELPER - @Nullable - public static IChatMutableComponent a(String s) { - return (IChatMutableComponent) ChatDeserializer.a(IChatBaseComponent.ChatSerializer.a, s, IChatMutableComponent.class, false); -diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutTitle.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutTitle.java + public ClientboundSetSubtitleTextPacket(Component subtitle) { + this.text = subtitle; +@@ -0,0 +0,0 @@ public class ClientboundSetSubtitleTextPacket implements Packet { - } +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitleTextPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitleTextPacket.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet; + public class ClientboundSetTitleTextPacket implements Packet { + private final Component text; + public net.kyori.adventure.text.Component adventure$text; // Paper ++ public net.md_5.bungee.api.chat.BaseComponent[] components; // Paper - } -+ // Paper start -+ public net.md_5.bungee.api.chat.BaseComponent[] components; -+ -+ public PacketPlayOutTitle(EnumTitleAction action, net.md_5.bungee.api.chat.BaseComponent[] components, int fadeIn, int stay, int fadeOut) { -+ this.a = action; -+ this.components = components; -+ this.c = fadeIn; -+ this.d = stay; -+ this.e = fadeOut; -+ } -+ // Paper end - - @Override - public void b(PacketDataSerializer packetdataserializer) throws IOException { -@@ -0,0 +0,0 @@ public class PacketPlayOutTitle implements Packet { - // Paper start - if (this.adventure$text != null) { - packetdataserializer.writeComponent(this.adventure$text); -+ } else if (this.components != null) { -+ packetdataserializer.writeComponent(this.components); - } else - // Paper end - packetdataserializer.a(this.b); + public ClientboundSetTitleTextPacket(Component title) { + this.text = title; +@@ -0,0 +0,0 @@ public class ClientboundSetTitleTextPacket implements Packet +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/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java ++++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java +@@ -0,0 +0,0 @@ public final class EntitySelector { + }; + + private EntitySelector() {} ++ // Paper start ++ public static final Predicate affectsSpawning = (entity) -> { ++ return !entity.isSpectator() && entity.isAlive() && (entity instanceof net.minecraft.server.level.ServerPlayer) && ((net.minecraft.server.level.ServerPlayer) entity).affectsSpawning; ++ }; ++ // Paper end + + public static Predicate withinDistance(double x, double y, double z, double max) { + double d4 = max * max; +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity { + if (this.level.getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) { + this.discard(); + } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { +- Player entityhuman = this.level.getNearestPlayer(this, -1.0D); ++ Player entityhuman = this.level.findNearbyPlayer(this, -1.0D, EntitySelector.affectsSpawning); // Paper + + if (entityhuman != null) { + double d0 = entityhuman.distanceToSqr((Entity) this); // CraftBukkit - decompile error +diff --git a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Silverfish.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Silverfish.java +@@ -0,0 +0,0 @@ public class Silverfish extends Monster { + if (checkAnyLightMonsterSpawnRules(type, world, spawnReason, pos, random)) { + Player entityhuman = world.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.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/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + private final ItemCooldowns cooldowns; + @Nullable + public FishingHook fishing; ++ // Paper start ++ public boolean affectsSpawning = true; ++ // Paper end + + // CraftBukkit start + public boolean fauxSleeping; +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + } + + private boolean isNearPlayer(Level world, BlockPos pos) { +- return world.hasNearbyAlivePlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); ++ return world.isAffectsSpawningPlayerNearby((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, (double) this.requiredPlayerRange); // Paper + } + + public void clientTick(Level world, BlockPos pos) { +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -0,0 +0,0 @@ public interface EntityGetter { + } + } + +- @Nullable +- default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { ++ default Player findNearbyPlayer(Entity entity, double d0, @Nullable Predicate predicate) { return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), d0, predicate); } // Paper ++ @Nullable default Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { // Paper + double d = -1.0D; + Player player = null; + +@@ -0,0 +0,0 @@ public interface EntityGetter { + return this.getNearestPlayer(x, y, z, maxDistance, predicate); + } + ++ // Paper end ++ default boolean isAffectsSpawningPlayerNearby(double d0, double d1, double d2, double d3) { ++ java.util.Iterator iterator = this.players().iterator(); ++ double d4; ++ do { ++ Player entityhuman; ++ do { ++ if (!iterator.hasNext()) { ++ return false; ++ } ++ ++ entityhuman = (Player) iterator.next(); ++ } while (!EntitySelector.affectsSpawning.test(entityhuman)); ++ ++ d4 = entityhuman.distanceToSqr(d0, d1, d2); ++ } while (d3 >= 0.0D && d4 >= d3 * d3); ++ ++ return true; ++ } ++ // Paper end ++ + default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { + for(Player player : this.players()) { + if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(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 getLocale() { + return this.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 (this.getHandle().connection == null) return; diff --git a/Spigot-Server-Patches/Player-elytra-boost-API.patch b/patches/server/Player-elytra-boost-API.patch similarity index 54% rename from Spigot-Server-Patches/Player-elytra-boost-API.patch rename to patches/server/Player-elytra-boost-API.patch index 5b5a7579a1..a7579ee013 100644 --- a/Spigot-Server-Patches/Player-elytra-boost-API.patch +++ b/patches/server/Player-elytra-boost-API.patch @@ -8,21 +8,6 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/ 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"); @@ -35,12 +20,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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) ++ net.minecraft.world.level.Level world = ((CraftWorld) getWorld()).getHandle(); ++ net.minecraft.world.entity.projectile.FireworkRocketEntity entity = new net.minecraft.world.entity.projectile.FireworkRocketEntity(world, item, getHandle()); ++ return world.addFreshEntity(entity) + ? (org.bukkit.entity.Firework) entity.getBukkitEntity() + : null; + } // Paper end - // Spigot start + @Override diff --git a/patches/server/Player.setPlayerProfile-API.patch b/patches/server/Player.setPlayerProfile-API.patch new file mode 100644 index 0000000000..1e431d6fcf --- /dev/null +++ b/patches/server/Player.setPlayerProfile-API.patch @@ -0,0 +1,133 @@ +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/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + final org.bukkit.craftbukkit.CraftServer server = ServerLoginPacketListenerImpl.this.server.server; + + // Paper start +- PlayerProfile profile = Bukkit.createProfile(uniqueId, playerName); ++ PlayerProfile profile = CraftPlayerProfile.asBukkitMirror(ServerLoginPacketListenerImpl.this.gameProfile); + AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(playerName, address, uniqueId, profile); + server.getPluginManager().callEvent(asyncEvent); + profile = asyncEvent.getPlayerProfile(); +- profile.complete(); +- gameProfile = CraftPlayerProfile.asAuthlibCopy(profile); ++ profile.complete(true); ++ ServerLoginPacketListenerImpl.this.gameProfile = CraftPlayerProfile.asAuthlib(profile); + playerName = gameProfile.getName(); + uniqueId = gameProfile.getId(); + // Paper end +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + protected int enchantmentSeed; + protected final float defaultFlySpeed = 0.02F; + private int lastLevelUpTime; +- private final GameProfile gameProfile; ++ public GameProfile gameProfile; // Paper - private->public + private boolean reducedDebugInfo; + private ItemStack lastItemInMainHand; + private final ItemCooldowns cooldowns; +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.enchantment.EnchantmentHelper; + import net.minecraft.world.item.enchantment.Enchantments; + import net.minecraft.world.level.GameType; + import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.biome.BiomeManager; + import net.minecraft.world.level.block.entity.SignBlockEntity; + import net.minecraft.world.level.saveddata.maps.MapDecoration; + import net.minecraft.world.level.saveddata.maps.MapItemSavedData; +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.hiddenPlayers.put(player.getUniqueId(), hidingPlugins); + + // Remove this player from the hidden player's EntityTrackerEntry +- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper start + ServerPlayer other = ((CraftPlayer) player).getHandle(); ++ unregisterPlayer(other); ++ } ++ private void unregisterPlayer(ServerPlayer other) { ++ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper end + ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); + if (entry != null) { + entry.removePlayer(this.getHandle()); +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + } + this.hiddenPlayers.remove(player.getUniqueId()); + +- ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper start + ServerPlayer other = ((CraftPlayer) player).getHandle(); ++ registerPlayer(other); ++ } ++ private void registerPlayer(ServerPlayer other) { ++ ChunkMap tracker = ((ServerLevel) entity.level).getChunkSource().chunkMap; ++ // Paper end + + this.getHandle().connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, other)); + +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + entry.updatePlayer(this.getHandle()); + } + } ++ // Paper start ++ private void reregisterPlayer(ServerPlayer player) { ++ if (!hiddenPlayers.containsKey(player.getUUID())) { ++ unregisterPlayer(player); ++ registerPlayer(player); ++ } ++ } ++ public void setPlayerProfile(com.destroystokyo.paper.profile.PlayerProfile profile) { ++ ServerPlayer self = getHandle(); ++ self.gameProfile = com.destroystokyo.paper.profile.CraftPlayerProfile.asAuthlibCopy(profile); ++ if (!self.sentListPacket) { ++ return; ++ } ++ List players = server.getServer().getPlayerList().players; ++ for (ServerPlayer 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() { ++ ServerPlayer handle = getHandle(); ++ ++ Location loc = getLocation(); ++ ++ ServerGamePacketListenerImpl connection = handle.connection; ++ reregisterPlayer(handle); ++ ++ //Respawn the player then update their position and selected slot ++ ServerLevel worldserver = handle.getLevel(); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundRespawnPacket(worldserver.dimensionType(), worldserver.dimension(), BiomeManager.obfuscateSeed(worldserver.getSeed()), handle.gameMode.getGameModeForPlayer(), handle.gameMode.getPreviousGameModeForPlayer(), worldserver.isDebug(), worldserver.isFlat(), true)); ++ handle.onUpdateAbilities(); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch(), java.util.Collections.emptySet(), 0, false)); ++ net.minecraft.server.MinecraftServer.getServer().getPlayerList().sendAllPlayerInfo(handle); ++ ++ if (this.isOp()) { ++ this.setOp(false); ++ this.setOp(true); ++ } ++ } ++ // Paper end + + public void removeDisconnectingPlayer(Player player) { + this.hiddenPlayers.remove(player.getUniqueId()); diff --git a/Spigot-Server-Patches/PlayerAdvancementCriterionGrantEvent.patch b/patches/server/PlayerAdvancementCriterionGrantEvent.patch similarity index 50% rename from Spigot-Server-Patches/PlayerAdvancementCriterionGrantEvent.patch rename to patches/server/PlayerAdvancementCriterionGrantEvent.patch index 42595d86d6..d9eebfe3e0 100644 --- a/Spigot-Server-Patches/PlayerAdvancementCriterionGrantEvent.patch +++ b/patches/server/PlayerAdvancementCriterionGrantEvent.patch @@ -4,20 +4,20 @@ 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 +diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.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 { +--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java ++++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java +@@ -0,0 +0,0 @@ public class PlayerAdvancements { boolean flag1 = advancementprogress.isDone(); - if (advancementprogress.a(s)) { + if (advancementprogress.grantProgress(criterionName)) { + // Paper start -+ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, s).callEvent()) { -+ advancementprogress.b(s); ++ if (!new com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent(this.player.getBukkitEntity(), advancement.bukkit, criterionName).callEvent()) { ++ advancementprogress.revokeProgress(criterionName); + return false; + } + // Paper end - this.d(advancement); - this.j.add(advancement); + this.unregisterListeners(advancement); + this.progressChanged.add(advancement); flag = true; diff --git a/Spigot-Server-Patches/PlayerAttemptPickupItemEvent.patch b/patches/server/PlayerAttemptPickupItemEvent.patch similarity index 61% rename from Spigot-Server-Patches/PlayerAttemptPickupItemEvent.patch rename to patches/server/PlayerAttemptPickupItemEvent.patch index 0ca1f099ec..9b98d18bf5 100644 --- a/Spigot-Server-Patches/PlayerAttemptPickupItemEvent.patch +++ b/patches/server/PlayerAttemptPickupItemEvent.patch @@ -4,31 +4,31 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.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; +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ import net.minecraft.stats.Stats; 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 { + public class ItemEntity extends Entity { -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { +@@ -0,0 +0,0 @@ public class ItemEntity 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); ++ PlayerAttemptPickupItemEvent attemptEvent = new PlayerAttemptPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); ++ this.level.getCraftServer().getPluginManager().callEvent(attemptEvent); + + flyAtPlayer = attemptEvent.getFlyAtPlayer(); + if (attemptEvent.isCancelled()) { + if (flyAtPlayer) { -+ entityhuman.receive(this, i); ++ player.take(this, i); + } + + return; diff --git a/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch b/patches/server/PlayerDeathEvent-getItemsToKeep.patch similarity index 69% rename from Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch rename to patches/server/PlayerDeathEvent-getItemsToKeep.patch index bd0e0794fc..a302625e5d 100644 --- a/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch +++ b/patches/server/PlayerDeathEvent-getItemsToKeep.patch @@ -7,11 +7,11 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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 { +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { }); } @@ -31,8 +31,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + 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); ++ if (EnchantmentHelper.hasVanishingCurse(item) || itemsToKeep.isEmpty() || item.isEmpty()) { ++ inv.set(i, ItemStack.EMPTY); + continue; + } + @@ -49,26 +49,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + if (!keep) { -+ inv.set(i, ItemStack.NULL_ITEM); ++ inv.set(i, ItemStack.EMPTY); + } + } + } + // 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(); + public void die(DamageSource source) { + boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { // 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(); + this.getInventory().clearContent(); + // Paper start - replace logic -+ for (NonNullList inv : this.inventory.getComponents()) { ++ for (NonNullList inv : this.getInventory().compartments) { + processKeep(event, inv); + } + processKeep(event, null); + // Paper end } - this.setSpectatorTarget(this); // Remove spectated target + this.setCamera(this); // Remove spectated target diff --git a/Spigot-Server-Patches/PlayerDeathEvent-shouldDropExperience.patch b/patches/server/PlayerDeathEvent-shouldDropExperience.patch similarity index 62% rename from Spigot-Server-Patches/PlayerDeathEvent-shouldDropExperience.patch rename to patches/server/PlayerDeathEvent-shouldDropExperience.patch index 1b7c30e2a7..5295b9a174 100644 --- a/Spigot-Server-Patches/PlayerDeathEvent-shouldDropExperience.patch +++ b/patches/server/PlayerDeathEvent-shouldDropExperience.patch @@ -4,16 +4,16 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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(); +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.tellNeutralMobsThatIDied(); } // 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 + this.getInventory().clearContent(); diff --git a/patches/server/PlayerElytraBoostEvent.patch b/patches/server/PlayerElytraBoostEvent.patch new file mode 100644 index 0000000000..5df337620d --- /dev/null +++ b/patches/server/PlayerElytraBoostEvent.patch @@ -0,0 +1,33 @@ +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/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -0,0 +0,0 @@ public class FireworkRocketItem extends Item { + if (!world.isClientSide) { + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(world, itemStack, user); + fireworkRocketEntity.spawningEntity = user.getUUID(); // Paper +- world.addFreshEntity(fireworkRocketEntity); +- if (!user.getAbilities().instabuild) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) fireworkRocketEntity.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(fireworkRocketEntity)) { ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { + itemStack.shrink(1); ++ } else ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ // Paper end + } + +- user.awardStat(Stats.ITEM_USED.get(this)); ++ // user.awardStat(Stats.ITEM_USED.get(this)); // Paper - move up + } + + return InteractionResultHolder.sidedSuccess(user.getItemInHand(hand), world.isClientSide()); diff --git a/patches/server/PlayerLaunchProjectileEvent.patch b/patches/server/PlayerLaunchProjectileEvent.patch new file mode 100644 index 0000000000..79bdf3f2f2 --- /dev/null +++ b/patches/server/PlayerLaunchProjectileEvent.patch @@ -0,0 +1,276 @@ +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/item/EggItem.java b/src/main/java/net/minecraft/world/item/EggItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/EggItem.java ++++ b/src/main/java/net/minecraft/world/item/EggItem.java +@@ -0,0 +0,0 @@ public class EggItem extends Item { + + entityegg.setItem(itemstack); + entityegg.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); +- // CraftBukkit start +- if (!world.addFreshEntity(entityegg)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityegg.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityegg)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), net.minecraft.sounds.SoundEvents.EGG_THROW, net.minecraft.sounds.SoundSource.PLAYERS, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } + return InteractionResultHolder.fail(itemstack); + } +- // CraftBukkit end ++ // Paper end + } + // world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above + ++ /* // Paper start - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + if (!user.getAbilities().instabuild) { + itemstack.shrink(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/EnderpearlItem.java b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/EnderpearlItem.java ++++ b/src/main/java/net/minecraft/world/item/EnderpearlItem.java +@@ -0,0 +0,0 @@ public class EnderpearlItem extends Item { + + entityenderpearl.setItem(itemstack); + entityenderpearl.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); +- if (!world.addFreshEntity(entityenderpearl)) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entityenderpearl.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entityenderpearl)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ user.getCooldowns().addCooldown(this, 20); ++ } else { ++ // Paper end + if (user instanceof net.minecraft.server.level.ServerPlayer) { + ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } +@@ -0,0 +0,0 @@ public class EnderpearlItem extends Item { + } + } + ++ /* // Paper start - moved up + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); + user.getCooldowns().addCooldown(this, 20); + // CraftBukkit end +@@ -0,0 +0,0 @@ public class EnderpearlItem extends Item { + if (!user.getAbilities().instabuild) { + itemstack.shrink(1); + } ++ */ // Paper end - moved up + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java ++++ b/src/main/java/net/minecraft/world/item/ExperienceBottleItem.java +@@ -0,0 +0,0 @@ public class ExperienceBottleItem extends Item { + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { + ItemStack itemStack = user.getItemInHand(hand); +- world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); ++ // world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // Paper - moved down + if (!world.isClientSide) { + ThrownExperienceBottle thrownExperienceBottle = new ThrownExperienceBottle(world, user); + thrownExperienceBottle.setItem(itemStack); + thrownExperienceBottle.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.7F, 1.0F); +- world.addFreshEntity(thrownExperienceBottle); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownExperienceBottle.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(thrownExperienceBottle)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemStack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EXPERIENCE_BOTTLE_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (net.minecraft.world.entity.Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemStack); ++ } ++ // Paper end + } + ++ /* // Paper start - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + if (!user.getAbilities().instabuild) { + itemStack.shrink(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/FireworkRocketItem.java ++++ b/src/main/java/net/minecraft/world/item/FireworkRocketItem.java +@@ -0,0 +0,0 @@ import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.stats.Stats; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.InteractionResultHolder; +@@ -0,0 +0,0 @@ public class FireworkRocketItem extends Item { + Direction direction = context.getClickedFace(); + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity(level, context.getPlayer(), vec3.x + (double)direction.getStepX() * 0.15D, vec3.y + (double)direction.getStepY() * 0.15D, vec3.z + (double)direction.getStepZ() * 0.15D, itemStack); + fireworkRocketEntity.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID(); // Paper +- level.addFreshEntity(fireworkRocketEntity); +- itemStack.shrink(1); ++ // Paper start - PlayerLaunchProjectileEvent ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) fireworkRocketEntity.getBukkitEntity()); ++ if (!event.callEvent() || !level.addFreshEntity(fireworkRocketEntity)) return InteractionResult.PASS; ++ if (event.shouldConsume() && !context.getPlayer().getAbilities().instabuild) itemStack.shrink(1); ++ else if (context.getPlayer() instanceof ServerPlayer) ((ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory(); ++ // Paper end + } + + return InteractionResult.sidedSuccess(level.isClientSide); +diff --git a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/LingeringPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/LingeringPotionItem.java +@@ -0,0 +0,0 @@ public class LingeringPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != net.minecraft.world.InteractionResult.FAIL) { + world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.LINGERING_POTION_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/SnowballItem.java b/src/main/java/net/minecraft/world/item/SnowballItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/SnowballItem.java ++++ b/src/main/java/net/minecraft/world/item/SnowballItem.java +@@ -0,0 +0,0 @@ public class SnowballItem extends Item { + + entitysnowball.setItem(itemstack); + entitysnowball.shootFromRotation(user, user.getXRot(), user.getYRot(), 0.0F, 1.5F, 1.0F); +- if (world.addFreshEntity(entitysnowball)) { +- if (!user.getAbilities().instabuild) { ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(entitysnowball)) { ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ // Paper end + itemstack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper + } + + world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); +- } else if (user instanceof net.minecraft.server.level.ServerPlayer) { +- ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } else { // Paper ++ if (user instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); // Paper ++ return InteractionResultHolder.fail(itemstack); // Paper + } + } + // CraftBukkit end + ++ /* // Paper tart - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + // CraftBukkit start - moved up + /* +@@ -0,0 +0,0 @@ public class SnowballItem extends Item { + itemstack.subtract(1); + } + */ ++ // Paper end + + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } +diff --git a/src/main/java/net/minecraft/world/item/SplashPotionItem.java b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/SplashPotionItem.java ++++ b/src/main/java/net/minecraft/world/item/SplashPotionItem.java +@@ -0,0 +0,0 @@ public class SplashPotionItem extends ThrowablePotionItem { + + @Override + public InteractionResultHolder use(Level world, Player user, InteractionHand hand) { ++ // Paper start ++ InteractionResultHolder wrapper = super.use(world, user, hand); ++ if (wrapper.getResult() != net.minecraft.world.InteractionResult.FAIL) { + world.playSound((Player)null, user.getX(), user.getY(), user.getZ(), SoundEvents.SPLASH_POTION_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); +- return super.use(world, user, hand); ++ } ++ return wrapper; ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java ++++ b/src/main/java/net/minecraft/world/item/ThrowablePotionItem.java +@@ -0,0 +0,0 @@ public class ThrowablePotionItem extends PotionItem { + ThrownPotion thrownPotion = new ThrownPotion(world, user); + thrownPotion.setItem(itemStack); + thrownPotion.shootFromRotation(user, user.getXRot(), user.getYRot(), -20.0F, 0.5F, 1.0F); +- world.addFreshEntity(thrownPotion); ++ // Paper start ++ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownPotion.getBukkitEntity()); ++ if (event.callEvent() && world.addFreshEntity(thrownPotion)) { ++ if (event.shouldConsume() && !user.getAbilities().instabuild) { ++ itemStack.shrink(1); ++ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ ++ user.awardStat(Stats.ITEM_USED.get(this)); ++ } else { ++ if (user instanceof net.minecraft.server.level.ServerPlayer) { ++ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); ++ } ++ return InteractionResultHolder.fail(itemStack); ++ } ++ // Paper end + } + ++ /* // Paper start - moved up + user.awardStat(Stats.ITEM_USED.get(this)); + if (!user.getAbilities().instabuild) { + itemStack.shrink(1); + } ++ */ // Paper end + + return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide()); + } diff --git a/Spigot-Server-Patches/PlayerNaturallySpawnCreaturesEvent.patch b/patches/server/PlayerNaturallySpawnCreaturesEvent.patch similarity index 53% rename from Spigot-Server-Patches/PlayerNaturallySpawnCreaturesEvent.patch rename to patches/server/PlayerNaturallySpawnCreaturesEvent.patch index ce5144dabf..f6ae8ee3de 100644 --- a/Spigot-Server-Patches/PlayerNaturallySpawnCreaturesEvent.patch +++ b/patches/server/PlayerNaturallySpawnCreaturesEvent.patch @@ -8,62 +8,22 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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; +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.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(); + long i = chunkcoordintpair.toLong(); - return !this.chunkDistanceManager.d(i) ? true : this.playerMap.a(i).noneMatch((entityplayer) -> { -- return !entityplayer.isSpectator() && a(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot -+ // Paper start - + return !this.distanceManager.hasPlayersNearby(i) ? true : this.playerMap.getPlayers(i).noneMatch((entityplayer) -> { ++ // Paper start - add PlayerNaturallySpawnCreaturesEvent + com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event; + double blockRange = 16384.0D; + if (reducedRange) { @@ -71,9 +31,46 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + return !entityplayer.isSpectator() && ChunkMap.euclideanDistanceSquared(chunkcoordintpair, (Entity) entityplayer) < blockRange; // Spigot }); } +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ //Paper start - call player naturally spawn event ++ int chunkRange = level.spigotConfig.mobSpawnRange; ++ chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; ++ chunkRange = Math.min(chunkRange, 8); ++ for (ServerPlayer entityPlayer : this.level.players()) { ++ entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); ++ entityPlayer.playerNaturallySpawnedEvent.callEvent(); ++ }; ++ // Paper end + this.level.timings.chunkTicks.startTiming(); // Paper + this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.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 ServerPlayer extends Player { + 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/patches/server/PlayerPickupExperienceEvent.patch b/patches/server/PlayerPickupExperienceEvent.patch new file mode 100644 index 0000000000..68ac81ba3d --- /dev/null +++ b/patches/server/PlayerPickupExperienceEvent.patch @@ -0,0 +1,20 @@ +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/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity { + @Override + public void playerTouch(Player player) { + if (!this.level.isClientSide) { +- if (player.takeXpDelay == 0) { ++ if (player.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper + player.takeXpDelay = 2; + player.take(this, 1); + int i = this.repairPlayerItems(player, this.value); diff --git a/Spigot-Server-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/server/PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 55% rename from Spigot-Server-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch rename to patches/server/PlayerPickupItemEvent-setFlyAtPlayer.patch index 9a7db230fd..1d0d50f679 100644 --- a/Spigot-Server-Patches/PlayerPickupItemEvent-setFlyAtPlayer.patch +++ b/patches/server/PlayerPickupItemEvent-setFlyAtPlayer.patch @@ -4,43 +4,43 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { // CraftBukkit start - fire PlayerPickupItemEvent - int canHold = entityhuman.inventory.canHold(itemstack); + int canHold = player.getInventory().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); +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { + PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); + playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); + this.level.getCraftServer().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); ++ player.take(this, i); + } + // Paper End return; } -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { +@@ -0,0 +0,0 @@ public class ItemEntity extends Entity { // CraftBukkit end - if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(entityhuman.getUniqueID())) && entityhuman.inventory.pickup(itemstack)) { -- entityhuman.receive(this, i); + if (this.pickupDelay == 0 && (this.owner == null || this.owner.equals(player.getUUID())) && player.getInventory().add(itemstack)) { +- player.take(this, i); + // Paper Start + if (flyAtPlayer) { -+ entityhuman.receive(this, i); ++ player.take(this, i); + } + // Paper End if (itemstack.isEmpty()) { - this.die(); + this.discard(); itemstack.setCount(i); diff --git a/Spigot-Server-Patches/PlayerReadyArrowEvent.patch b/patches/server/PlayerReadyArrowEvent.patch similarity index 56% rename from Spigot-Server-Patches/PlayerReadyArrowEvent.patch rename to patches/server/PlayerReadyArrowEvent.patch index bf25e73e68..38acbec8e0 100644 --- a/Spigot-Server-Patches/PlayerReadyArrowEvent.patch +++ b/patches/server/PlayerReadyArrowEvent.patch @@ -6,19 +6,19 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.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); +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); } + // Paper start + protected boolean tryReadyArrow(ItemStack bow, ItemStack itemstack) { -+ return !(this instanceof EntityPlayer) || ++ return !(this instanceof ServerPlayer) || + new com.destroystokyo.paper.event.player.PlayerReadyArrowEvent( -+ ((EntityPlayer) this).getBukkitEntity(), ++ ((ServerPlayer) this).getBukkitEntity(), + org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(bow), + org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack) + ).callEvent(); @@ -26,14 +26,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + @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) { + public ItemStack getProjectile(ItemStack stack) { + if (!(stack.getItem() instanceof ProjectileWeaponItem)) { +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + for (int i = 0; i < this.inventory.getContainerSize(); ++i) { ItemStack itemstack2 = this.inventory.getItem(i); - if (predicate.test(itemstack2)) { -+ if (predicate.test(itemstack2) && tryReadyArrow(itemstack, itemstack2)) { // Paper ++ if (predicate.test(itemstack2) && tryReadyArrow(stack, itemstack2)) { // Paper return itemstack2; } } diff --git a/Spigot-Server-Patches/PlayerTeleportEndGatewayEvent.patch b/patches/server/PlayerTeleportEndGatewayEvent.patch similarity index 56% rename from Spigot-Server-Patches/PlayerTeleportEndGatewayEvent.patch rename to patches/server/PlayerTeleportEndGatewayEvent.patch index e7ac1cca42..5d924f0568 100644 --- a/Spigot-Server-Patches/PlayerTeleportEndGatewayEvent.patch +++ b/patches/server/PlayerTeleportEndGatewayEvent.patch @@ -5,24 +5,24 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.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; +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -0,0 +0,0 @@ import net.minecraft.data.worldgen.Features; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtUtils; + import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +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 + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; +@@ -0,0 +0,0 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { 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 ++ PlayerTeleportEvent teleEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(player, player.getLocation(), location, new org.bukkit.craftbukkit.block.CraftEndGateway(net.minecraft.server.MCUtil.toLocation(worldserver, blockEntity.getBlockPos()).getBlock())); // Paper Bukkit.getPluginManager().callEvent(teleEvent); if (teleEvent.isCancelled()) { return; diff --git a/patches/server/PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/PortalCreateEvent-needs-to-know-its-entity.patch new file mode 100644 index 0000000000..e6e1f4ac81 --- /dev/null +++ b/patches/server/PortalCreateEvent-needs-to-know-its-entity.patch @@ -0,0 +1,146 @@ +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 { + net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition); + + if (!(block.getBlock() instanceof BaseEntityBlock)) { // 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.getBlockState(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/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java +@@ -0,0 +0,0 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; +@@ -0,0 +0,0 @@ public abstract class BaseFireBlock extends Block { + super.entityInside(state, world, pos, entity); + } + ++ // Paper start - ItemActionContext param ++ @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { this.onPlace(state, world, pos, oldState, notify, null); } + @Override +- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { +- if (!oldState.is(state.getBlock())) { ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ // Paper end ++ if (!iblockdata1.is(iblockdata.getBlock())) { + if (BaseFireBlock.inPortalDimension(world)) { +- Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, pos, Direction.Axis.X); ++ Optional optional = PortalShape.findEmptyPortalShape((LevelAccessor) world, blockposition, Direction.Axis.X); + + if (optional.isPresent()) { +- ((PortalShape) optional.get()).createPortal(); ++ ((PortalShape) optional.get()).createPortal(itemActionContext); // Paper - pass ItemActionContext param + return; + } + } + +- if (!state.canSurvive(world, pos)) { +- this.fireExtinguished(world, pos); // CraftBukkit - fuel block broke ++ if (!iblockdata.canSurvive(world, blockposition)) { ++ fireExtinguished(world, blockposition); // CraftBukkit - fuel block broke + } + + } +diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java +@@ -0,0 +0,0 @@ import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +@@ -0,0 +0,0 @@ public class FireBlock extends BaseFireBlock { + } + + @Override +- public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { +- super.onPlace(state, world, pos, oldState, notify); +- world.getBlockTicks().scheduleTick(pos, this, FireBlock.getFireTickDelay(world.random)); ++ // Paper start - ItemActionContext param ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); ++ // Paper end ++ world.getBlockTicks().scheduleTick(blockposition, this, getFireTickDelay(world.random)); + } + + private static int getFireTickDelay(Random random) { +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -0,0 +0,0 @@ import net.minecraft.world.item.DyeColor; + import net.minecraft.world.item.Item; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.context.BlockPlaceContext; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.BlockGetter; + import net.minecraft.world.level.EmptyBlockGetter; + import net.minecraft.world.level.Level; +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { + DebugPackets.sendNeighborsUpdatePacket(world, pos); + } + ++ // Paper start - add ItemActionContext param ++ @Deprecated ++ public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) { ++ this.onPlace(iblockdata, world, blockposition, iblockdata1, flag); ++ } ++ // Paper end + @Deprecated + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot +diff --git a/src/main/java/net/minecraft/world/level/portal/PortalShape.java b/src/main/java/net/minecraft/world/level/portal/PortalShape.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/portal/PortalShape.java ++++ b/src/main/java/net/minecraft/world/level/portal/PortalShape.java +@@ -0,0 +0,0 @@ import net.minecraft.tags.BlockTags; + import net.minecraft.tags.Tag; + import net.minecraft.util.Mth; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.item.context.UseOnContext; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.NetherPortalBlock; +@@ -0,0 +0,0 @@ public class PortalShape { + } + + // CraftBukkit start - return boolean +- public boolean createPortal() { ++ // Paper start - ItemActionContext param ++ @Deprecated public boolean createPortal() { return this.createPortal(null); } ++ public boolean createPortal(UseOnContext itemActionContext) { ++ // Paper end + org.bukkit.World bworld = this.level.getMinecraftWorld().getWorld(); + + // Copy below for loop +@@ -0,0 +0,0 @@ public class PortalShape { + this.blocks.setBlock(blockposition, iblockdata, 18); + }); + +- PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) this.blocks.getList(), bworld, null, PortalCreateEvent.CreateReason.FIRE); ++ PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) blocks.getList(), bworld, itemActionContext == null || itemActionContext.getPlayer() == null ? null : itemActionContext.getPlayer().getBukkitEntity(), PortalCreateEvent.CreateReason.FIRE); // Paper - pass entity param + this.level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { diff --git a/Spigot-Server-Patches/Potential-bed-API.patch b/patches/server/Potential-bed-API.patch similarity index 70% rename from Spigot-Server-Patches/Potential-bed-API.patch rename to patches/server/Potential-bed-API.patch index efbe6e2113..de10d553a1 100644 --- a/Spigot-Server-Patches/Potential-bed-API.patch +++ b/patches/server/Potential-bed-API.patch @@ -11,28 +11,28 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b 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; +@@ -0,0 +0,0 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; + import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.world.MenuProvider; 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; + return this.getHandle().sleepCounter; } + // Paper start - Potential bed api + @Override + public Location getPotentialBedLocation() { -+ EntityPlayer handle = (EntityPlayer) getHandle(); -+ BlockPosition bed = handle.getSpawn(); ++ ServerPlayer handle = (ServerPlayer) getHandle(); ++ BlockPos bed = handle.getRespawnPosition(); + if (bed == null) { + return null; + } + -+ WorldServer worldServer = handle.server.getWorldServer(handle.getSpawnDimension()); ++ ServerLevel worldServer = handle.server.getLevel(handle.getRespawnDimension()); + if (worldServer == null) { + return null; + } diff --git a/patches/server/PreCreatureSpawnEvent.patch b/patches/server/PreCreatureSpawnEvent.patch new file mode 100644 index 0000000000..bd46f397df --- /dev/null +++ b/patches/server/PreCreatureSpawnEvent.patch @@ -0,0 +1,150 @@ +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/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + + @Nullable + public T spawnCreature(ServerLevel worldserver, @Nullable CompoundTag nbttagcompound, @Nullable Component ichatbasecomponent, @Nullable Player entityhuman, BlockPos blockposition, MobSpawnType 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(EntityType.getKey(this).getPath()); ++ if (type != null) { ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(worldserver, blockposition), ++ type, ++ spawnReason ++ ); ++ if (!event.callEvent()) { ++ return null; ++ } ++ } ++ // Paper end + T t0 = this.create(worldserver, nbttagcompound, ichatbasecomponent, entityhuman, blockposition, enummobspawn, flag, flag1); + + if (t0 != null) { +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + BlockPos blockposition1 = this.findSpawnPositionForGolemInColumn(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( ++ net.minecraft.server.MCUtil.toLocation(level, blockposition1), ++ org.bukkit.entity.EntityType.IRON_GOLEM, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.VILLAGE_DEFENSE ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ GolemSensor.golemDetected(this); // Set Golem Last Seen to stop it from spawning another one ++ return null; ++ } ++ break; ++ } ++ // Paper end + IronGolem entityirongolem = (IronGolem) EntityType.IRON_GOLEM.create(world, (CompoundTag) null, (Component) null, (Player) null, blockposition1, MobSpawnType.MOB_SUMMONED, false, false); + + if (entityirongolem != null) { +diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + double d2 = j >= 3 ? nbttaglist.getDouble(2) : (double) pos.getZ() + (world.random.nextDouble() - world.random.nextDouble()) * (double) this.spawnRange + 0.5D; + + if (world.noCollision(((EntityType) optional.get()).getAABB(d0, d1, d2)) && SpawnPlacements.checkSpawnRules((EntityType) optional.get(), world, MobSpawnType.SPAWNER, new BlockPos(d0, d1, d2), world.getRandom())) { ++ // Paper start ++ EntityType entityType = optional.get(); ++ String key = EntityType.getKey(entityType).getPath(); ++ ++ 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( ++ net.minecraft.server.MCUtil.toLocation(world, d0, d1, d2), ++ type, ++ org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ ); ++ if (!event.callEvent()) { ++ flag = true; ++ if (event.shouldAbortSpawn()) { ++ break; ++ } ++ continue; ++ } ++ } ++ // Paper end + Entity entity = EntityType.loadEntityRecursive(nbttagcompound, world, (entity1) -> { + entity1.moveTo(d0, d1, d2, entity1.getYRot(), entity1.getXRot()); + return entity1; +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + return this.oSpin; + } + } ++ +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + j1 = biomesettingsmobs_c.minCount + world.random.nextInt(1 + biomesettingsmobs_c.maxCount - biomesettingsmobs_c.minCount); + } + +- if (NaturalSpawner.isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2) && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper start ++ Boolean doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); ++ if (doSpawning == null) { ++ return; ++ } ++ if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { ++ // Paper end + Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type); + + if (entityinsentient == null) { +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + return squaredDistance <= 576.0D ? false : (world.getSharedSpawnPos().closerThan((Position) (new Vec3((double) pos.getX() + 0.5D, (double) pos.getY(), (double) pos.getZ() + 0.5D)), 24.0D) ? false : Objects.equals(new ChunkPos(pos), chunk.getPos()) || world.isPositionEntityTicking((BlockPos) pos)); + } + +- private static boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { ++ private static Boolean isValidSpawnPostitionForType(ServerLevel world, MobCategory group, StructureFeatureManager structureAccessor, ChunkGenerator chunkGenerator, MobSpawnSettings.SpawnerData spawnEntry, BlockPos.MutableBlockPos pos, double squaredDistance) { // Paper + EntityType entitytypes = spawnEntry.type; + ++ // Paper start ++ com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent event; ++ org.bukkit.entity.EntityType type = org.bukkit.entity.EntityType.fromName(EntityType.getKey(entitytypes).getPath()); ++ if (type != null) { ++ event = new com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent( ++ net.minecraft.server.MCUtil.toLocation(world, pos), ++ type, SpawnReason.NATURAL ++ ); ++ if (!event.callEvent()) { ++ if (event.shouldAbortSpawn()) { ++ return null; ++ } ++ return false; ++ } ++ } ++ // Paper end + if (entitytypes.getCategory() == MobCategory.MISC) { + return false; + } else if (!entitytypes.canSpawnFarFromPlayer() && squaredDistance > (double) (entitytypes.getCategory().getDespawnDistance() * entitytypes.getCategory().getDespawnDistance())) { diff --git a/patches/server/PreSpawnerSpawnEvent.patch b/patches/server/PreSpawnerSpawnEvent.patch new file mode 100644 index 0000000000..a31a073edb --- /dev/null +++ b/patches/server/PreSpawnerSpawnEvent.patch @@ -0,0 +1,29 @@ +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/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + + 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( + net.minecraft.server.MCUtil.toLocation(world, d0, d1, d2), + type, +- org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER ++ net.minecraft.server.MCUtil.toLocation(world, pos) + ); + if (!event.callEvent()) { + flag = true; diff --git a/patches/server/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch new file mode 100644 index 0000000000..c18b7bf7d2 --- /dev/null +++ b/patches/server/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -0,0 +1,48 @@ +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/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + public 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.level != this.level || this.entityMap.containsKey(entity.getId())) { ++ new Throwable("[ERROR] Illegal PlayerChunkMap::addEntity for world " + this.level.getWorld().getName() ++ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : "")) ++ .printStackTrace(); ++ return; ++ } ++ // Paper end + if (!(entity instanceof EnderDragonPart)) { + EntityType entitytypes = entity.getType(); + int i = entitytypes.clientTrackingRange() * 16; +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + public void onTrackingStart(Entity entity) { + org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot +- ServerLevel.this.getChunkSource().addEntity(entity); ++ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - moved down below valid=true + if (entity instanceof ServerPlayer) { + ServerLevel.this.players.add((ServerPlayer) entity); + ServerLevel.this.updateSleepingPlayerList(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } + + entity.valid = true; // CraftBukkit ++ ServerLevel.this.getChunkSource().addEntity(entity); + // Paper start - Set origin location when the entity is being added to the world + if (entity.getOriginVector() == null) { + entity.setOrigin(entity.getBukkitEntity().getLocation()); diff --git a/patches/server/Prevent-Enderman-from-loading-chunks.patch b/patches/server/Prevent-Enderman-from-loading-chunks.patch new file mode 100644 index 0000000000..244c267f68 --- /dev/null +++ b/patches/server/Prevent-Enderman-from-loading-chunks.patch @@ -0,0 +1,30 @@ +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/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0D); + int k = Mth.floor(this.enderman.getZ() - 1.0D + random.nextDouble() * 2.0D); + BlockPos blockposition = new BlockPos(i, j, k); +- BlockState iblockdata = world.getBlockState(blockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + BlockPos blockposition1 = blockposition.below(); + BlockState iblockdata1 = world.getBlockState(blockposition1); + BlockState iblockdata2 = this.enderman.getCarriedBlock(); +@@ -0,0 +0,0 @@ public class EnderMan extends Monster implements NeutralMob { + int j = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0D); + int k = Mth.floor(this.enderman.getZ() - 2.0D + random.nextDouble() * 4.0D); + BlockPos blockposition = new BlockPos(i, j, k); +- BlockState iblockdata = world.getBlockState(blockposition); ++ BlockState iblockdata = world.getTypeIfLoaded(blockposition); // Paper ++ if (iblockdata == null) return; // Paper + Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D); + Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); + BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); diff --git a/patches/server/Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server/Prevent-Frosted-Ice-from-loading-holding-chunks.patch new file mode 100644 index 0000000000..96141e1259 --- /dev/null +++ b/patches/server/Prevent-Frosted-Ice-from-loading-holding-chunks.patch @@ -0,0 +1,33 @@ +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 + +1.17: Shouldn't be needed as blocks no longer tick without at least 1 radius chunk loaded. + +diff --git a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/FrostedIceBlock.java +@@ -0,0 +0,0 @@ public class FrostedIceBlock extends IceBlock { + + for(Direction direction : Direction.values()) { + mutableBlockPos.setWithOffset(pos, direction); +- BlockState blockState = world.getBlockState(mutableBlockPos); ++ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper ++ if (blockState == null) { continue; } // Paper + if (blockState.is(this) && !this.slightlyMelt(blockState, world, mutableBlockPos)) { + world.getBlockTicks().scheduleTick(mutableBlockPos, this, Mth.nextInt(random, world.paperConfig.frostedIceDelayMin, world.paperConfig.frostedIceDelayMax)); // Paper - use configurable min/max delay + } +@@ -0,0 +0,0 @@ public class FrostedIceBlock extends IceBlock { + + for(Direction direction : Direction.values()) { + mutableBlockPos.setWithOffset(pos, direction); +- if (world.getBlockState(mutableBlockPos).is(this)) { ++ // Paper start ++ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); ++ if (blockState != null && blockState.is(this)) { ++ // Paper end + ++i; + if (i >= maxNeighbors) { + return false; diff --git a/patches/server/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch b/patches/server/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch new file mode 100644 index 0000000000..ac69a2264c --- /dev/null +++ b/patches/server/Prevent-Mob-AI-Rules-from-Loading-Chunks.patch @@ -0,0 +1,40 @@ +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/RemoveBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java +@@ -0,0 +0,0 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Nullable + private BlockPos getPosWithBlock(BlockPos pos, BlockGetter world) { +- if (world.getBlockState(pos).is(this.blockToRemove)) { ++ net.minecraft.world.level.block.state.BlockState block = world.getTypeIfLoaded(pos); // Paper ++ if (block == null) return null; // Paper ++ if (block.is(this.blockToRemove)) { // Paper + return pos; + } else { + BlockPos[] ablockposition = new BlockPos[]{pos.below(), pos.west(), pos.east(), pos.north(), pos.south(), pos.below().below()}; +@@ -0,0 +0,0 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + for (int j = 0; j < i; ++j) { + BlockPos blockposition1 = ablockposition1[j]; + +- if (world.getBlockState(blockposition1).is(this.blockToRemove)) { ++ net.minecraft.world.level.block.state.BlockState block2 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (block2 != null && block2.is(this.blockToRemove)) { // Paper + return blockposition1; + } + } +@@ -0,0 +0,0 @@ public class RemoveBlockGoal extends MoveToBlockGoal { + + @Override + protected boolean isValidTarget(LevelReader world, BlockPos pos) { +- ChunkAccess ichunkaccess = world.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ()), ChunkStatus.FULL, false); ++ ChunkAccess ichunkaccess = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4); // Paper + + return ichunkaccess == null ? false : ichunkaccess.getBlockState(pos).is(this.blockToRemove) && ichunkaccess.getBlockState(pos.above()).isAir() && ichunkaccess.getBlockState(pos.above(2)).isAir(); + } diff --git a/patches/server/Prevent-Pathfinding-out-of-World-Border.patch b/patches/server/Prevent-Pathfinding-out-of-World-Border.patch new file mode 100644 index 0000000000..35d3dd2861 --- /dev/null +++ b/patches/server/Prevent-Pathfinding-out-of-World-Border.patch @@ -0,0 +1,27 @@ +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 + +TODO: This doesn't prevent the pathfinder from using blocks outside the world border as nodes. We can fix this +by adding code to all overrides in: + NodeEvaluator: + public abstract BlockPathTypes getBlockPathType(BlockGetter world, int x, int y, int z); + +to return BLOCKED if it is outside the world border. + +diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java ++++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +@@ -0,0 +0,0 @@ public abstract class PathNavigation { + // Paper start - Pathfind event + boolean copiedSet = false; + for (BlockPos possibleTarget : positions) { +- if (!new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(), ++ if (!this.mob.getCommandSenderWorld().getWorldBorder().isWithinBounds(possibleTarget) || !new com.destroystokyo.paper.event.entity.EntityPathfindEvent(this.mob.getBukkitEntity(), // Paper - don't path out of world border + MCUtil.toLocation(this.mob.level, possibleTarget), target == null ? null : target.getBukkitEntity()).callEvent()) { + if (!copiedSet) { + copiedSet = true; diff --git a/patches/server/Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server/Prevent-bees-loading-chunks-checking-hive-position.patch new file mode 100644 index 0000000000..8d8fb11607 --- /dev/null +++ b/patches/server/Prevent-bees-loading-chunks-checking-hive-position.patch @@ -0,0 +1,18 @@ +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/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + if (!this.hasHive()) { + return false; + } else { ++ if (level.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) + BlockEntity tileentity = this.level.getBlockEntity(this.hivePos); + + return tileentity != null && tileentity.getType() == BlockEntityType.BEEHIVE; diff --git a/patches/server/Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server/Prevent-chunk-loading-from-Fluid-Flowing.patch new file mode 100644 index 0000000000..02c2bf2d5e --- /dev/null +++ b/patches/server/Prevent-chunk-loading-from-Fluid-Flowing.patch @@ -0,0 +1,75 @@ +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/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java ++++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java +@@ -0,0 +0,0 @@ public abstract class FlowingFluid extends Fluid { + Direction enumdirection = (Direction) entry.getKey(); + FluidState fluid1 = (FluidState) entry.getValue(); + BlockPos blockposition1 = pos.relative(enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + + if (this.canSpreadTo(world, pos, blockState, enumdirection, blockposition1, iblockdata1, world.getFluidState(blockposition1), fluid1.getType())) { + // CraftBukkit start +@@ -0,0 +0,0 @@ public abstract class FlowingFluid extends Fluid { + while (iterator.hasNext()) { + Direction enumdirection = (Direction) iterator.next(); + BlockPos blockposition1 = pos.relative(enumdirection); +- BlockState iblockdata1 = world.getBlockState(blockposition1); ++ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); // Paper ++ if (iblockdata1 == null) continue; // Paper + FluidState fluid = iblockdata1.getFluidState(); + + if (fluid.getType().isSame((Fluid) this) && this.canPassThroughWall(enumdirection, (BlockGetter) world, pos, state, blockposition1, iblockdata1)) { +@@ -0,0 +0,0 @@ public abstract class FlowingFluid extends Fluid { + if (enumdirection1 != enumdirection) { + BlockPos blockposition2 = blockposition.relative(enumdirection1); + short short0 = FlowingFluid.getCacheKey(blockposition1, blockposition2); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (k) -> { +- BlockState iblockdata1 = world.getBlockState(blockposition2); ++ // Paper start - avoid loading chunks ++ Pair pair = short2objectmap.get(short0); ++ if (pair == null) { ++ BlockState iblockdatax = world.getTypeIfLoaded(blockposition2); ++ if (iblockdatax == null) { ++ continue; ++ } + +- return Pair.of(iblockdata1, iblockdata1.getFluidState()); +- }); ++ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + BlockState iblockdata1 = (BlockState) pair.getFirst(); + FluidState fluid = (FluidState) pair.getSecond(); + +@@ -0,0 +0,0 @@ public abstract class FlowingFluid extends Fluid { + Direction enumdirection = (Direction) iterator.next(); + BlockPos blockposition1 = pos.relative(enumdirection); + short short0 = FlowingFluid.getCacheKey(pos, blockposition1); +- Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (j) -> { +- BlockState iblockdata1 = world.getBlockState(blockposition1); +- +- return Pair.of(iblockdata1, iblockdata1.getFluidState()); +- }); ++ // Paper start ++ Pair pair = (Pair) short2objectmap.get(short0); ++ if (pair == null) { ++ BlockState iblockdatax = world.getTypeIfLoaded(blockposition1); ++ if (iblockdatax == null) continue; ++ ++ pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); ++ short2objectmap.put(short0, pair); ++ } ++ // Paper end + BlockState iblockdata1 = (BlockState) pair.getFirst(); + FluidState fluid = (FluidState) pair.getSecond(); + FluidState fluid1 = this.getNewLiquid(world, blockposition1, iblockdata1); diff --git a/patches/server/Prevent-consuming-the-wrong-itemstack.patch b/patches/server/Prevent-consuming-the-wrong-itemstack.patch new file mode 100644 index 0000000000..08666eaec6 --- /dev/null +++ b/patches/server/Prevent-consuming-the-wrong-itemstack.patch @@ -0,0 +1,52 @@ +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.entityData.set(LivingEntity.DATA_LIVING_ENTITY_FLAGS, (byte) j); + } + +- public void startUsingItem(InteractionHand hand) { +- ItemStack itemstack = this.getItemInHand(hand); ++ // Paper start -- OBFHELPER and forwarder to method with forceUpdate parameter ++ public void startUsingItem(InteractionHand hand) { this.updateActiveItem(hand, false); } ++ public void updateActiveItem(InteractionHand enumhand, boolean forceUpdate) { ++ // Paper end ++ ItemStack itemstack = this.getItemInHand(enumhand); + +- if (!itemstack.isEmpty() && !this.isUsingItem()) { ++ if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag + this.useItem = itemstack; + this.useItemRemaining = itemstack.getUseDuration(); + if (!this.level.isClientSide) { + this.setLivingEntityFlag(1, true); +- this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND); ++ this.setLivingEntityFlag(2, enumhand == InteractionHand.OFF_HAND); + } + + } +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.releaseUsingItem(); + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { ++ this.updateActiveItem(this.getUsedItemHand(), true); // Paper + this.triggerItemUseEffects(this.useItem, 16); + // CraftBukkit start - fire PlayerItemConsumeEvent + ItemStack itemstack; +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + this.stopUsingItem(); +- // Paper start - if the replacement is anything but the default, update the client inventory +- if (this instanceof ServerPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { ++ // Paper start ++ if (this instanceof ServerPlayer) { + ((ServerPlayer) this).getBukkitEntity().updateInventory(); + } + // Paper end diff --git a/Spigot-Server-Patches/Prevent-grindstones-from-overstacking-items.patch b/patches/server/Prevent-grindstones-from-overstacking-items.patch similarity index 54% rename from Spigot-Server-Patches/Prevent-grindstones-from-overstacking-items.patch rename to patches/server/Prevent-grindstones-from-overstacking-items.patch index c3b1391c76..b3717d50b5 100644 --- a/Spigot-Server-Patches/Prevent-grindstones-from-overstacking-items.patch +++ b/patches/server/Prevent-grindstones-from-overstacking-items.patch @@ -4,18 +4,18 @@ 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 +diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.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()) { +--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java +@@ -0,0 +0,0 @@ public class GrindstoneMenu extends AbstractContainerMenu { + i = Math.max(item.getMaxDamage() - l, 0); + itemstack2 = this.mergeEnchants(itemstack, itemstack1); + if (!itemstack2.isDamageableItem()) { - 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(); + this.resultSlots.setItem(0, ItemStack.EMPTY); + this.broadcastChanges(); return; } diff --git a/Spigot-Server-Patches/Prevent-headless-pistons-from-being-created.patch b/patches/server/Prevent-headless-pistons-from-being-created.patch similarity index 52% rename from Spigot-Server-Patches/Prevent-headless-pistons-from-being-created.patch rename to patches/server/Prevent-headless-pistons-from-being-created.patch index 0e6f3a9e31..6c5399dedd 100644 --- a/Spigot-Server-Patches/Prevent-headless-pistons-from-being-created.patch +++ b/patches/server/Prevent-headless-pistons-from-being-created.patch @@ -26,49 +26,36 @@ diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/j 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; +@@ -0,0 +0,0 @@ import java.util.Random; + 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.core.BlockPos; ++import net.minecraft.core.Direction; + import net.minecraft.core.Vec3i; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.server.level.ServerLevel; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.BaseFireBlock; + import net.minecraft.world.level.block.Block; 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; + import net.minecraft.world.level.block.entity.BlockEntity; ++import net.minecraft.world.level.block.piston.PistonHeadBlock; ++import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.material.FluidState; @@ -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 + if (f > 0.0F && this.damageCalculator.shouldBlockExplode(this, this.level, 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())); ++ BlockEntity extension = this.level.getBlockEntity(blockposition); ++ if (extension instanceof PistonMovingBlockEntity && ((PistonMovingBlockEntity) extension).isSourcePiston()) { ++ Direction direction = iblockdata.getValue(PistonHeadBlock.FACING); ++ set.add(blockposition.relative(direction.getOpposite())); + } + } + // 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/patches/server/Prevent-logins-from-being-processed-when-the-player-.patch b/patches/server/Prevent-logins-from-being-processed-when-the-player-.patch new file mode 100644 index 0000000000..2e3d6659a0 --- /dev/null +++ b/patches/server/Prevent-logins-from-being-processed-when-the-player-.patch @@ -0,0 +1,24 @@ +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/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener + } + // Paper end + if (this.state == ServerLoginPacketListenerImpl.State.READY_TO_ACCEPT) { +- this.handleAcceptedLogin(); ++ // Paper start - prevent logins to be processed even though disconnect was called ++ if (connection.isConnected()) { ++ this.handleAcceptedLogin(); ++ } ++ // Paper end + } else if (this.state == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) { + ServerPlayer entityplayer = this.server.getPlayerList().getPlayer(this.gameProfile.getId()); + diff --git a/patches/server/Prevent-mob-spawning-from-loading-generating-chunks.patch b/patches/server/Prevent-mob-spawning-from-loading-generating-chunks.patch new file mode 100644 index 0000000000..acc3086a69 --- /dev/null +++ b/patches/server/Prevent-mob-spawning-from-loading-generating-chunks.patch @@ -0,0 +1,32 @@ +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/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + StructureFeatureManager structuremanager = world.structureFeatureManager(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + int i = pos.getY(); +- BlockState iblockdata = chunk.getBlockState(pos); ++ BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn + +- if (!iblockdata.isRedstoneConductor(chunk, pos)) { ++ if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + int j = 0; + int k = 0; +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + if (entityhuman != null) { + double d2 = entityhuman.distanceToSqr(d0, (double) i, d1); + +- if (NaturalSpawner.isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { ++ if (world.isLoadedAndInBounds(blockposition_mutableblockposition) && NaturalSpawner.isRightDistanceToPlayerAndSpawnPoint(world, chunk, blockposition_mutableblockposition, d2)) { // Paper - don't load chunks for mob spawn + if (biomesettingsmobs_c == null) { + Optional optional = NaturalSpawner.getRandomSpawnMobAt(world, structuremanager, chunkgenerator, group, world.random, (BlockPos) blockposition_mutableblockposition); + diff --git a/patches/server/Prevent-opening-inventories-when-frozen.patch b/patches/server/Prevent-opening-inventories-when-frozen.patch new file mode 100644 index 0000000000..802dc6eb4c --- /dev/null +++ b/patches/server/Prevent-opening-inventories-when-frozen.patch @@ -0,0 +1,50 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + containerUpdateDelay = level.paperConfig.containerUpdateTickRate; + } + // Paper end +- if (!this.level.isClientSide && !this.containerMenu.stillValid(this)) { ++ if (!this.level.isClientSide && this.containerMenu != this.inventoryMenu && (isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - auto close while frozen + this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper + this.containerMenu = this.inventoryMenu; + } +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } else { + // CraftBukkit start + this.containerMenu = container; +- this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); ++ if (!isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper + // CraftBukkit end + this.initMenu(container); + return OptionalInt.of(this.containerCounter); +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.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.initMenu(container); + } +@@ -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.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper ++ if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper + player.containerMenu = container; + player.initMenu(container); + } diff --git a/Spigot-Server-Patches/Prevent-position-desync-in-playerconnection-causing-.patch b/patches/server/Prevent-position-desync-in-playerconnection-causing-.patch similarity index 57% rename from Spigot-Server-Patches/Prevent-position-desync-in-playerconnection-causing-.patch rename to patches/server/Prevent-position-desync-in-playerconnection-causing-.patch index 52ab763df6..34a996e3a4 100644 --- a/Spigot-Server-Patches/Prevent-position-desync-in-playerconnection-causing-.patch +++ b/patches/server/Prevent-position-desync-in-playerconnection-causing-.patch @@ -13,19 +13,19 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser - 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 + this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9)); + this.player.setOnGround(packet.isOnGround()); // CraftBukkit - SPIGOT-5810, SPIGOT-5835: reset by this.player.move + // Paper start - prevent position desync -+ if (this.teleportPos != null) { ++ if (this.awaitingPositionFromClient != null) { + return; // ... thanks Mojang for letting move calls teleport across dimensions. + } + // Paper end - prevent position desync double d12 = d8; - d7 = d4 - this.player.locX(); + d7 = d0 - this.player.getX(); diff --git a/patches/server/Prevent-rayTrace-from-loading-chunks.patch b/patches/server/Prevent-rayTrace-from-loading-chunks.patch new file mode 100644 index 0000000000..a7c058ce14 --- /dev/null +++ b/patches/server/Prevent-rayTrace-from-loading-chunks.patch @@ -0,0 +1,29 @@ +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/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BlockGetter.java ++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java +@@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor { + + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + default BlockHitResult rayTraceBlock(ClipContext raytrace1, BlockPos blockposition) { +- BlockState iblockdata = this.getBlockState(blockposition); ++ // Paper start - Prevent raytrace from loading chunks ++ BlockState iblockdata = this.getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ // copied the last function parameter (listed below) ++ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); ++ ++ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), new BlockPos(raytrace1.getTo())); ++ } ++ // Paper end + FluidState fluid = this.getFluidState(blockposition); + Vec3 vec3d = raytrace1.getFrom(); + Vec3 vec3d1 = raytrace1.getTo(); diff --git a/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch new file mode 100644 index 0000000000..fc67e01e55 --- /dev/null +++ b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch @@ -0,0 +1,20 @@ +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/SleepInBed.java b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/SleepInBed.java +@@ -0,0 +0,0 @@ public class SleepInBed extends Behavior { + } + } + +- BlockState blockState = world.getBlockState(globalPos.pos()); ++ BlockState blockState = world.getTypeIfLoaded(globalPos.pos()); // Paper ++ if (blockState == null) { return false; } // Paper + return globalPos.pos().closerThan(entity.position(), 2.0D) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED); + } + } diff --git a/patches/server/Prevent-teleporting-dead-entities.patch b/patches/server/Prevent-teleporting-dead-entities.patch new file mode 100644 index 0000000000..ec00c16755 --- /dev/null +++ b/patches/server/Prevent-teleporting-dead-entities.patch @@ -0,0 +1,21 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + + private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set set, boolean flag) { ++ if (player.isRemoved()) { ++ LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); ++ return; ++ } + // CraftBukkit start + if (Float.isNaN(f)) { + f = 0; diff --git a/patches/server/Prevent-tile-entity-and-entity-crashes.patch b/patches/server/Prevent-tile-entity-and-entity-crashes.patch new file mode 100644 index 0000000000..4529083987 --- /dev/null +++ b/patches/server/Prevent-tile-entity-and-entity-crashes.patch @@ -0,0 +1,66 @@ +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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + try { + tickConsumer.accept(entity); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +- +- entity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("Entity threw exception at " + entity.level.getWorld().getName() + ":" + entity.getX() + "," + entity.getY() + "," + entity.getZ()); ++ throwable.printStackTrace(); ++ entity.discard(); ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { + return minecraftkey + " // " + this.getClass().getCanonicalName(); + }); + if (this.level != null) { +- CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.getBlockState()); ++ // Paper start - Prevent TileEntity and Entity crashes ++ BlockState block = this.getBlockState(); ++ if (block != null) { ++ CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, block); ++ } ++ // Paper end + CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition)); + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + + gameprofilerfiller.pop(); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); +- +- this.blockEntity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent tile entity and entity crashes ++ System.err.println("TileEntity threw exception at " + LevelChunk.this.getLevel().getWorld().getName() + ":" + this.getPos().getX() + "," + this.getPos().getY() + "," + this.getPos().getZ()); ++ throwable.printStackTrace(); ++ LevelChunk.this.removeBlockEntity(this.getPos()); ++ // Paper end + // Spigot start + } finally { + this.blockEntity.tickTimer.stopTiming(); diff --git a/patches/server/Print-Error-details-when-failing-to-save-player-data.patch b/patches/server/Print-Error-details-when-failing-to-save-player-data.patch new file mode 100644 index 0000000000..73c235e1a0 --- /dev/null +++ b/patches/server/Print-Error-details-when-failing-to-save-player-data.patch @@ -0,0 +1,19 @@ +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/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +@@ -0,0 +0,0 @@ public class PlayerDataStorage { + + Util.safeReplaceFile(file1, file, file2); + } catch (Exception exception) { +- PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", player.getName().getString()); ++ PlayerDataStorage.LOGGER.warn("Failed to save player data for {}", player.getScoreboardName(), exception); // Paper + } + + } diff --git a/Spigot-Server-Patches/Profile-Lookup-Events.patch b/patches/server/Profile-Lookup-Events.patch similarity index 100% rename from Spigot-Server-Patches/Profile-Lookup-Events.patch rename to patches/server/Profile-Lookup-Events.patch diff --git a/Spigot-Server-Patches/ProfileWhitelistVerifyEvent.patch b/patches/server/ProfileWhitelistVerifyEvent.patch similarity index 65% rename from Spigot-Server-Patches/ProfileWhitelistVerifyEvent.patch rename to patches/server/ProfileWhitelistVerifyEvent.patch index 5b6d8129f8..9fece971c0 100644 --- a/Spigot-Server-Patches/ProfileWhitelistVerifyEvent.patch +++ b/patches/server/ProfileWhitelistVerifyEvent.patch @@ -12,29 +12,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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"); +- } else if (!this.isWhiteListed(gameprofile)) { +- chatmessage = new TranslatableComponent("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); + } else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) { + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); @@ -0,0 +0,0 @@ public abstract class PlayerList { - this.server.getCommandDispatcher().a(entityplayer); + this.server.getCommands().sendCommands(player); } + // 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 profile) { +- return !this.doWhiteList || this.ops.contains(profile) || this.whitelist.contains(profile); ++ return isWhitelisted(profile, 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); ++ boolean isOp = this.ops.contains(gameprofile); ++ boolean isWhitelisted = !this.doWhiteList || isOp || this.whitelist.contains(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(net.minecraft.server.MCUtil.toBukkit(gameprofile), this.doWhiteList, isWhitelisted, isOp, org.spigotmc.SpigotConfig.whitelistMessage); + event.callEvent(); + if (!event.isWhitelisted()) { + if (loginEvent != null) { @@ -46,5 +46,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end - public boolean isOp(GameProfile gameprofile) { - return this.operators.d(gameprofile) || this.server.a(gameprofile) && this.server.getSaveData().o() || this.v; + public boolean isOp(GameProfile profile) { + return this.ops.contains(profile) || this.server.isSingleplayerOwner(profile) && this.server.getWorldData().getAllowCommands() || this.allowCheatsForAllPlayers; diff --git a/patches/server/Properly-fix-item-duplication-bug.patch b/patches/server/Properly-fix-item-duplication-bug.patch new file mode 100644 index 0000000000..c69988ba19 --- /dev/null +++ b/patches/server/Properly-fix-item-duplication-bug.patch @@ -0,0 +1,33 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + + @Override + public boolean isImmobile() { +- return super.isImmobile() || !this.getBukkitEntity().isOnline(); ++ return super.isImmobile() || (this.connection != null && this.connection.isDisconnected()); // Paper + } + + @Override +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + + public final boolean isDisconnected() { +- return !this.player.joining && !this.connection.isConnected(); ++ return (!this.player.joining && !this.connection.isConnected()) || this.processedDisconnect; // Paper + } + // CraftBukkit end + diff --git a/Spigot-Server-Patches/Properly-handle-async-calls-to-restart-the-server.patch b/patches/server/Properly-handle-async-calls-to-restart-the-server.patch similarity index 81% rename from Spigot-Server-Patches/Properly-handle-async-calls-to-restart-the-server.patch rename to patches/server/Properly-handle-async-calls-to-restart-the-server.patch index 56b481e5f5..7d288af0fb 100644 --- a/Spigot-Server-Patches/Properly-handle-async-calls-to-restart-the-server.patch +++ b/patches/server/Properly-handle-async-calls-to-restart-the-server.patch @@ -33,73 +33,56 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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; +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop, ServerLevel> levels; private PlayerList playerList; - private volatile boolean isRunning; + private volatile boolean running; + private volatile boolean isRestarting = false; // Paper - flag to signify we're attempting to restart - private boolean isStopped; - private int ticks; + private boolean stopped; + private int tickCount; protected final Proxy proxy; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant) MinecraftServer.getServer().getPlayerList().players ) +- for ( ServerPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) - { -- p.playerConnection.disconnect(SpigotConfig.restartMessage); +- p.connection.disconnect(SpigotConfig.restartMessage); - } - // Give the socket a chance to send the packets - try @@ -146,16 +129,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - { - } - // Close the socket so we can rebind with the new process -- MinecraftServer.getServer().getServerConnection().b(); +- MinecraftServer.getServer().getConnection().stop(); + // Paper start - sync copied from above with minor changes, async added + private static void shutdownServer(boolean isRestarting) + { -+ if ( MinecraftServer.getServer().isMainThread() ) ++ if ( MinecraftServer.getServer().isSameThread() ) + { + // Kick all players -+ for ( EntityPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) ++ for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) + { -+ p.playerConnection.disconnect(SpigotConfig.restartMessage); ++ p.connection.disconnect(SpigotConfig.restartMessage); + } + // Give the socket a chance to send the packets + try @@ -223,7 +206,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static void closeSocket() + { + // Close the socket so we can rebind with the new process -+ MinecraftServer.getServer().getServerConnection().b(); ++ MinecraftServer.getServer().getConnection().stop(); + + // Give time for it to kick in + try diff --git a/Spigot-Server-Patches/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 53% rename from Spigot-Server-Patches/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch index db921d24e0..ddcc875e5c 100644 --- a/Spigot-Server-Patches/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -40,43 +40,43 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + BlockPos blockposition = new BlockPos(d4, d5, d6); + BlockState iblockdata = this.level.getBlockState(blockposition); + if (!iblockdata.isDestroyable()) continue; // Paper - Fluid fluid = iblockdata.getFluid(); // Paper - Optional optional = this.l.a(this, this.world, blockposition, iblockdata, fluid); + FluidState fluid = iblockdata.getFluidState(); // Paper + if (!this.level.isInWorldBounds(blockposition)) { @@ -0,0 +0,0 @@ public class Explosion { - IBlockData iblockdata = this.world.getType(blockposition); + BlockState iblockdata = this.level.getBlockState(blockposition); Block block = iblockdata.getBlock(); - if (!iblockdata.isAir()) { + if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper - BlockPosition blockposition1 = blockposition.immutableCopy(); + BlockPos blockposition1 = blockposition.immutable(); - 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 + this.level.getProfiler().push("explosion_blocks"); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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) { +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { // CraftBukkit start - tree generation if (this.captureTreeGeneration) { + // Paper start -+ IBlockData type = getType(blockposition); ++ BlockState type = getBlockState(pos); + if (!type.isDestroyable()) return false; + // Paper end - CraftBlockState blockstate = capturedBlockStates.get(blockposition); + CraftBlockState blockstate = this.capturedBlockStates.get(pos); if (blockstate == null) { - blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i); + blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); 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; +@@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike { + protected final StateDefinition stateDefinition; + private BlockState defaultBlockState; // Paper start + public final boolean isDestroyable() { + return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || @@ -94,64 +94,64 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.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 { +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { @Override - public boolean a(IBlockData iblockdata, World world, BlockPosition blockposition, int i, int j) { - EnumDirection enumdirection = (EnumDirection) iblockdata.get(BlockPiston.FACING); + public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { + Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.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 ++ Direction directionQueuedAs = Direction.from3DDataValue(data & 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); + boolean flag = this.getNeighborSignal(world, pos, enumdirection); +@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { + BlockState iblockdata1 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.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 { + world.setBlock(pos, iblockdata1, 20); +- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata1, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); ++ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata1, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change + world.blockUpdated(pos, iblockdata1.getBlock()); + iblockdata1.updateNeighbourShapes(world, pos, 2); + if (this.isSticky) { +@@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { } } } else { -- world.a(blockposition.shift(enumdirection), false); +- world.removeBlock(pos.relative(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); ++ BlockPos headPos = pos.relative(enumdirection); ++ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston. ++ world.removeBlock(headPos, false); + } else { -+ ((WorldServer)world).getChunkProvider().flagDirty(headPos); // ... fix client desync ++ ((ServerLevel)world).getChunkSource().blockChanged(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 + world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F); +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java 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 { +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { @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 + public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { +- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())); ++ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper } @Deprecated -@@ -0,0 +0,0 @@ public abstract class BlockBase { +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { public Block getBlock() { - return (Block) this.c; + return (Block) this.owner; } - + // Paper start @@ -160,14 +160,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end public Material getMaterial() { - return this.g; + return this.material; } -@@ -0,0 +0,0 @@ public abstract class BlockBase { +@@ -0,0 +0,0 @@ public abstract class BlockBehaviour { } - public EnumPistonReaction getPushReaction() { -- return this.getBlock().getPushReaction(this.p()); -+ return !isDestroyable() ? EnumPistonReaction.BLOCK : this.getBlock().getPushReaction(this.p()); // Paper + public PushReaction getPistonPushReaction() { +- return this.getBlock().getPistonPushReaction(this.asState()); ++ return !isDestroyable() ? PushReaction.BLOCK : this.getBlock().getPistonPushReaction(this.asState()); // Paper } - public boolean i(IBlockAccess iblockaccess, BlockPosition blockposition) { + public boolean isSolidRender(BlockGetter world, BlockPos pos) { diff --git a/patches/server/Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server/Provide-E-TE-Chunk-count-stat-methods.patch new file mode 100644 index 0000000000..e6b047ed44 --- /dev/null +++ b/patches/server/Provide-E-TE-Chunk-count-stat-methods.patch @@ -0,0 +1,83 @@ +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/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public static final int TICKS_PER_DAY = 24000; + public static final int MAX_ENTITY_SPAWN_Y = 20000000; + public static final int MIN_ENTITY_SPAWN_Y = -20000000; +- protected final List blockEntityTickers = Lists.newArrayList(); ++ protected final List blockEntityTickers = Lists.newArrayList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper + private final List pendingBlockEntityTickers = Lists.newArrayList(); + private boolean tickingBlockEntities; + public final Thread thread; +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 ++ @Override ++ public int getEntityCount() { ++ int ret = 0; ++ for (net.minecraft.world.entity.Entity entity : world.getEntities().getAll()) { ++ if (entity.isChunkLoaded()) { ++ ++ret; ++ } ++ } ++ return ret; ++ } ++ ++ @Override ++ public int getTileEntityCount() { ++ // We don't use the full world tile entity list, so we must iterate chunks ++ Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; ++ int size = 0; ++ for (ChunkHolder playerchunk : chunks.values()) { ++ net.minecraft.world.level.chunk.LevelChunk chunk = playerchunk.getTickingChunk(); ++ if (chunk == null) { ++ continue; ++ } ++ size += chunk.blockEntities.size(); ++ } ++ return size; ++ } ++ ++ @Override ++ public int getTickableTileEntityCount() { ++ return world.getTotalTileEntityTickers(); ++ } ++ ++ @Override ++ public int getChunkCount() { ++ int ret = 0; ++ ++ for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) { ++ if (chunkHolder.getTickingChunk() != null) { ++ ++ret; ++ } ++ } ++ ++ return ret; ++ } ++ ++ @Override ++ public int getPlayerCount() { ++ return world.players().size(); ++ } ++ // Paper end ++ + private static final Random rand = new Random(); + + public CraftWorld(ServerLevel world, ChunkGenerator gen, Environment env) { diff --git a/Spigot-Server-Patches/RangedEntity-API.patch b/patches/server/RangedEntity-API.patch similarity index 71% rename from Spigot-Server-Patches/RangedEntity-API.patch rename to patches/server/RangedEntity-API.patch index 158cce5cc6..d304517f18 100644 --- a/Spigot-Server-Patches/RangedEntity-API.patch +++ b/patches/server/RangedEntity-API.patch @@ -14,11 +14,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package com.destroystokyo.paper.entity; + -+import net.minecraft.world.entity.monster.IRangedEntity; ++import net.minecraft.world.entity.monster.RangedAttackMob; +import org.bukkit.craftbukkit.entity.CraftLivingEntity; +import org.bukkit.entity.LivingEntity; + -+public interface CraftRangedEntity extends RangedEntity { ++public interface CraftRangedEntity extends RangedEntity { + T getHandle(); + + @Override @@ -31,16 +31,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.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; +--- a/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java ++++ b/src/main/java/net/minecraft/world/entity/monster/RangedAttackMob.java +@@ -0,0 +0,0 @@ package net.minecraft.world.entity.monster; + import net.minecraft.world.entity.LivingEntity; - 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 + public interface RangedAttackMob { +- void performRangedAttack(LivingEntity target, float pullProgress); ++ void performRangedAttack(LivingEntity target, float pullProgress); @Deprecated default void rangedAttack(LivingEntity entityliving, float f) { performRangedAttack(entityliving, f); } // Paper - OBFHELPER + + // - see EntitySkeletonAbstract melee goal + void setAggressive(boolean flag); default void setChargingAttack(boolean charging) { setAggressive(charging); }; // Paper @@ -54,9 +54,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 class CraftDrowned extends CraftZombie implements Drowned, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftDrowned(CraftServer server, EntityDrowned entity) { + public CraftDrowned(CraftServer server, net.minecraft.world.entity.monster.Drowned 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 @@ -67,29 +67,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 class CraftIllusioner extends CraftSpellcaster implements Illusioner, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftIllusioner(CraftServer server, EntityIllagerIllusioner entity) { + public CraftIllusioner(CraftServer server, net.minecraft.world.entity.monster.Illusioner 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 class CraftLlama extends CraftChestedHorse implements Llama, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftLlama(CraftServer server, EntityLlama entity) { + public CraftLlama(CraftServer server, net.minecraft.world.entity.animal.horse.Llama 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 @@ -100,9 +93,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftPiglin(CraftServer server, EntityPiglin entity) { + public CraftPiglin(CraftServer server, net.minecraft.world.entity.monster.piglin.Piglin 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 @@ -113,22 +106,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 class CraftPillager extends CraftIllager implements Pillager, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftPillager(CraftServer server, EntityPillager entity) { + public CraftPillager(CraftServer server, net.minecraft.world.entity.monster.Pillager 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; +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.CraftServer; + 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 class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton { ++public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper - public CraftSkeleton(CraftServer server, EntitySkeletonAbstract entity) { + public CraftSkeleton(CraftServer server, net.minecraft.world.entity.monster.Skeleton 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 @@ -139,8 +132,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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) { ++public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftSnowman(CraftServer server, SnowGolem 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 @@ -152,8 +145,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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) { ++public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch 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 @@ -165,7 +158,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 ++public class CraftWither extends CraftMonster implements Wither, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper private BossBar bossBar; diff --git a/Spigot-Server-Patches/Reduce-Either-Optional-allocation.patch b/patches/server/Reduce-Either-Optional-allocation.patch similarity index 100% rename from Spigot-Server-Patches/Reduce-Either-Optional-allocation.patch rename to patches/server/Reduce-Either-Optional-allocation.patch diff --git a/patches/server/Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/Reduce-MutableInt-allocations-from-light-engine.patch new file mode 100644 index 0000000000..c0103698e2 --- /dev/null +++ b/patches/server/Reduce-MutableInt-allocations-from-light-engine.patch @@ -0,0 +1,50 @@ +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/BlockLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +@@ -0,0 +0,0 @@ import org.apache.commons.lang3.mutable.MutableInt; + public final class BlockLightEngine extends LayerLightEngine { + private static final Direction[] DIRECTIONS = Direction.values(); + private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ private final MutableInt mutableInt = new MutableInt(); // Paper + + public BlockLightEngine(LightChunkGetter chunkProvider) { + super(chunkProvider, LightLayer.BLOCK, new BlockLightSectionStorage(chunkProvider)); +@@ -0,0 +0,0 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { + return 15; +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +@@ -0,0 +0,0 @@ import org.apache.commons.lang3.mutable.MutableInt; + public final class SkyLightEngine extends LayerLightEngine { + private static final Direction[] DIRECTIONS = Direction.values(); + private static final Direction[] HORIZONTALS = new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST}; ++ private final MutableInt mutableInt = new MutableInt(); // Paper + + public SkyLightEngine(LightChunkGetter chunkProvider) { + super(chunkProvider, LightLayer.SKY, new SkyLightSectionStorage(chunkProvider)); +@@ -0,0 +0,0 @@ public final class SkyLightEngine extends LayerLightEngine= 15) { + return level; + } else { +- MutableInt mutableInt = new MutableInt(); ++ //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded + BlockState blockState = this.getStateAndOpacity(targetId, mutableInt); + if (mutableInt.getValue() >= 15) { + return 15; diff --git a/patches/server/Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/Reduce-allocation-of-Vec3D-by-entity-tracker.patch new file mode 100644 index 0000000000..e8d8a15032 --- /dev/null +++ b/patches/server/Reduce-allocation-of-Vec3D-by-entity-tracker.patch @@ -0,0 +1,61 @@ +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/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + public void updatePlayer(ServerPlayer player) { + org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot + if (player != this.entity) { +- Vec3 vec3d = player.position().subtract(this.entity.position()); // 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 = player.getX() - this.entity.getX(); ++ double vec3d_dy = player.getY() - this.entity.getY(); ++ double vec3d_dz = player.getZ() - this.entity.getZ(); ++ // Paper end - remove allocation of Vec3D here + int i = Math.min(this.getEffectiveRange(), (ChunkMap.this.viewDistance - 1) * 16); +- boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.entity.broadcastToPlayer(player); ++ boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.entity.broadcastToPlayer(player); // Paper - remove allocation of Vec3D here + + // CraftBukkit start - respect vanish API + if (this.entity instanceof ServerPlayer) { +diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -0,0 +0,0 @@ public class ServerEntity { + ++this.teleportDelay; + i = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); + j = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); +- Vec3 vec3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp)); +- boolean flag1 = vec3d.lengthSqr() >= 7.62939453125E-6D; ++ // Paper start - reduce allocation of Vec3D here ++ double vec3d_dx = this.entity.getX() - 2.44140625E-4D*(this.xp); ++ double vec3d_dy = this.entity.getY() - 2.44140625E-4D*(this.yp); ++ double vec3d_dz = this.entity.getZ() - 2.44140625E-4D*(this.zp); ++ 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.tickCount % 60 == 0; + boolean flag3 = Math.abs(i - this.yRotp) >= 1 || Math.abs(j - this.xRotp) >= 1; +@@ -0,0 +0,0 @@ public class ServerEntity { + // CraftBukkit end + + if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { +- long k = ClientboundMoveEntityPacket.entityToPacket(vec3d.x); +- long l = ClientboundMoveEntityPacket.entityToPacket(vec3d.y); +- long i1 = ClientboundMoveEntityPacket.entityToPacket(vec3d.z); ++ // Paper start - remove allocation of Vec3D here ++ long k = ClientboundMoveEntityPacket.entityToPacket(vec3d_dx); ++ long l = ClientboundMoveEntityPacket.entityToPacket(vec3d_dy); ++ long i1 = ClientboundMoveEntityPacket.entityToPacket(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.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.isOnGround()) { diff --git a/patches/server/Reduce-blockpos-allocation-from-pathfinding.patch b/patches/server/Reduce-blockpos-allocation-from-pathfinding.patch new file mode 100644 index 0000000000..19d4b878bd --- /dev/null +++ b/patches/server/Reduce-blockpos-allocation-from-pathfinding.patch @@ -0,0 +1,28 @@ +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/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java ++++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java +@@ -0,0 +0,0 @@ public class WalkNodeEvaluator extends NodeEvaluator { + return BlockPathTypes.DANGER_FIRE; + } + +- if (world.getFluidState(pos).is(FluidTags.WATER)) { ++ if (blockState.getFluidState().is(FluidTags.WATER)) { + return BlockPathTypes.WATER_BORDER; + } + } // Paper +@@ -0,0 +0,0 @@ public class WalkNodeEvaluator extends NodeEvaluator { + } else if (blockState.is(Blocks.COCOA)) { + return BlockPathTypes.COCOA; + } else { +- FluidState fluidState = world.getFluidState(pos); ++ FluidState fluidState = blockState.getFluidState(); // Paper - remove another get type call + if (fluidState.is(FluidTags.LAVA)) { + return BlockPathTypes.LAVA; + } else if (isBurningBlock(blockState)) { diff --git a/patches/server/Reduce-memory-footprint-of-NBTTagCompound.patch b/patches/server/Reduce-memory-footprint-of-NBTTagCompound.patch new file mode 100644 index 0000000000..b96a3a5c84 --- /dev/null +++ b/patches/server/Reduce-memory-footprint-of-NBTTagCompound.patch @@ -0,0 +1,50 @@ +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/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -0,0 +0,0 @@ public class CompoundTag implements Tag { + if (i > 512) { + throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512"); + } else { +- Map map = Maps.newHashMap(); ++ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap map = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f); // Paper - reduce memory footprint of NBTTagCompound + + byte b; + while((b = CompoundTag.readNamedTagType(dataInput, nbtAccounter)) != 0) { +@@ -0,0 +0,0 @@ public class CompoundTag implements Tag { + } + + public CompoundTag() { +- this(Maps.newHashMap()); ++ this(new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(8, 0.8f)); // Paper - reduce memory footprint of NBTTagCompound + } + + @Override +@@ -0,0 +0,0 @@ public class CompoundTag implements Tag { + + @Override + public CompoundTag copy() { +- Map map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy)); +- return new CompoundTag(map); ++ // Paper start - reduce memory footprint of NBTTagCompound ++ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f); ++ java.util.Iterator> iterator = (this.tags instanceof it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap) ? ((it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap)this.tags).object2ObjectEntrySet().fastIterator() : this.tags.entrySet().iterator(); ++ while (iterator.hasNext()) { ++ Map.Entry entry = iterator.next(); ++ ret.put(entry.getKey(), entry.getValue().copy()); ++ } ++ ++ return new CompoundTag(ret); ++ // Paper end - reduce memory footprint of NBTTagCompound + } + + @Override diff --git a/Spigot-Server-Patches/Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server/Refresh-player-inventory-when-cancelling-PlayerInter.patch similarity index 52% rename from Spigot-Server-Patches/Refresh-player-inventory-when-cancelling-PlayerInter.patch rename to patches/server/Refresh-player-inventory-when-cancelling-PlayerInter.patch index f9ac5c62ed..801d74c634 100644 --- a/Spigot-Server-Patches/Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ b/patches/server/Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -15,15 +15,15 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { - } +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } - if (event.isCancelled()) { -+ this.player.updateInventory(this.player.activeContainer); // Paper - Refresh player inventory - return; - } - // CraftBukkit end + if (event.isCancelled()) { ++ ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote(); // Paper - Refresh player inventory + return; + } + // CraftBukkit end diff --git a/patches/server/Remap-fixes.patch b/patches/server/Remap-fixes.patch new file mode 100644 index 0000000000..1998d582c6 --- /dev/null +++ b/patches/server/Remap-fixes.patch @@ -0,0 +1,196 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Fri, 11 Jun 2021 05:25:03 -0500 +Subject: [PATCH] Remap fixes + + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/core/BlockPos.java ++++ b/src/main/java/net/minecraft/core/BlockPos.java +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + + public static Iterable withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ) { + int i = rangeX + rangeY + rangeZ; +- int j = center.getX(); +- int k = center.getY(); +- int l = center.getZ(); ++ // Paper start - rename variables to fix conflict with anonymous class (remap fix) ++ int centerX = center.getX(); ++ int centerY = center.getY(); ++ int centerZ = center.getZ(); ++ // Paper end + return () -> { + return new AbstractIterator() { + private final BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos(); +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + protected BlockPos computeNext() { + if (this.zMirror) { + this.zMirror = false; +- this.cursor.setZ(l - (this.cursor.getZ() - l)); ++ this.cursor.setZ(centerZ - (this.cursor.getZ() - centerZ)); // Paper - remap fix + return this.cursor; + } else { + BlockPos blockPos; +@@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { + int k = this.currentDepth - Math.abs(i) - Math.abs(j); + if (k <= rangeZ) { + this.zMirror = k != 0; +- blockPos = this.cursor.set(j + i, k + j, l + k); ++ blockPos = this.cursor.set(centerX + i, centerY + j, centerZ + k); // Paper - remap fix + } + } + +diff --git a/src/main/java/net/minecraft/server/commands/SummonCommand.java b/src/main/java/net/minecraft/server/commands/SummonCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/commands/SummonCommand.java ++++ b/src/main/java/net/minecraft/server/commands/SummonCommand.java +@@ -0,0 +0,0 @@ public class SummonCommand { + + nbttagcompound1.putString("id", entity.toString()); + ServerLevel worldserver = source.getLevel(); +- Entity entity1 = EntityType.loadEntityRecursive(nbttagcompound1, worldserver, (entity1) -> { +- entity1.moveTo(pos.x, pos.y, pos.z, entity1.getYRot(), entity1.getXRot()); +- return entity1; ++ Entity entity1 = EntityType.loadEntityRecursive(nbttagcompound1, worldserver, (loadedEntity) -> { // Paper - remap fix ++ loadedEntity.moveTo(pos.x, pos.y, pos.z, loadedEntity.getYRot(), loadedEntity.getXRot()); // Paper - remap fix ++ return loadedEntity; // Paper - remap fix + }); + + if (entity1 == null) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -0,0 +0,0 @@ public class BehaviorUtils { + + return optional.map((uuid) -> { + return ((ServerLevel) entity.level).getEntity(uuid); +- }).map((entity) -> { +- return entity instanceof LivingEntity ? (LivingEntity) entity : null; ++ }).map((entity2) -> { // Paper - remap fix ++ return entity2 instanceof LivingEntity ? (LivingEntity) entity2 : null; // Paper - remap fix + }); + } + +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -0,0 +0,0 @@ public class Phantom extends FlyingMob implements Enemy { + List list = Phantom.this.level.getNearbyPlayers(this.attackTargeting, (LivingEntity) Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + + if (!list.isEmpty()) { +- list.sort(Comparator.comparing(Entity::getY).reversed()); ++ list.sort(Comparator.comparing(Entity::getY).reversed()); // Paper - remap fix + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java ++++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java +@@ -0,0 +0,0 @@ public class RecipeManager extends SimpleJsonResourceReloadListener { + Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); // CraftBukkit + + recipes.forEach((irecipe) -> { +- Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes) -> { ++ Map> map1 = (Map) map.computeIfAbsent(irecipe.getType(), (recipes_) -> { // Paper - remap fix + return new Object2ObjectLinkedOpenHashMap<>(); // CraftBukkit + }); + Recipe irecipe1 = (Recipe) map1.put(irecipe.getId(), irecipe); +diff --git a/src/test/java/org/bukkit/DyeColorsTest.java b/src/test/java/org/bukkit/DyeColorsTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/DyeColorsTest.java ++++ b/src/test/java/org/bukkit/DyeColorsTest.java +@@ -0,0 +0,0 @@ import static org.hamcrest.Matchers.*; + import static org.junit.Assert.*; + import java.util.ArrayList; + import java.util.List; +-import net.minecraft.world.item.DyeColor; + import org.bukkit.support.AbstractTestingBase; + import org.junit.Test; + import org.junit.runner.RunWith; +@@ -0,0 +0,0 @@ public class DyeColorsTest extends AbstractTestingBase { + @Test + public void checkColor() { + Color color = this.dye.getColor(); +- float[] nmsColorArray = DyeColor.byId(this.dye.getWoolData()).getTextureDiffuseColors(); ++ float[] nmsColorArray = net.minecraft.world.item.DyeColor.byId(this.dye.getWoolData()).getTextureDiffuseColors(); // Paper - remap fix + Color nmsColor = Color.fromRGB((int) (nmsColorArray[0] * 255), (int) (nmsColorArray[1] * 255), (int) (nmsColorArray[2] * 255)); + assertThat(color, is(nmsColor)); + } +@@ -0,0 +0,0 @@ public class DyeColorsTest extends AbstractTestingBase { + @Test + public void checkFireworkColor() { + Color color = this.dye.getFireworkColor(); +- int nmsColor = DyeColor.byId(this.dye.getWoolData()).getFireworkColor(); ++ int nmsColor = net.minecraft.world.item.DyeColor.byId(this.dye.getWoolData()).getFireworkColor(); // Paper - remap fix + assertThat(color, is(Color.fromRGB(nmsColor))); + } + } +diff --git a/src/test/java/org/bukkit/PerMaterialTest.java b/src/test/java/org/bukkit/PerMaterialTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/PerMaterialTest.java ++++ b/src/test/java/org/bukkit/PerMaterialTest.java +@@ -0,0 +0,0 @@ public class PerMaterialTest extends AbstractTestingBase { + if (this.material.isBlock()) { + assertThat(this.material.isInteractable(), + is(!CraftMagicNumbers.getBlock(material).getClass() +- .getMethod("interact", BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, InteractionHand.class, BlockHitResult.class) ++ .getMethod("use", BlockState.class, net.minecraft.world.level.Level.class, BlockPos.class, Player.class, InteractionHand.class, BlockHitResult.class) // Paper - remap fix + .getDeclaringClass().equals(BlockBehaviour.class))); + } else { + assertFalse(this.material.isInteractable()); +diff --git a/src/test/java/org/bukkit/entity/EntityTypesTest.java b/src/test/java/org/bukkit/entity/EntityTypesTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/entity/EntityTypesTest.java ++++ b/src/test/java/org/bukkit/entity/EntityTypesTest.java +@@ -0,0 +0,0 @@ import java.util.Set; + import java.util.stream.Collectors; + import net.minecraft.core.Registry; + import net.minecraft.resources.ResourceLocation; +-import net.minecraft.world.entity.EntityType; + import org.bukkit.support.AbstractTestingBase; + import org.junit.Assert; + import org.junit.Test; +@@ -0,0 +0,0 @@ public class EntityTypesTest extends AbstractTestingBase { + public void testMaps() { + Set allBukkit = Arrays.stream(EntityType.values()).filter((b) -> b.getName() != null).collect(Collectors.toSet()); + +- for (EntityType nms : Registry.ENTITY_TYPE) { +- ResourceLocation key = EntityType.getKey(nms); ++ for (net.minecraft.world.entity.EntityType nms : Registry.ENTITY_TYPE) { // Paper - remap fix ++ ResourceLocation key = net.minecraft.world.entity.EntityType.getKey(nms); // Paper - remap fix + + org.bukkit.entity.EntityType bukkit = org.bukkit.entity.EntityType.fromName(key.getPath()); + Assert.assertNotNull("Missing nms->bukkit " + key, bukkit); +diff --git a/src/test/java/org/bukkit/entity/PandaGeneTest.java b/src/test/java/org/bukkit/entity/PandaGeneTest.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/test/java/org/bukkit/entity/PandaGeneTest.java ++++ b/src/test/java/org/bukkit/entity/PandaGeneTest.java +@@ -0,0 +0,0 @@ + package org.bukkit.entity; + +-import net.minecraft.world.entity.animal.Panda; + import org.bukkit.craftbukkit.entity.CraftPanda; + import org.junit.Assert; + import org.junit.Test; +@@ -0,0 +0,0 @@ public class PandaGeneTest { + @Test + public void testBukkit() { + for (Panda.Gene gene : Panda.Gene.values()) { +- Panda.Gene nms = CraftPanda.toNms(gene); ++ net.minecraft.world.entity.animal.Panda.Gene nms = CraftPanda.toNms(gene); // Paper - remap fix + + Assert.assertNotNull("NMS gene null for " + gene, nms); + Assert.assertEquals("Recessive status did not match " + gene, gene.isRecessive(), nms.isRecessive()); +@@ -0,0 +0,0 @@ public class PandaGeneTest { + + @Test + public void testNMS() { +- for (Panda.Gene gene : Panda.Gene.values()) { ++ for (net.minecraft.world.entity.animal.Panda.Gene gene : net.minecraft.world.entity.animal.Panda.Gene.values()) { // Paper - remap fix + org.bukkit.entity.Panda.Gene bukkit = CraftPanda.fromNms(gene); + + Assert.assertNotNull("Bukkit gene null for " + gene, bukkit); diff --git a/Spigot-Server-Patches/Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 81% rename from Spigot-Server-Patches/Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/Remote-Connections-shouldn-t-hold-up-shutdown.patch index 2c7491c56c..2dd2496aba 100644 --- a/Spigot-Server-Patches/Remote-Connections-shouldn-t-hold-up-shutdown.patch +++ b/patches/server/Remote-Connections-shouldn-t-hold-up-shutdown.patch @@ -9,16 +9,16 @@ diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b 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 +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } - if (this.remoteControlListener != null) { -- this.remoteControlListener.b(); + if (this.rconThread != null) { +- this.rconThread.stop(); + //this.remoteControlListener.b(); // Paper - don't wait for remote connections } - if (this.remoteStatusListener != null) { -- this.remoteStatusListener.b(); + if (this.queryThreadGs4 != null) { +- this.queryThreadGs4.stop(); + //this.remoteStatusListener.b(); // Paper - don't wait for remote connections } diff --git a/Spigot-Server-Patches/Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server/Remove-CraftScheduler-Async-Task-Debugger.patch similarity index 65% rename from Spigot-Server-Patches/Remove-CraftScheduler-Async-Task-Debugger.patch rename to patches/server/Remove-CraftScheduler-Async-Task-Debugger.patch index 7941dd2e6b..8184009915 100644 --- a/Spigot-Server-Patches/Remove-CraftScheduler-Async-Task-Debugger.patch +++ b/patches/server/Remove-CraftScheduler-Async-Task-Debugger.patch @@ -14,19 +14,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { } - parsePending(); + this.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 +- this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); ++ //this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper + this.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); + this.pending.addAll(temp); temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); -- debugHead = debugHead.getNextHead(currentTick); -+ //debugHead = debugHead.getNextHead(currentTick); // Paper + MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper +- this.debugHead = this.debugHead.getNextHead(currentTick); ++ //this.debugHead = this.debugHead.getNextHead(currentTick); // Paper } private void addTask(final CraftTask task) { @@ -37,9 +37,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + return ""; + /* - int debugTick = currentTick; - StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - RECENT_TICKS).append('-').append(debugTick).append('{'); - debugHead.debugTo(string); + int debugTick = this.currentTick; + StringBuilder string = new StringBuilder("Recent tasks from ").append(debugTick - CraftScheduler.RECENT_TICKS).append('-').append(debugTick).append('{'); + this.debugHead.debugTo(string); return string.append('}').toString(); + */ + // Paper end diff --git a/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch b/patches/server/Remove-FishingHook-reference-on-Craft-Entity-removal.patch similarity index 73% rename from Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch rename to patches/server/Remove-FishingHook-reference-on-Craft-Entity-removal.patch index af566cd19a..9e240ca79e 100644 --- a/Spigot-Server-Patches/Remove-FishingHook-reference-on-Craft-Entity-removal.patch +++ b/patches/server/Remove-FishingHook-reference-on-Craft-Entity-removal.patch @@ -3,6 +3,7 @@ From: Aikar Date: Thu, 16 Jun 2016 00:17:23 -0400 Subject: [PATCH] Remove FishingHook reference on Craft Entity removal +TODO 1.17 isn't this supposed to be applied to when the fish hook is removed _in general_? Not just in Bukkit api calls? 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 @@ -10,15 +11,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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()]; + return HookState.values()[this.getHandle().currentState.ordinal()]; } + + // Paper start + @Override + public void remove() { + super.remove(); -+ if (getHandle().getOwner() != null) { -+ getHandle().getOwner().hookedFish = null; ++ if (getHandle().getPlayerOwner() != null) { ++ getHandle().getPlayerOwner().fishing = null; + } + } + // Paper end diff --git a/Spigot-Server-Patches/Remove-Metadata-on-reload.patch b/patches/server/Remove-Metadata-on-reload.patch similarity index 86% rename from Spigot-Server-Patches/Remove-Metadata-on-reload.patch rename to patches/server/Remove-Metadata-on-reload.patch index c6e4d700a6..e732c32c7c 100644 --- a/Spigot-Server-Patches/Remove-Metadata-on-reload.patch +++ b/patches/server/Remove-Metadata-on-reload.patch @@ -15,9 +15,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper - pluginManager.clearPlugins(); - commandMap.clearCommands(); -+ + this.pluginManager.clearPlugins(); + this.commandMap.clearCommands(); + // Paper start + for (Plugin plugin : pluginClone) { + entityMetadata.removeAll(plugin); @@ -25,7 +24,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + playerMetadata.removeAll(plugin); + } + // Paper end -+ - resetRecipes(); - reloadData(); + this.reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot + com.destroystokyo.paper.PaperConfig.registerCommands(); // Paper diff --git a/Spigot-Server-Patches/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch b/patches/server/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch similarity index 67% rename from Spigot-Server-Patches/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch rename to patches/server/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch index 91ac1e1582..3d1ede7e19 100644 --- a/Spigot-Server-Patches/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch +++ b/patches/server/Remove-ProjectileHitEvent-call-when-fireballs-dead.patch @@ -6,14 +6,14 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.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 { +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -0,0 +0,0 @@ public abstract class AbstractHurtingProjectile extends Projectile { // CraftBukkit start - Fire ProjectileHitEvent - if (this.dead) { + if (this.isRemoved()) { - CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); + // CraftEventFactory.callProjectileHitEvent(this, movingobjectposition); // Paper - this is an undesired duplicate event } diff --git a/patches/server/Remove-invalid-mob-spawner-tile-entities.patch b/patches/server/Remove-invalid-mob-spawner-tile-entities.patch new file mode 100644 index 0000000000..a60db033f7 --- /dev/null +++ b/patches/server/Remove-invalid-mob-spawner-tile-entities.patch @@ -0,0 +1,34 @@ +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/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.TickList; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.EntityBlock; ++import net.minecraft.world.level.block.SpawnerBlock; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityTicker; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.TickingBlockEntity; ++import net.minecraft.world.level.block.entity.SpawnerBlockEntity; + import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.level.gameevent.EuclideanGameEventDispatcher; + import net.minecraft.world.level.gameevent.GameEventDispatcher; +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + } + + // CraftBukkit start ++ // Paper start - Remove invalid mob spawner tile entities ++ } else if (blockEntity instanceof SpawnerBlockEntity && !(getBlockState(blockposition).getBlock() instanceof SpawnerBlock)) { ++ this.removeBlockEntity(blockEntity.getBlockPos()); ++ // Paper end + } else { + System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ() + + " (" + this.getBlockState(blockposition) + ") where there was no entity tile!"); diff --git a/patches/server/Remove-some-streams-from-structures.patch b/patches/server/Remove-some-streams-from-structures.patch new file mode 100644 index 0000000000..d4a2892990 --- /dev/null +++ b/patches/server/Remove-some-streams-from-structures.patch @@ -0,0 +1,106 @@ +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/StructureFeatureManager.java b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/StructureFeatureManager.java ++++ b/src/main/java/net/minecraft/world/level/StructureFeatureManager.java +@@ -0,0 +0,0 @@ public class StructureFeatureManager { + }); + } + ++ // Paper start - remove structure streams - based on method above ++ public java.util.List> streamlessStartsForFeature(SectionPos sectionPosition, StructureFeature structureGenerator) { ++ java.util.List> list = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); ++ for (Long curLong : this.level.getChunk(sectionPosition.x(), sectionPosition.z(), ChunkStatus.STRUCTURE_REFERENCES).getReferencesForFeature(structureGenerator)) { ++ SectionPos sectionPosition1 = SectionPos.of(new ChunkPos(curLong), 0); ++ StructureStart structurestart = getStartForFeature(sectionPosition1, structureGenerator, this.level.getChunk(sectionPosition1.x(), sectionPosition1.z(), ChunkStatus.STRUCTURE_STARTS)); ++ if (structurestart != null && structurestart.isValid()) { ++ list.add(structurestart); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + @Nullable + public StructureStart getStartForFeature(SectionPos pos, StructureFeature feature, FeatureAccess holder) { + return holder.getStartForFeature(feature); +@@ -0,0 +0,0 @@ public class StructureFeatureManager { + } + + public StructureStart getStructureAt(BlockPos pos, boolean matchChildren, StructureFeature feature) { +- return (StructureStart) DataFixUtils.orElse(this.startsForFeature(SectionPos.of(pos), feature).filter((structurestart) -> { +- return matchChildren ? structurestart.getPieces().stream().anyMatch((structurepiece) -> { +- return structurepiece.getBoundingBox().isInside((Vec3i) pos); +- }) : structurestart.getBoundingBox().isInside((Vec3i) pos); +- }).findFirst(), StructureStart.INVALID_START); ++ // Paper start - remove structure streams ++ for (StructureStart structureStart : streamlessStartsForFeature(SectionPos.of(pos), feature)) { ++ if (matchChildren) { ++ for (net.minecraft.world.level.levelgen.structure.StructurePiece piece : structureStart.getPieces()) { ++ if (piece.getBoundingBox().isInside(pos)) { ++ return structureStart; ++ } ++ } ++ } else if (structureStart.getBoundingBox().isInside(pos)) { ++ return structureStart; ++ } ++ } ++ return StructureStart.INVALID_START; ++ // Paper end + } + + // Spigot start +diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/biome/Biome.java ++++ b/src/main/java/net/minecraft/world/level/biome/Biome.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + import net.minecraft.world.level.levelgen.feature.StructureFeature; + import net.minecraft.world.level.levelgen.structure.BoundingBox; ++import net.minecraft.world.level.levelgen.structure.StructureStart; + import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder; + import net.minecraft.world.level.levelgen.synth.PerlinSimplexNoise; + import net.minecraft.world.level.material.FluidState; +@@ -0,0 +0,0 @@ public final class Biome { + int p = region.getMinBuildHeight() + 1; + int q = region.getMaxBuildHeight() - 1; + region.setCurrentlyGenerating(supplier); +- structureAccessor.startsForFeature(SectionPos.of(origin), structureFeature).forEach((structureStart) -> { ++ // Paper start - remove structure streams ++ for (StructureStart structureStart : structureAccessor.streamlessStartsForFeature(SectionPos.of(origin), structureFeature)) { + structureStart.placeInChunk(region, structureAccessor, chunkGenerator, random, new BoundingBox(n, p, o, n + 15, q, o + 15), new ChunkPos(l, m)); +- }); ++ } ++ // Paper end + } catch (Exception var24) { + CrashReport crashReport = CrashReport.forThrowable(var24, "Feature placement"); + crashReport.addCategory("Feature").setDetail("Description", supplier::get); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/Beardifier.java +@@ -0,0 +0,0 @@ public class Beardifier { + this.rigids = new ObjectArrayList<>(10); + + for(StructureFeature structureFeature : StructureFeature.NOISE_AFFECTING_FEATURES) { +- accessor.startsForFeature(SectionPos.bottomOf(chunk), structureFeature).forEach((start) -> { ++ for (net.minecraft.world.level.levelgen.structure.StructureStart start : accessor.streamlessStartsForFeature(SectionPos.of(chunkPos, 0), structureFeature)) { // Paper - remove structure streams + for(StructurePiece structurePiece : start.getPieces()) { + if (structurePiece.isCloseToChunk(chunkPos, 12)) { + if (structurePiece instanceof PoolElementStructurePiece) { +@@ -0,0 +0,0 @@ public class Beardifier { + } + } + +- }); ++ } // Paper - remove structure streams + } + + this.pieceIterator = this.rigids.iterator(); diff --git a/patches/server/Remove-stale-POIs.patch b/patches/server/Remove-stale-POIs.patch new file mode 100644 index 0000000000..8d02b9a5f7 --- /dev/null +++ b/patches/server/Remove-stale-POIs.patch @@ -0,0 +1,22 @@ +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/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + }); + optional1.ifPresent((villageplacetype) -> { + this.getServer().execute(() -> { ++ // Paper start ++ if (!optional.isPresent() && this.getPoiManager().exists(blockposition1, com.google.common.base.Predicates.alwaysTrue())) { ++ this.getPoiManager().remove(blockposition1); ++ } ++ // Paper end + this.getPoiManager().add(blockposition1, villageplacetype); + DebugPackets.sendPoiAddedPacket(this, blockposition1); + }); diff --git a/patches/server/Remove-streams-from-Mob-AI-System.patch b/patches/server/Remove-streams-from-Mob-AI-System.patch new file mode 100644 index 0000000000..a0363bd310 --- /dev/null +++ b/patches/server/Remove-streams-from-Mob-AI-System.patch @@ -0,0 +1,224 @@ +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/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java +@@ -0,0 +0,0 @@ package net.minecraft.world.entity.ai.goal; + import java.util.EnumSet; + + public abstract class Goal { +- private final EnumSet flags = EnumSet.noneOf(Goal.Flag.class); ++ private final EnumSet flags = EnumSet.noneOf(Goal.Flag.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 com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + + public abstract boolean canUse(); + +@@ -0,0 +0,0 @@ public abstract class Goal { + } + + public void setFlags(EnumSet controls) { +- this.flags.clear(); +- this.flags.addAll(controls); ++ // Paper start - remove streams from pathfindergoalselector ++ this.goalTypes.clear(); ++ this.goalTypes.addAllUnchecked(controls); ++ // Paper end - remove streams from pathfindergoalselector + } + + @Override +@@ -0,0 +0,0 @@ public abstract class Goal { + return this.getClass().getSimpleName(); + } + +- public EnumSet getFlags() { +- return this.flags; ++ // 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 Flag { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -0,0 +0,0 @@ public class GoalSelector { + private final Map lockedFlags = new EnumMap<>(Goal.Flag.class); + public final Set availableGoals = Sets.newLinkedHashSet(); + private final Supplier profiler; +- private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); ++ private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.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 com.destroystokyo.paper.util.set.OptimizedSmallEnumSet goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector + private int tickCount; + private int newGoalRate = 3; + private int curRate; ++ private static final Goal.Flag[] PATHFINDER_GOAL_TYPES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector + + public GoalSelector(Supplier profiler) { + this.profiler = profiler; +@@ -0,0 +0,0 @@ public class GoalSelector { + } + // Paper end + public void removeGoal(Goal goal) { +- this.availableGoals.stream().filter((wrappedGoal) -> { +- return wrappedGoal.getGoal() == goal; +- }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop); +- this.availableGoals.removeIf((wrappedGoal) -> { +- return wrappedGoal.getGoal() == goal; +- }); ++ // Paper start - remove streams from pathfindergoalselector ++ for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal goalWrapped = iterator.next(); ++ if (goalWrapped.getGoal() != goal) { ++ continue; ++ } ++ if (goalWrapped.isRunning()) { ++ goalWrapped.stop(); ++ } ++ iterator.remove(); ++ } ++ // Paper end - remove streams from pathfindergoalselector + } + + public void tick() { + ProfilerFiller profilerFiller = this.profiler.get(); + profilerFiller.push("goalCleanup"); +- this.getRunningGoals().filter((wrappedGoal) -> { +- return !wrappedGoal.isRunning() || wrappedGoal.getFlags().stream().anyMatch(this.disabledFlags::contains) || !wrappedGoal.canContinueToUse(); +- }).forEach(Goal::stop); +- this.lockedFlags.forEach((flag, wrappedGoal) -> { ++ // Paper start - remove streams from pathfindergoalselector ++ for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); + if (!wrappedGoal.isRunning()) { +- this.lockedFlags.remove(flag); ++ continue; ++ } ++ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.canContinueToUse()) { ++ continue; ++ } ++ wrappedGoal.stop(); ++ } ++ // Paper end - remove streams from pathfindergoalselector ++ this.lockedFlags.forEach((pathfindergoal_type, pathfindergoalwrapped) -> { ++ if (!pathfindergoalwrapped.isRunning()) { ++ this.lockedFlags.remove(pathfindergoal_type); + } + + }); + profilerFiller.pop(); + profilerFiller.push("goalUpdate"); +- this.availableGoals.stream().filter((wrappedGoal) -> { +- return !wrappedGoal.isRunning(); +- }).filter((wrappedGoal) -> { +- return wrappedGoal.getFlags().stream().noneMatch(this.disabledFlags::contains); +- }).filter((wrappedGoal) -> { +- return wrappedGoal.getFlags().stream().allMatch((flag) -> { +- return this.lockedFlags.getOrDefault(flag, NO_GOAL).canBeReplacedBy(wrappedGoal); +- }); +- }).filter(WrappedGoal::canUse).forEach((wrappedGoal) -> { +- wrappedGoal.getFlags().forEach((flag) -> { +- WrappedGoal wrappedGoal2 = this.lockedFlags.getOrDefault(flag, NO_GOAL); +- wrappedGoal2.stop(); +- this.lockedFlags.put(flag, wrappedGoal); +- }); ++ ++ // Paper start - remove streams from pathfindergoalselector ++ goal_update_loop: for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (wrappedGoal.isRunning()) { ++ continue; ++ } ++ ++ com.destroystokyo.paper.util.set.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) { ++ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); ++ if (!wrapped.canBeReplacedBy(wrappedGoal)) { ++ continue goal_update_loop; ++ } ++ } ++ ++ if (!wrappedGoal.canUse()) { ++ continue; ++ } ++ ++ iterator1 = wrappedGoalSet.getBackingSet(); ++ wrappedGoalSize = wrappedGoalSet.size(); ++ for (int i = 0; i < wrappedGoalSize; ++i) { ++ Goal.Flag type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)]; ++ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1); ++ WrappedGoal wrapped = this.lockedFlags.getOrDefault(type, GoalSelector.NO_GOAL); ++ ++ wrapped.stop(); ++ this.lockedFlags.put(type, wrappedGoal); ++ } + wrappedGoal.start(); +- }); ++ } ++ // Paper end - remove streams from pathfindergoalselector + profilerFiller.pop(); + profilerFiller.push("goalTick"); +- this.getRunningGoals().forEach(WrappedGoal::tick); ++ // Paper start - remove streams from pathfindergoalselector ++ for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { ++ WrappedGoal wrappedGoal = iterator.next(); ++ if (wrappedGoal.isRunning()) { ++ wrappedGoal.tick(); ++ } ++ } ++ // Paper end - remove streams from pathfindergoalselector + profilerFiller.pop(); + } + +@@ -0,0 +0,0 @@ public class GoalSelector { + } + + public void disableControlFlag(Goal.Flag control) { +- this.disabledFlags.add(control); ++ this.goalTypes.addUnchecked(control); // Paper - remove streams from pathfindergoalselector + } + + public void enableControlFlag(Goal.Flag control) { +- this.disabledFlags.remove(control); ++ this.goalTypes.removeUnchecked(control); // Paper - remove streams from pathfindergoalselector + } + + public void setControlFlag(Goal.Flag control, boolean enabled) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java +@@ -0,0 +0,0 @@ public class WrappedGoal extends Goal { + this.goal.setFlags(controls); + } + +- @Override +- public EnumSet getFlags() { +- return this.goal.getFlags(); ++ // Paper start - remove streams from pathfindergoalselector ++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet getGoalTypes() { ++ return this.goal.getGoalTypes(); ++ // Paper end - remove streams from pathfindergoalselector + } + + public boolean isRunning() { diff --git a/patches/server/Remove-streams-from-PairedQueue.patch b/patches/server/Remove-streams-from-PairedQueue.patch new file mode 100644 index 0000000000..254a7e495b --- /dev/null +++ b/patches/server/Remove-streams-from-PairedQueue.patch @@ -0,0 +1,46 @@ +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/StrictQueue.java b/src/main/java/net/minecraft/util/thread/StrictQueue.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/util/thread/StrictQueue.java ++++ b/src/main/java/net/minecraft/util/thread/StrictQueue.java +@@ -0,0 +0,0 @@ public interface StrictQueue { + private final List> queueList; + + public FixedPriorityQueue(int priorityCount) { +- this.queueList = IntStream.range(0, priorityCount).mapToObj((i) -> { +- return Queues.newConcurrentLinkedQueue(); +- }).collect(Collectors.toList()); ++ // Paper start - remove streams ++ this.queueList = new java.util.ArrayList<>(priorityCount); // queues ++ for (int j = 0; j < priorityCount; ++j) { ++ this.queueList.add(Queues.newConcurrentLinkedQueue()); ++ } ++ // Paper end - remove streams + } + + @Nullable +@@ -0,0 +0,0 @@ public interface StrictQueue { + + @Override + public boolean isEmpty() { +- return this.queueList.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.queueList.size(); i < len; ++i) { ++ Queue queue = this.queueList.get(i); ++ if (!queue.isEmpty()) { ++ return false; ++ } ++ } ++ return true; ++ // Paper end - remove streams + } + + @Override diff --git a/patches/server/Remove-streams-from-SensorNearest.patch b/patches/server/Remove-streams-from-SensorNearest.patch new file mode 100644 index 0000000000..cda6bfea63 --- /dev/null +++ b/patches/server/Remove-streams-from-SensorNearest.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll +Date: Wed, 3 Mar 2021 12:48:48 +0100 +Subject: [PATCH] Remove streams from SensorNearest + +The behavioural nearby sensors are validated every tick on the entities +that registered the respective sensors and are therefore a good subject +to performance improvements. + +More specifically this commit replaces the Stream#filter usage with +ArrayList#removeIf as the removeIf method on an array list is heavily +optimized towards a single internal array re-allocation without any +further overhead on the removeIf call. + +The only negative of this change is the rather agressive diff these +patches introduce as the methods are basically being reimplemented +compared to the previous stream-based implementation. + +See: https://nipafx.dev/java-stream-performance/ + +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +@@ -0,0 +0,0 @@ public class NearestItemSensor extends Sensor { + return true; + }); + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); +- Optional optional = list.stream().filter((itemEntity) -> { +- return entity.wantsToPickUp(itemEntity.getItem()); +- }).filter((itemEntity) -> { +- return itemEntity.closerThan(entity, 9.0D); +- }).filter(entity::hasLineOfSight).findFirst(); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional); ++ // Paper start - remove streams in favour of lists ++ ItemEntity nearest = null; ++ for (ItemEntity entityItem : list) { ++ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 9.0D) && entity.hasLineOfSight(entityItem)) { ++ nearest = entityItem; ++ break; ++ } ++ } ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest)); ++ // Paper end + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +@@ -0,0 +0,0 @@ public class NearestLivingEntitySensor extends Sensor { + list.sort(Comparator.comparingDouble(entity::distanceToSqr)); + Brain brain = entity.getBrain(); + brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, list); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, list.stream().filter((livingEntity2) -> { +- return isEntityTargetable(entity, livingEntity2); +- }).collect(Collectors.toList())); ++ // Paper start - remove streams in favour of lists ++ List visibleMobs = new java.util.ArrayList<>(list); ++ visibleMobs.removeIf(otherEntityLiving -> !Sensor.isEntityTargetable(entity, otherEntityLiving)); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, visibleMobs); ++ // Paper end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +@@ -0,0 +0,0 @@ public class PlayerSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- List list = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((serverPlayer) -> { +- return entity.closerThan(serverPlayer, 16.0D); +- }).sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList()); ++ // Paper start - remove streams in favour of lists ++ List players = new java.util.ArrayList<>(world.players()); ++ players.removeIf(player -> !EntitySelector.NO_SPECTATORS.test(player) || !entity.closerThan(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator + Brain brain = entity.getBrain(); +- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list); +- List list2 = list.stream().filter((player) -> { +- return isEntityTargetable(entity, player); +- }).collect(Collectors.toList()); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0)); +- Optional optional = list2.stream().filter((player) -> { +- return isEntityAttackable(entity, player); +- }).findFirst(); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional); ++ ++ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); ++ ++ Player nearest = null, nearestTargetable = null; ++ for (Player player : players) { ++ if (Sensor.isEntityTargetable(entity, player)) { ++ if (nearest == null) nearest = player; ++ if (Sensor.isEntityAttackable(entity, player)) { ++ nearestTargetable = player; ++ break; // Both variables are assigned, no reason to loop further ++ } ++ } ++ } ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, nearestTargetable); ++ // Paper end + } + } diff --git a/patches/server/Remove-streams-from-classes-related-villager-gossip.patch b/patches/server/Remove-streams-from-classes-related-villager-gossip.patch new file mode 100644 index 0000000000..34dd4b2c8c --- /dev/null +++ b/patches/server/Remove-streams-from-classes-related-villager-gossip.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Josh Roy <10731363+JRoy@users.noreply.github.com> +Date: Wed, 1 Jul 2020 18:01:49 -0400 +Subject: [PATCH] Remove streams from classes related villager gossip + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java ++++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +@@ -0,0 +0,0 @@ import com.mojang.serialization.Dynamic; + import com.mojang.serialization.DynamicOps; + import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ObjectArrayList; // Paper + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import java.util.Arrays; +@@ -0,0 +0,0 @@ public class GossipContainer { + }); + } + ++ // Paper start - Remove streams from reputation ++ private List decompress() { ++ List list = new ObjectArrayList<>(); ++ for (Map.Entry entry : getReputations().entrySet()) { ++ for (GossipContainer.GossipEntry cur : entry.getValue().decompress(entry.getKey())) { ++ if (cur.weightedValue() != 0) ++ list.add(cur); ++ } ++ } ++ return list; ++ } ++ // Paper end ++ + private Collection selectGossipsForTransfer(Random random, int count) { +- List list = this.unpack().collect(Collectors.toList()); ++ List list = decompress(); // Paper - Remove streams from reputation + if (list.isEmpty()) { + return Collections.emptyList(); + } else { +@@ -0,0 +0,0 @@ public class GossipContainer { + + } + +- public Dynamic store(DynamicOps dynamicOps) { +- return new Dynamic<>(dynamicOps, dynamicOps.createList(this.unpack().map((gossipEntry) -> { +- return gossipEntry.store(dynamicOps); ++ public Dynamic store(DynamicOps dynamicops) { ++ return new Dynamic(dynamicops, dynamicops.createList(this.decompress().stream().map((reputation_b) -> { ++ return reputation_b.store(dynamicops); + }).map(Dynamic::getValue))); + } + +@@ -0,0 +0,0 @@ public class GossipContainer { + final Object2IntMap entries = new Object2IntOpenHashMap<>(); + + public int weightedValue(Predicate gossipTypeFilter) { +- return this.entries.object2IntEntrySet().stream().filter((entry) -> { +- return gossipTypeFilter.test(entry.getKey()); +- }).mapToInt((entry) -> { +- return entry.getIntValue() * (entry.getKey()).weight; +- }).sum(); ++ // Paper start - Remove streams from reputation ++ int weight = 0; ++ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { ++ if (gossipTypeFilter.test(entry.getKey())) { ++ weight += entry.getIntValue() * entry.getKey().weight; ++ } ++ } ++ return weight; ++ } ++ ++ public List decompress(UUID uuid) { ++ List list = new ObjectArrayList<>(); ++ for (Object2IntMap.Entry entry : entries.object2IntEntrySet()) { ++ list.add(new GossipContainer.GossipEntry(uuid, entry.getKey(), entry.getIntValue())); ++ } ++ return list; ++ // Paper - end + } + + public Stream unpack(UUID target) { diff --git a/patches/server/Reset-Ender-Crystals-on-Dragon-Spawn.patch b/patches/server/Reset-Ender-Crystals-on-Dragon-Spawn.patch new file mode 100644 index 0000000000..6cabd7e49a --- /dev/null +++ b/patches/server/Reset-Ender-Crystals-on-Dragon-Spawn.patch @@ -0,0 +1,24 @@ +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/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -0,0 +0,0 @@ public class EndDragonFight { + enderDragon.moveTo(0.0D, 128.0D, 0.0D, this.level.random.nextFloat() * 360.0F, 0.0F); + this.level.addFreshEntity(enderDragon); + this.dragonUUID = enderDragon.getUUID(); ++ this.resetSpikeCrystals(); // Paper + return enderDragon; + } + diff --git a/patches/server/Reset-players-airTicks-on-respawn.patch b/patches/server/Reset-players-airTicks-on-respawn.patch new file mode 100644 index 0000000000..b740452629 --- /dev/null +++ b/patches/server/Reset-players-airTicks-on-respawn.patch @@ -0,0 +1,18 @@ +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/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } + + this.setHealth(this.getMaxHealth()); ++ this.setAirSupply(this.getMaxAirSupply()); // Paper + this.remainingFireTicks = 0; + this.fallDistance = 0; + this.foodData = new FoodData(this); diff --git a/Spigot-Server-Patches/Reset-shield-blocking-on-dimension-change.patch b/patches/server/Reset-shield-blocking-on-dimension-change.patch similarity index 51% rename from Spigot-Server-Patches/Reset-shield-blocking-on-dimension-change.patch rename to patches/server/Reset-shield-blocking-on-dimension-change.patch index 8ef85b78e3..8b932d8808 100644 --- a/Spigot-Server-Patches/Reset-shield-blocking-on-dimension-change.patch +++ b/patches/server/Reset-shield-blocking-on-dimension-change.patch @@ -4,17 +4,17 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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); +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.level.getCraftServer().getPluginManager().callEvent(changeEvent); // CraftBukkit end } + // Paper start + if (this.isBlocking()) { -+ this.clearActiveItem(); ++ this.stopUsingItem(); + } + // Paper end diff --git a/patches/server/Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server/Reset-spawner-timer-when-spawner-event-is-cancelled.patch new file mode 100644 index 0000000000..5d29bf93c3 --- /dev/null +++ b/patches/server/Reset-spawner-timer-when-spawner-event-is-cancelled.patch @@ -0,0 +1,27 @@ +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/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java ++++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + // Spigot End + } + entity.spawnedViaMobSpawner = true; // Paper ++ flag = true; // Paper + // Spigot Start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { + Entity vehicle = entity.getVehicle(); +@@ -0,0 +0,0 @@ public abstract class BaseSpawner { + ((Mob) entity).spawnAnim(); + } + +- flag = true; ++ //flag = true; // Paper - moved up above cancellable event + } + } + diff --git a/patches/server/Reset-villager-inventory-on-cancelled-pickup-event.patch b/patches/server/Reset-villager-inventory-on-cancelled-pickup-event.patch new file mode 100644 index 0000000000..854c248e2e --- /dev/null +++ b/patches/server/Reset-villager-inventory-on-cancelled-pickup-event.patch @@ -0,0 +1,54 @@ +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/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/SimpleContainer.java ++++ b/src/main/java/net/minecraft/world/SimpleContainer.java +@@ -0,0 +0,0 @@ public class SimpleContainer implements Container, StackedContentsCompatible { + 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.setChanged(); ++ } ++ // Paper end ++ + public void onOpen(CraftHumanEntity who) { + this.transaction.add(who); + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + } + + // CraftBukkit start +- ItemStack remaining = new SimpleContainer(inventorysubcontainer).addItem(itemstack); +- if (CraftEventFactory.callEntityPickupItemEvent(this, item, remaining.getCount(), false).isCancelled()) { ++ // Paper start ++ List contentsSnapshot = new java.util.ArrayList<>(inventorysubcontainer.getContents()); ++ ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ if (CraftEventFactory.callEntityPickupItemEvent(this, item, itemstack1.getCount(), false).isCancelled()) { ++ inventorysubcontainer.setContents(contentsSnapshot); ++ // Paper end + return; + } + // CraftBukkit end + + this.onItemPickup(item); + this.take(item, itemstack.getCount()); +- ItemStack itemstack1 = inventorysubcontainer.addItem(itemstack); ++ // ItemStack itemstack1 = inventorysubcontainer.a(itemstack); // Paper - moved up + + if (itemstack1.isEmpty()) { + item.discard(); diff --git a/Spigot-Server-Patches/Restore-custom-InventoryHolder-support.patch b/patches/server/Restore-custom-InventoryHolder-support.patch similarity index 89% rename from Spigot-Server-Patches/Restore-custom-InventoryHolder-support.patch rename to patches/server/Restore-custom-InventoryHolder-support.patch index d5c9bd78b9..abeb3eb978 100644 --- a/Spigot-Server-Patches/Restore-custom-InventoryHolder-support.patch +++ b/patches/server/Restore-custom-InventoryHolder-support.patch @@ -26,10 +26,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public Inventory createInventory(InventoryHolder holder, InventoryType type) { + // Paper start + if (holder != null) { -+ return DEFAULT_CONVERTER.createInventory(holder, type); ++ return this.DEFAULT_CONVERTER.createInventory(holder, type); + } + //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type); + return this.converterMap.get(type).createInventory(holder, type); } @@ -0,0 +0,0 @@ public final class CraftInventoryCreator { @@ -41,6 +41,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return DEFAULT_CONVERTER.createInventory(holder, type, title); + } + //noinspection ConstantConditions // Paper end - return converterMap.get(type).createInventory(holder, type, title); + return this.converterMap.get(type).createInventory(holder, type, title); } diff --git a/Spigot-Server-Patches/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch b/patches/server/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch similarity index 83% rename from Spigot-Server-Patches/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch rename to patches/server/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch index d207708d6b..749d0e558f 100644 --- a/Spigot-Server-Patches/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch +++ b/patches/server/Restore-vanlla-default-mob-spawn-range-and-water-ani.patch @@ -13,9 +13,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 ); +- this.mobSpawnRange = (byte) this.getInt( "mob-spawn-range", 6 ); ++ this.mobSpawnRange = (byte) getInt( "mob-spawn-range", 8 ); // Paper - Vanilla + this.log( "Mob Spawn Range: " + this.mobSpawnRange ); } diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml diff --git a/patches/server/Restrict-vanilla-teleport-command-to-valid-locations.patch b/patches/server/Restrict-vanilla-teleport-command-to-valid-locations.patch new file mode 100644 index 0000000000..f59a3681f9 --- /dev/null +++ b/patches/server/Restrict-vanilla-teleport-command-to-valid-locations.patch @@ -0,0 +1,24 @@ +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/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java ++++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java +@@ -0,0 +0,0 @@ public class TeleportCommand { + + private static void performTeleport(CommandSourceStack source, Entity target, ServerLevel world, double x, double y, double z, Set movementFlags, float yaw, float pitch, @Nullable TeleportCommand.LookAt facingLocation) throws CommandSyntaxException { + BlockPos blockposition = new BlockPos(x, y, z); ++ // Paper start - Don't allow teleport command to invalid locations ++ if (x <= -30000000 || z <= -30000000 || x > 30000000 || z > 30000000 || y > 30000000 || y <= -30000000) { // Copy/pasta from BaseBlockPosition#isValidLocation ++ org.bukkit.Bukkit.getLogger().warning("Refused to teleport " + target.getScoreboardName() + " to " + x + ", " + y + ", " + z); ++ return; ++ } ++ // Paper end + + if (!Level.isInSpawnableBounds(blockposition)) { + throw TeleportCommand.INVALID_POSITION.create(); diff --git a/Spigot-Server-Patches/Retain-block-place-order-when-capturing-blockstates.patch b/patches/server/Retain-block-place-order-when-capturing-blockstates.patch similarity index 51% rename from Spigot-Server-Patches/Retain-block-place-order-when-capturing-blockstates.patch rename to patches/server/Retain-block-place-order-when-capturing-blockstates.patch index 6f630fcbf8..6f01622f48 100644 --- a/Spigot-Server-Patches/Retain-block-place-order-when-capturing-blockstates.patch +++ b/patches/server/Retain-block-place-order-when-capturing-blockstates.patch @@ -9,16 +9,16 @@ 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 +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.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 { +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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 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/patches/server/Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/server/Return-chat-component-with-empty-text-instead-of-thr.patch new file mode 100644 index 0000000000..8481f0dbc9 --- /dev/null +++ b/patches/server/Return-chat-component-with-empty-text-instead-of-thr.patch @@ -0,0 +1,33 @@ +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/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -0,0 +0,0 @@ import net.minecraft.ReportedException; + import net.minecraft.core.NonNullList; + import net.minecraft.core.Registry; + import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.util.Mth; +@@ -0,0 +0,0 @@ public abstract class AbstractContainerMenu { + } + private Component title; + public final Component 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 TextComponent(""); ++ } ++ // Paper end + return this.title; + } + public final void setTitle(Component title) { diff --git a/Spigot-Server-Patches/Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server/Sanitise-RegionFileCache-and-make-configurable.patch similarity index 78% rename from Spigot-Server-Patches/Sanitise-RegionFileCache-and-make-configurable.patch rename to patches/server/Sanitise-RegionFileCache-and-make-configurable.patch index 1b718e4453..496eaabaa7 100644 --- a/Spigot-Server-Patches/Sanitise-RegionFileCache-and-make-configurable.patch +++ b/patches/server/Sanitise-RegionFileCache-and-make-configurable.patch @@ -24,16 +24,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.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 { +--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +@@ -0,0 +0,0 @@ public class RegionFileStorage 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(); +- if (this.regionCache.size() >= 256) { ++ if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable + ((RegionFile) this.regionCache.removeLast()).close(); } diff --git a/patches/server/Seed-based-feature-search.patch b/patches/server/Seed-based-feature-search.patch new file mode 100644 index 0000000000..9217e92cc9 --- /dev/null +++ b/patches/server/Seed-based-feature-search.patch @@ -0,0 +1,71 @@ +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 = true; ++ 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/levelgen/feature/StructureFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/StructureFeature.java +@@ -0,0 +0,0 @@ public abstract class StructureFeature { + if (!world.getWorldBorder().isChunkInBounds(chunkPos.x, chunkPos.z)) { continue; } // Paper + boolean bl3 = world.getBiomeManager().getPrimaryBiomeAtChunk(chunkPos).getGenerationSettings().isValidStart(this); + if (bl3) { +- ChunkAccess chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); ++ // Paper start - seed based feature search ++ ChunkAccess chunkAccess = null; ++ if (structureAccessor.getWorld().paperConfig.seedBasedFeatureSearch) { ++ Biome biomeBase = structureAccessor.getWorld().getBiomeManager().getBiome(new BlockPos(chunkPos.getMinBlockX() + 9, 0, chunkPos.getMinBlockZ() + 9)); ++ if (!biomeBase.getGenerationSettings().isValidStart(this)) { ++ continue; ++ } ++ if (!structureAccessor.getWorld().paperConfig.seedBasedFeatureSearchLoadsChunks) { ++ chunkAccess = structureAccessor.getWorld().getChunkIfLoaded(chunkPos.x, chunkPos.z); ++ if (chunkAccess == null) { ++ return chunkPos.getWorldPosition().offset(8, searchStartPos.getY(), 8); ++ } ++ } ++ } ++ if (chunkAccess == null) { ++ chunkAccess = world.getChunk(chunkPos.x, chunkPos.z, ChunkStatus.STRUCTURE_STARTS); ++ } ++ // Paper end + StructureStart structureStart = structureAccessor.getStartForFeature(SectionPos.bottomOf(chunkAccess), this, chunkAccess); + if (structureStart != null && structureStart.isValid()) { + if (skipExistingChunks && structureStart.canBeReferenced()) { diff --git a/patches/server/Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server/Send-attack-SoundEffects-only-to-players-who-can-see.patch new file mode 100644 index 0000000000..6a52128726 --- /dev/null +++ b/patches/server/Send-attack-SoundEffects-only-to-players-who-can-see.patch @@ -0,0 +1,80 @@ +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/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ import net.minecraft.network.chat.MutableComponent; + import net.minecraft.network.chat.TextComponent; + import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; ++import net.minecraft.network.protocol.game.ClientboundSoundPacket; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + int i = b0 + EnchantmentHelper.getKnockbackBonus((LivingEntity) this); + + if (this.isSprinting() && flag) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + ++i; + flag1 = true; + } +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + } + } + +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.sweepAttack(); + } + +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + } + + if (flag2) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + this.crit(target); + } + + if (!flag2 && !flag3) { + if (flag) { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + } else { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + } + } + +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + + this.applyExhaustion(level.spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value + } else { +- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); ++ sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility + if (flag4) { + target.clearFire(); + } +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { + public int getXpNeededForNextLevel() { + return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); + } ++ // Paper start - send SoundEffect to everyone who can see fromEntity ++ private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) { ++ fromEntity.level.playSound(fromEntity, x, y, z, soundEffect, soundCategory, volume, pitch); // This will not send the effect to the entity himself ++ if (fromEntity instanceof ServerPlayer) { ++ ((ServerPlayer) fromEntity).connection.send(new ClientboundSoundPacket(soundEffect, soundCategory, x, y, z, volume, pitch)); ++ } ++ } ++ // Paper end + + // CraftBukkit start + public void causeFoodExhaustion(float exhaustion) { diff --git a/Spigot-Server-Patches/Send-empty-commands-if-tab-completion-is-disabled.patch b/patches/server/Send-empty-commands-if-tab-completion-is-disabled.patch similarity index 61% rename from Spigot-Server-Patches/Send-empty-commands-if-tab-completion-is-disabled.patch rename to patches/server/Send-empty-commands-if-tab-completion-is-disabled.patch index 8360f60660..de657bb183 100644 --- a/Spigot-Server-Patches/Send-empty-commands-if-tab-completion-is-disabled.patch +++ b/patches/server/Send-empty-commands-if-tab-completion-is-disabled.patch @@ -4,18 +4,18 @@ 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 +diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.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 { +--- a/src/main/java/net/minecraft/commands/Commands.java ++++ b/src/main/java/net/minecraft/commands/Commands.java +@@ -0,0 +0,0 @@ public class Commands { } - public void a(EntityPlayer entityplayer) { + public void sendCommands(ServerPlayer player) { - 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<>())); ++ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>())); + return; + } + // Paper end diff --git a/Spigot-Server-Patches/Server-Tick-Events.patch b/patches/server/Server-Tick-Events.patch similarity index 66% rename from Spigot-Server-Patches/Server-Tick-Events.patch rename to patches/server/Server-Tick-Events.patch index 52c96c6ddd..0eec3b56bb 100644 --- a/Spigot-Server-Patches/Server-Tick-Events.patch +++ b/patches/server/Server-Tick-Events.patch @@ -9,24 +9,24 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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= 600) { - this.startDrownedConversion(300); +--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java +@@ -0,0 +0,0 @@ public class Zombie extends Monster { + ++this.inWaterTime; + if (this.inWaterTime >= 600) { + this.startUnderWaterConversion(300); + this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 } } else { - this.bt = -1; + this.inWaterTime = -1; diff --git a/Spigot-Server-Patches/Set-area-affect-cloud-rotation.patch b/patches/server/Set-area-affect-cloud-rotation.patch similarity index 61% rename from Spigot-Server-Patches/Set-area-affect-cloud-rotation.patch rename to patches/server/Set-area-affect-cloud-rotation.patch index 717dcc3a49..b3da40d3d8 100644 --- a/Spigot-Server-Patches/Set-area-affect-cloud-rotation.patch +++ b/patches/server/Set-area-affect-cloud-rotation.patch @@ -9,10 +9,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(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 + entity = new net.minecraft.world.entity.AreaEffectCloud(this.world, x, y, z); ++ entity.moveTo(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); - } + entity = new net.minecraft.world.entity.projectile.EvokerFangs(this.world, x, y, z, (float) Math.toRadians(yaw), 0, null); + } else if (Marker.class.isAssignableFrom(clazz)) { diff --git a/Spigot-Server-Patches/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch b/patches/server/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch similarity index 95% rename from Spigot-Server-Patches/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch rename to patches/server/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch index 86f387b8e6..bf75bba818 100644 --- a/Spigot-Server-Patches/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch +++ b/patches/server/Set-cap-on-JDK-per-thread-native-byte-buffer-cache.patch @@ -27,4 +27,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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"); + acceptsAll(Main.asList("?", "help"), "Show the help"); diff --git a/Spigot-Server-Patches/Set-spigots-verbose-world-setting-to-false-by-def.patch b/patches/server/Set-spigots-verbose-world-setting-to-false-by-def.patch similarity index 76% rename from Spigot-Server-Patches/Set-spigots-verbose-world-setting-to-false-by-def.patch rename to patches/server/Set-spigots-verbose-world-setting-to-false-by-def.patch index ebcfd3f143..d83717b07f 100644 --- a/Spigot-Server-Patches/Set-spigots-verbose-world-setting-to-false-by-def.patch +++ b/patches/server/Set-spigots-verbose-world-setting-to-false-by-def.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void init() { -- this.verbose = getBoolean( "verbose", true ); -+ this.verbose = getBoolean( "verbose", false ); // Paper +- this.verbose = this.getBoolean( "verbose", true ); ++ this.verbose = this.getBoolean( "verbose", false ); // Paper - log( "-------- World Settings For [" + worldName + "] --------" ); + this.log( "-------- World Settings For [" + this.worldName + "] --------" ); SpigotConfig.readConfig( SpigotWorldConfig.class, this ); diff --git a/patches/server/Setup-Gradle-project.patch b/patches/server/Setup-Gradle-project.patch new file mode 100644 index 0000000000..385a1e3c45 --- /dev/null +++ b/patches/server/Setup-Gradle-project.patch @@ -0,0 +1,638 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kyle Wood +Date: Thu, 10 Dec 2020 20:54:19 -0800 +Subject: [PATCH] Setup Gradle project + +The pom.xml file is deleted in this patch so the patch will fail to +apply if there are changes made to it from upstream - thus notifying us +that changes were made. + +diff --git a/.gitignore b/.gitignore +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -0,0 +0,0 @@ ++.gradle/ ++build/ ++ + # Eclipse stuff + /.classpath + /.project +diff --git a/build.gradle.kts b/build.gradle.kts +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ ++import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer ++import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer ++import io.papermc.paperweight.util.Git ++import io.papermc.paperweight.util.path ++import shadow.org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE ++import java.text.SimpleDateFormat ++import java.util.Date ++import java.util.Locale ++ ++plugins { ++ java ++ `maven-publish` ++ id("com.github.johnrengelman.shadow") ++} ++ ++repositories { ++ maven("https://libraries.minecraft.net/") ++} ++ ++dependencies { ++ implementation(project(":Paper-API")) ++ implementation("jline:jline:2.12.1") ++ implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") { ++ exclude(group = "org.apache.logging.log4j", module = "log4j-api") ++ } ++ implementation("org.ow2.asm:asm:9.1") ++ implementation("com.googlecode.json-simple:json-simple:1.1.1") { ++ // This includes junit transitively for whatever reason ++ isTransitive = false ++ } ++ runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") ++ runtimeOnly("mysql:mysql-connector-java:5.1.49") ++ ++ runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") ++ runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") ++ runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.0") ++ ++ testImplementation("junit:junit:4.13.1") ++ testImplementation("org.hamcrest:hamcrest-library:1.3") ++} ++ ++tasks.jar { ++ archiveClassifier.set("dev") ++ ++ manifest { ++ val git = Git(rootProject.layout.projectDirectory.path) ++ val gitHash = git("rev-parse", "HEAD").getText().substring(0, 7) ++ attributes( ++ "Main-Class" to "org.bukkit.craftbukkit.Main", ++ "Implementation-Title" to "CraftBukkit", ++ "Implementation-Version" to "git-Paper-\"$gitHash\"", ++ "Implementation-Vendor" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(Date()), // Paper ++ "Specification-Title" to "Bukkit", ++ "Specification-Version" to project.version, ++ "Specification-Vendor" to "Bukkit Team", ++ ) ++ for (tld in setOf("net", "com", "org")) { ++ attributes("$tld/bukkit", "Sealed" to true) ++ } ++ } ++} ++ ++publishing { ++ publications.create("maven") { ++ artifactId = rootProject.name.toLowerCase(Locale.ENGLISH) ++ artifact(tasks.reobfJar) { ++ classifier = null ++ } ++ artifact(tasks.shadowJar) ++ } ++} ++ ++tasks.shadowJar { ++ archiveClassifier.set("mojang-mapped") ++ ++ val packageVersion = "1_17_R1" ++ relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.v$packageVersion") { ++ exclude("org.bukkit.craftbukkit.Main*") ++ } ++ listOf( ++ "jline", "it.unimi", "org.apache.commons.codec", "org.apache.commons.io", ++ "org.apache.commons.lang3", "org.apache.http", "org.apache.maven", "org.codehaus.plexus", ++ "org.eclipse.aether", "org.eclipse.sisu", "org.objectweb.asm" ++ ).forEach { pack -> ++ relocate(pack, "org.bukkit.craftbukkit.libs.$pack") ++ } ++ mergeServiceFiles() ++ transform(ModifiedLog4j2PluginsCacheFileTransformer::class.java) ++} ++ ++tasks.test { ++ exclude("org/bukkit/craftbukkit/inventory/ItemStack*Test.class") ++} ++ ++fun TaskContainer.registerRunTask( ++ name: String, block: JavaExec.() -> Unit ++): TaskProvider = register(name) { ++ group = "paper" ++ standardInput = System.`in` ++ workingDir = rootProject.layout.projectDirectory.dir( ++ providers.gradleProperty("runWorkDir").forUseAtConfigurationTime().orElse("run") ++ ).get().asFile ++ args("--nogui") ++ systemProperty("net.kyori.adventure.text.warnWhenLegacyFormattingDetected", true) ++ if (project.hasProperty("disableWatchdog")) { ++ systemProperty("disable.watchdog", true) ++ } ++ doFirst { ++ workingDir.mkdirs() ++ } ++ block(this) ++} ++ ++tasks.registerRunTask("runShadow") { ++ description = "Spin up a test server from the shadowJar archiveFile" ++ classpath(tasks.shadowJar.flatMap { it.archiveFile }) ++} ++ ++tasks.registerRunTask("runReobf") { ++ description = "Spin up a test server from the reobfJar output jar" ++ classpath(tasks.reobfJar.flatMap { it.outputJar }) ++} ++ ++tasks.registerRunTask("runDev") { ++ description = "Spin up a non-shaded non-remapped test server" ++ classpath = java.sourceSets.main.get().runtimeClasspath ++ mainClass.set("org.bukkit.craftbukkit.Main") ++} ++ ++class ModifiedLog4j2PluginsCacheFileTransformer : Transformer by Log4j2PluginsCacheFileTransformer() { ++ override fun canTransformResource(element: FileTreeElement): Boolean { ++ return PLUGIN_CACHE_FILE == element.name || element.name == "Log4j2Plugins.dat" ++ } ++} +diff --git a/pom.xml b/pom.xml +deleted file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- a/pom.xml ++++ /dev/null +@@ -0,0 +0,0 @@ +- +- 4.0.0 +- org.spigotmc +- spigot +- jar +- 1.17-R0.1-SNAPSHOT +- Spigot +- https://www.spigotmc.org/ +- +- +- true +- UTF-8 +- unknown +- git +- 1_17_R1 +- 1.8 +- 1.8 +- +- +- +- org.spigotmc +- spigot-parent +- dev-SNAPSHOT +- ../pom.xml +- +- +- +- +- org.spigotmc +- spigot-api +- ${project.version} +- compile +- +- +- org.spigotmc +- minecraft-server +- ${project.version} +- compile +- +- +- jline +- jline +- 2.12.1 +- compile +- +- +- org.apache.logging.log4j +- log4j-iostreams +- 2.14.1 +- compile +- +- +- +- org.apache.logging.log4j +- log4j-api +- +- +- +- +- org.ow2.asm +- asm +- 9.1 +- compile +- +- +- +- com.googlecode.json-simple +- json-simple +- 1.1.1 +- runtime +- +- +- org.xerial +- sqlite-jdbc +- 3.34.0 +- runtime +- +- +- mysql +- mysql-connector-java +- 5.1.49 +- runtime +- +- +- +- org.apache.maven +- maven-resolver-provider +- 3.8.1 +- runtime +- +- +- org.apache.maven.resolver +- maven-resolver-connector-basic +- 1.7.0 +- runtime +- +- +- org.apache.maven.resolver +- maven-resolver-transport-http +- 1.7.0 +- runtime +- +- +- +- junit +- junit +- 4.13.1 +- test +- +- +- org.hamcrest +- hamcrest-library +- 1.3 +- test +- +- +- +- +- +- +- +- net.md-5 +- scriptus +- 0.4.1 +- +- +- ex-spigot +- +- ${bt.name}-Spigot-%s +- ../ +- spigot.desc +- +- initialize +- +- describe +- +- +- +- ex-craftbukkit +- +- -%s +- ../../CraftBukkit +- craftbukkit.desc +- +- initialize +- +- describe +- +- +- +- +- +- org.apache.maven.plugins +- maven-clean-plugin +- 3.1.0 +- +- +- initialize +- +- clean +- +- +- +- +- +- org.apache.maven.plugins +- maven-jar-plugin +- 3.2.0 +- +- +- +- false +- +- +- org.bukkit.craftbukkit.Main +- CraftBukkit +- ${spigot.desc}${craftbukkit.desc} +- ${project.build.outputTimestamp} +- Bukkit +- ${api.version} +- Bukkit Team +- true +- +- +- +- net/bukkit/ +- +- true +- +- +- +- com/bukkit/ +- +- true +- +- +- +- org/bukkit/ +- +- true +- +- +- +- +- +- +- +- org.apache.maven.plugins +- maven-shade-plugin +- 3.2.4 +- +- +- org.ow2.asm +- asm +- 9.1 +- +- +- org.ow2.asm +- asm-commons +- 9.1 +- +- +- +- +- package +- +- shade +- +- +- ${shadeSourcesJar} +- +- +- org.spigotmc:minecraft-server +- +- com/google/common/** +- com/google/gson/** +- com/google/thirdparty/** +- +- +- +- org.eclipse.sisu:org.eclipse.sisu.inject +- +- META-INF/services/javax.annotation.processing.Processor +- +- +- +- +- +- +- +- 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 +- +- +- org.apache.commons.io +- org.bukkit.craftbukkit.libs.org.apache.commons.io +- +- +- org.apache.commons.lang3 +- org.bukkit.craftbukkit.libs.org.apache.commons.lang3 +- +- +- org.apache.http +- org.bukkit.craftbukkit.libs.org.apache.http +- +- +- org.apache.maven +- org.bukkit.craftbukkit.libs.org.apache.maven +- +- +- org.codehaus.plexus +- org.bukkit.craftbukkit.libs.org.codehaus.plexus +- +- +- org.eclipse.aether +- org.bukkit.craftbukkit.libs.org.eclipse.aether +- +- +- org.eclipse.sisu +- org.bukkit.craftbukkit.libs.org.eclipse.sisu +- +- +- org.objectweb.asm +- org.bukkit.craftbukkit.libs.org.objectweb.asm +- +- +- org.bukkit.craftbukkit +- org.bukkit.craftbukkit.v${minecraft_version} +- +- org.bukkit.craftbukkit.Main* +- +- +- +- +- +- META-INF/services/java.sql.Driver +- +- +- +- +- +- +- +- net.md-5 +- specialsource-maven-plugin +- 1.2.2 +- +- +- package +- +- remap +- +- remap-fields +- +- org.spigotmc:minecraft-server:${project.version}:csrg:maps-spigot-fields +- true +- +- +- +- +- +- org.apache.maven.plugins +- maven-compiler-plugin +- 3.8.1 +- +- +- eclipse +- +- +- +- org.codehaus.plexus +- plexus-compiler-eclipse +- 2.8.8 +- +- +- org.eclipse.jdt +- ecj +- 3.24.0 +- +- +- +- +- org.apache.maven.plugins +- maven-surefire-plugin +- 2.12.4 +- +- ${basedir}/target/test-server +- +- org/bukkit/craftbukkit/inventory/ItemStack*Test.java +- +- +- +- +- +- +- +- +- shadeSourcesJar +- +- true +- true +- +- +- +- development +- +- false +- +- +- +- +- org.apache.maven.plugins +- maven-checkstyle-plugin +- 3.1.1 +- +- +- process-classes +- +- check +- +- +- +- +- checkstyle.xml +- true +- +- +- +- com.puppycrawl.tools +- checkstyle +- 8.39 +- +- +- +- +- org.codehaus.mojo +- animal-sniffer-maven-plugin +- 1.20 +- +- +- process-classes +- +- check +- +- +- +- +- +- org.codehaus.mojo.signature +- java18 +- 1.0 +- +- +- +- +- +- +- +- remapped +- +- +- +- net.md-5 +- specialsource-maven-plugin +- +- +- package +- +- remap +- +- remap-obf +- +- org.spigotmc:minecraft-server:${project.version}:csrg:maps-spigot +- true +- true +- remapped-obf +- +- +- +- package +- +- remap +- +- remap-mojang +- +- ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar +- org.spigotmc:minecraft-server:${project.version}:txt:maps-mojang +- true +- remapped-mojang +- +- +- +- +- +- +- +- +- diff --git a/Spigot-Server-Patches/Shoulder-Entities-Release-API.patch b/patches/server/Shoulder-Entities-Release-API.patch similarity index 64% rename from Spigot-Server-Patches/Shoulder-Entities-Release-API.patch rename to patches/server/Shoulder-Entities-Release-API.patch index 4b864860b3..53a7ff4c6b 100644 --- a/Spigot-Server-Patches/Shoulder-Entities-Release-API.patch +++ b/patches/server/Shoulder-Entities-Release-API.patch @@ -4,11 +4,11 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.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 { +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { } @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public Entity releaseLeftShoulderEntity() { + Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityLeft()); + if (entity != null) { -+ this.setShoulderEntityLeft(new NBTTagCompound()); ++ this.setShoulderEntityLeft(new CompoundTag()); + } + return entity; + } @@ -24,28 +24,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public Entity releaseRightShoulderEntity() { + Entity entity = this.spawnEntityFromShoulder0(this.getShoulderEntityRight()); + if (entity != null) { -+ this.setShoulderEntityRight(new NBTTagCompound()); ++ this.setShoulderEntityRight(new CompoundTag()); + } + return entity; + } + // Paper - maintain old signature - private boolean spawnEntityFromShoulder(NBTTagCompound nbttagcompound) { // CraftBukkit void->boolean -- if (!this.world.isClientSide && !nbttagcompound.isEmpty()) { + private boolean spawnEntityFromShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean +- if (!this.level.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); ++ private Entity spawnEntityFromShoulder0(@Nullable CompoundTag nbttagcompound) { ++ if (!this.level.isClientSide && nbttagcompound != null && !nbttagcompound.isEmpty()) { + return EntityType.create(nbttagcompound, this.level).map((entity) -> { // CraftBukkit + if (entity instanceof TamableAnimal) { + ((TamableAnimal) entity).setOwnerUUID(this.uuid); } - entity.setPosition(this.locX(), this.locY() + 0.699999988079071D, this.locZ()); -- return ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit + entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ()); +- return ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit - }).orElse(true); // CraftBukkit -+ boolean addedToWorld = ((WorldServer) this.world).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit ++ boolean addedToWorld = ((ServerLevel) this.level).addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit + return addedToWorld ? entity : null; + }).orElse(null); // CraftBukkit // Paper - false -> null } @@ -62,7 +62,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + this.getHandle().getCooldowns().addCooldown(CraftMagicNumbers.getItem(material), ticks); } + // Paper start @@ -93,4 +93,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public boolean discoverRecipe(NamespacedKey recipe) { - return discoverRecipes(Arrays.asList(recipe)) != 0; + return this.discoverRecipes(Arrays.asList(recipe)) != 0; diff --git a/Spigot-Server-Patches/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch similarity index 87% rename from Spigot-Server-Patches/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch rename to patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch index fd7ae88eac..9a80ee0af2 100644 --- a/Spigot-Server-Patches/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ b/patches/server/Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -5,32 +5,32 @@ 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 +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 { +--- 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 { + try { 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; +- 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 var5) { + if (outputStream != null) { + try { 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) { + public SystemReport fillSystemReport(SystemReport systemreport) { 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 @@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); + deadline.add(Calendar.DAY_OF_YEAR, -7); 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 ***"); @@ -104,7 +104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - 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 ) + if ( net.minecraft.world.level.Level.lastPhysicsProblem != null ) { @@ -0,0 +0,0 @@ public class WatchdogThread extends Thread } @@ -112,6 +112,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 ); + WatchdogThread.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/patches/server/Show-blockstate-location-if-we-failed-to-read-it.patch similarity index 88% rename from Spigot-Server-Patches/Show-blockstate-location-if-we-failed-to-read-it.patch rename to patches/server/Show-blockstate-location-if-we-failed-to-read-it.patch index ad3c24e902..07166c991d 100644 --- a/Spigot-Server-Patches/Show-blockstate-location-if-we-failed-to-read-it.patch +++ b/patches/server/Show-blockstate-location-if-we-failed-to-read-it.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.ja 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 +@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockStat public CraftBlockEntityState(Block block, Class tileEntityClass) { super(block); @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.tileEntityClass = tileEntityClass; // get tile entity from block: -@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockState +@@ -0,0 +0,0 @@ public class CraftBlockEntityState extends CraftBlockStat this.load(this.snapshot); } // Paper end diff --git a/patches/server/Significantly-improve-performance-of-the-end-generat.patch b/patches/server/Significantly-improve-performance-of-the-end-generat.patch new file mode 100644 index 0000000000..40d0e81bba --- /dev/null +++ b/patches/server/Significantly-improve-performance-of-the-end-generat.patch @@ -0,0 +1,63 @@ +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/TheEndBiomeSource.java b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java ++++ b/src/main/java/net/minecraft/world/level/biome/TheEndBiomeSource.java +@@ -0,0 +0,0 @@ public class TheEndBiomeSource extends BiomeSource { + private final Biome midlands; + private final Biome islands; + private final Biome barrens; ++ // 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 TheEndBiomeSource(Registry biomeRegistry, long seed) { + this(biomeRegistry, seed, biomeRegistry.getOrThrow(Biomes.THE_END), biomeRegistry.getOrThrow(Biomes.END_HIGHLANDS), biomeRegistry.getOrThrow(Biomes.END_MIDLANDS), biomeRegistry.getOrThrow(Biomes.SMALL_END_ISLANDS), biomeRegistry.getOrThrow(Biomes.END_BARRENS)); +@@ -0,0 +0,0 @@ public class TheEndBiomeSource extends BiomeSource { + float f = 100.0F - Mth.sqrt((long) i * (long) i + (long) j * (long) j) * 8.0F; // Paper - cast ints to long to avoid integer overflow + f = Mth.clamp(f, -100.0F, 80.0F); + ++ NoiseCache cache = noiseCache.get().computeIfAbsent(simplexNoise, noiseKey -> new NoiseCache()); // Paper + for(int o = -12; o <= 12; ++o) { + for(int p = -12; p <= 12; ++p) { + long q = (long)(k + o); + long r = (long)(l + p); +- if (q * q + r * r > 4096L && simplexNoise.getValue((double)q, (double)r) < (double)-0.9F) { +- float g = (Mth.abs((float)q) * 3439.0F + Mth.abs((float)r) * 147.0F) % 13.0F + 9.0F; ++ // Paper start - Significantly improve end generation performance by using a noise cache ++ long key = net.minecraft.world.level.ChunkPos.asLong((int) q, (int) r); ++ int index = (int) it.unimi.dsi.fastutil.HashCommon.mix(key) & 8191; ++ float g = Float.MIN_VALUE; ++ if (cache.keys[index] == key) { ++ g = cache.values[index]; ++ } else { ++ if (q * q + r * r > 4096L && simplexNoise.getValue((double)q, (double)r) < (double)-0.9F) { ++ g = (Mth.abs((float) q) * 3439.0F + Mth.abs((float) r) * 147.0F) % 13.0F + 9.0F; ++ } ++ cache.keys[index] = key; ++ cache.values[index] = g; ++ } ++ if (g != Float.MIN_VALUE) { ++ // Paper end + float h = (float)(m - o * 2); + float s = (float)(n - p * 2); + float t = 100.0F - Mth.sqrt(h * h + s * s) * g; diff --git a/patches/server/SkeletonHorse-Additions.patch b/patches/server/SkeletonHorse-Additions.patch new file mode 100644 index 0000000000..1c37bd6e05 --- /dev/null +++ b/patches/server/SkeletonHorse-Additions.patch @@ -0,0 +1,97 @@ +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/animal/horse/SkeletonTrapGoal.java b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java ++++ b/src/main/java/net/minecraft/world/entity/animal/horse/SkeletonTrapGoal.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.Level; + public class SkeletonTrapGoal extends Goal { + + private final SkeletonHorse horse; ++ private java.util.List eligiblePlayers; // Paper + + public SkeletonTrapGoal(SkeletonHorse skeletonHorse) { + this.horse = skeletonHorse; +@@ -0,0 +0,0 @@ public class SkeletonTrapGoal extends Goal { + + @Override + public boolean canUse() { +- return this.horse.level.hasNearbyAlivePlayer(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D); ++ return !(eligiblePlayers = this.horse.level.findNearbyBukkitPlayers(this.horse.getX(), this.horse.getY(), this.horse.getZ(), 10.0D, false)).isEmpty(); // Paper + } + + @Override + public void tick() { + ServerLevel worldserver = (ServerLevel) this.horse.level; ++ if (!new com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent((org.bukkit.entity.SkeletonHorse) this.horse.getBukkitEntity(), eligiblePlayers).callEvent()) return; // Paper + DifficultyInstance difficultydamagescaler = worldserver.getCurrentDifficultyAt(this.horse.blockPosition()); + + this.horse.setTrap(false); +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -0,0 +0,0 @@ public interface EntityGetter { + return player; + } + ++ // Paper start ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, boolean notSpectator) { ++ return findNearbyBukkitPlayers(x, y, z, radius, notSpectator ? EntitySelector.NO_SPECTATORS : net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR); ++ } ++ ++ default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { ++ com.google.common.collect.ImmutableList.Builder builder = com.google.common.collect.ImmutableList.builder(); ++ ++ for (Player human : this.players()) { ++ if (predicate == null || predicate.test(human)) { ++ double distanceSquared = human.distanceToSqr(x, y, z); ++ ++ if (radius < 0.0D || distanceSquared < radius * radius) { ++ builder.add(human.getBukkitEntity()); ++ } ++ } ++ } ++ ++ return builder.build(); ++ } ++ // Paper end ++ + @Nullable + default Player getNearestPlayer(Entity entity, double maxDistance) { + return this.getNearestPlayer(entity.getX(), entity.getY(), entity.getZ(), maxDistance, 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 net.minecraft.world.entity.animal.horse.SkeletonHorse getHandle() { ++ return (net.minecraft.world.entity.animal.horse.SkeletonHorse) super.getHandle(); ++ } ++ ++ @Override ++ public int getTrapTime() { ++ return getHandle().trapTime; ++ } ++ ++ @Override ++ public boolean isTrap() { ++ return getHandle().isTrap(); ++ } ++ ++ @Override ++ public void setTrap(boolean trap) { ++ getHandle().setTrap(trap); ++ } ++ // Paper end + } diff --git a/patches/server/Skip-distance-map-update-when-spawning-disabled.patch b/patches/server/Skip-distance-map-update-when-spawning-disabled.patch new file mode 100644 index 0000000000..de4673a7e0 --- /dev/null +++ b/patches/server/Skip-distance-map-update-when-spawning-disabled.patch @@ -0,0 +1,19 @@ +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/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + int l = this.distanceManager.getNaturalSpawnChunkCount(); + // Paper start - per player mob spawning + NaturalSpawner.SpawnState spawnercreature_d; // moved down +- if (this.chunkMap.playerMobDistanceMap != null) { ++ if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't update when animals and monsters are disabled + // update distance map + this.level.timings.playerMobDistanceMapUpdate.startTiming(); + this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); diff --git a/patches/server/Slime-Pathfinder-Events.patch b/patches/server/Slime-Pathfinder-Events.patch new file mode 100644 index 0000000000..71f7298b2d --- /dev/null +++ b/patches/server/Slime-Pathfinder-Events.patch @@ -0,0 +1,167 @@ +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/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Slime.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Slime.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.biome.Biomes; + import net.minecraft.world.level.levelgen.WorldgenRandom; + import net.minecraft.world.level.storage.loot.BuiltInLootTables; + import net.minecraft.world.phys.Vec3; ++// 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; ++// Paper end + // CraftBukkit start + import java.util.ArrayList; + import java.util.List; +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + @Override + public void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); ++ nbt.putBoolean("Paper.canWander", this.canWander); // Paper + nbt.putInt("Size", this.getSize() - 1); + nbt.putBoolean("wasOnGround", this.wasOnGround); + } +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + public void readAdditionalSaveData(CompoundTag nbt) { + this.setSize(nbt.getInt("Size") + 1, false); + super.readAdditionalSaveData(nbt); ++ // Paper start - check exists before loading or this will be loaded as false ++ if (nbt.contains("Paper.canWander")) { ++ this.canWander = nbt.getBoolean("Paper.canWander"); ++ } ++ // Paper end + this.wasOnGround = nbt.getBoolean("wasOnGround"); + } + +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return (this.slime.isInWater() || this.slime.isInLava()) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeSwimEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + public boolean canUse() { + LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (!this.slime.canAttack(entityliving)) { ++ return false; ++ } ++ return this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + public boolean canContinueToUse() { + LivingEntity entityliving = this.slime.getTarget(); + +- return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : --this.growTiredTimer > 0); ++ // Paper start ++ if (entityliving == null || !entityliving.isAlive()) { ++ return false; ++ } ++ if (!this.slime.canAttack(entityliving)) { ++ return false; ++ } ++ return --this.growTiredTimer > 0 && this.slime.canWander && new SlimeTargetLivingEntityEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (org.bukkit.entity.LivingEntity) entityliving.getBukkitEntity()).callEvent(); ++ // Paper end + } + + @Override +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F); + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); + } ++ ++ // Paper start - clear timer and target when goal resets ++ public void stop() { ++ this.growTiredTimer = 0; ++ this.slime.setTarget(null); ++ } ++ // Paper end + } + + private static class SlimeRandomDirectionGoal extends Goal { +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return this.slime.getTarget() == null && (this.slime.onGround || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl && this.slime.canWander; // Paper - add canWander + } + + @Override + public void tick() { + if (--this.nextRandomizeTime <= 0) { + this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); +- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); ++ // Paper start ++ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360)); ++ if (!this.slime.canWander || !event.callEvent()) return; ++ this.chosenDegrees = event.getNewYaw(); ++ // Paper end + } + + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.chosenDegrees, false); +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + + @Override + public boolean canUse() { +- return !this.slime.isPassenger(); ++ return !this.slime.isPassenger() && this.slime.canWander && new SlimeWanderEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity()).callEvent(); // Paper + } + + @Override +@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { + ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setWantedMovement(1.0D); + } + } ++ ++ // 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 ++ @Override ++ public boolean canWander() { ++ return getHandle().canWander(); ++ } ++ ++ @Override ++ 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/patches/server/Spawn-player-in-correct-world-on-login.patch similarity index 80% rename from Spigot-Server-Patches/Spawn-player-in-correct-world-on-login.patch rename to patches/server/Spawn-player-in-correct-world-on-login.patch index 1bf01a8259..29a184cf53 100644 --- a/Spigot-Server-Patches/Spawn-player-in-correct-world-on-login.patch +++ b/patches/server/Spawn-player-in-correct-world-on-login.patch @@ -14,17 +14,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - 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")) { ++ if (nbttagcompound != null && nbttagcompound.contains("WorldUUIDMost") && nbttagcompound.contains("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(); ++ resourcekey = ((CraftWorld) bWorld).getHandle().dimension(); + } else { -+ resourcekey = World.OVERWORLD; ++ resourcekey = Level.OVERWORLD; + } + } else if (nbttagcompound != null) { + // Vanilla migration support + // Paper end - DataResult dataresult = DimensionManager.a(new Dynamic(DynamicOpsNBT.a, nbttagcompound.get("Dimension"))); + DataResult dataresult = DimensionType.parseLegacy(new Dynamic(NbtOps.INSTANCE, nbttagcompound.get("Dimension"))); Logger logger = PlayerList.LOGGER; diff --git a/patches/server/Stop-copy-on-write-operations-for-updating-light-dat.patch b/patches/server/Stop-copy-on-write-operations-for-updating-light-dat.patch new file mode 100644 index 0000000000..605b7d91fd --- /dev/null +++ b/patches/server/Stop-copy-on-write-operations-for-updating-light-dat.patch @@ -0,0 +1,297 @@ +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/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.LightChunkGetter; + + public class BlockLightSectionStorage extends LayerLightSectionStorage { + protected BlockLightSectionStorage(LightChunkGetter chunkProvider) { +- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap<>())); ++ super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data + } + + @Override +@@ -0,0 +0,0 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage { +- public BlockDataLayerStorageMap(Long2ObjectOpenHashMap arrays) { +- super(arrays); ++ public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data ++ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data + } + + @Override + public BlockLightSectionStorage.BlockDataLayerStorageMap copy() { +- return new BlockLightSectionStorage.BlockDataLayerStorageMap(this.map.clone()); ++ return new BlockDataLayerStorageMap(this.data, true); // Paper - avoid copying light data + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java ++++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java +@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { + private final long[] lastSectionKeys = new long[2]; + private final DataLayer[] lastSections = new DataLayer[2]; + private boolean cacheEnabled; +- protected final Long2ObjectOpenHashMap map; ++ 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 + +- protected DataLayerStorageMap(Long2ObjectOpenHashMap arrays) { +- this.map = arrays; ++ // Paper start - avoid copying light data ++ protected DataLayerStorageMap(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.clearCache(); + this.cacheEnabled = true; + } +@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { + public abstract M copy(); + + public void copyDataLayer(long pos) { +- this.map.put(pos, this.map.get(pos).copy()); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data + this.clearCache(); + } + + public boolean hasLayer(long chunkPos) { +- return this.map.containsKey(chunkPos); ++ return lookup.apply(chunkPos) != null; // Paper - avoid copying light data + } + + @Nullable +- public DataLayer getLayer(long chunkPos) { ++ public final DataLayer getLayer(long chunkPos) { // Paper - final + if (this.cacheEnabled) { + for(int i = 0; i < 2; ++i) { + if (chunkPos == this.lastSectionKeys[i]) { +@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { + } + } + +- DataLayer dataLayer = this.map.get(chunkPos); ++ DataLayer dataLayer = lookup.apply(chunkPos); // Paper - avoid copying light data + if (dataLayer == null) { + return null; + } else { +@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { + + @Nullable + public DataLayer removeLayer(long chunkPos) { +- return this.map.remove(chunkPos); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data + } + + public void setLayer(long pos, DataLayer data) { +- this.map.put(pos, data); ++ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data ++ this.data.queueUpdate(pos, data); // Paper - avoid copying light data + } + + public void clearCache() { +diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java +@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> + protected final LongSet dataSectionSet = new LongOpenHashSet(); + protected final LongSet toMarkNoData = new LongOpenHashSet(); + protected final LongSet toMarkData = new LongOpenHashSet(); +- protected volatile M visibleSectionData; ++ 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 updatingSectionData; + protected final LongSet changedSections = new LongOpenHashSet(); + protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); +@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> + this.layer = lightType; + this.chunkSource = chunkProvider; + this.updatingSectionData = lightData; +- this.visibleSectionData = lightData.copy(); +- this.visibleSectionData.disableCache(); ++ this.e_visible = lightData.copy(); // Paper - avoid copying light dat ++ this.e_visible.disableCache(); // Paper - avoid copying light dat + } + + protected boolean storingLightForSection(long sectionPos) { +@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> + + @Nullable + protected DataLayer getDataLayer(long sectionPos, boolean cached) { +- return this.getDataLayer((M)(cached ? this.updatingSectionData : this.visibleSectionData), sectionPos); ++ // Paper start - avoid copying light data ++ if (cached) { ++ return this.getDataLayer(this.updatingSectionData, sectionPos); ++ } else { ++ synchronized (this.visibleUpdateLock) { ++ return this.getDataLayer(this.e_visible, sectionPos); ++ } ++ } ++ // Paper end - avoid copying light data + } + + @Nullable +@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> + + protected void swapSectionMap() { + if (!this.changedSections.isEmpty()) { ++ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data + M dataLayerStorageMap = this.updatingSectionData.copy(); + dataLayerStorageMap.disableCache(); +- this.visibleSectionData = dataLayerStorageMap; ++ this.e_visible = dataLayerStorageMap; // Paper - avoid copying light data ++ } // Paper - avoid copying light data + this.changedSections.clear(); + } + +diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java ++++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java +@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage(), new Long2IntOpenHashMap(), Integer.MAX_VALUE)); ++ super(LightLayer.SKY, chunkProvider, new SkyLightSectionStorage.SkyDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data + } + + @Override +@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage i) { + (this.updatingSectionData).currentLowestY = i; +- (this.updatingSectionData).topSections.defaultReturnValue((this.updatingSectionData).currentLowestY); ++ (this.updatingSectionData).otherData.queueDefaultReturnValue((this.updatingSectionData).currentLowestY); // Paper - avoid copying light data + } + + long l = SectionPos.getZeroNode(sectionPos); +- int j = (this.updatingSectionData).topSections.get(l); ++ int j = (this.updatingSectionData).otherData.getUpdating(l); // Paper - avoid copying light data + if (j < i + 1) { +- (this.updatingSectionData).topSections.put(l, i + 1); ++ (this.updatingSectionData).otherData.queueUpdate(l, i + 1); // Paper - avoid copying light data + if (this.columnsWithSkySources.contains(l)) { + this.queueAddSource(sectionPos); + if (j > (this.updatingSectionData).currentLowestY) { +@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= i; + } + +@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage { + int currentLowestY; +- final Long2IntOpenHashMap topSections; +- +- public SkyDataLayerStorageMap(Long2ObjectOpenHashMap arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) { +- super(arrays); +- this.topSections = columnToTopSection; +- columnToTopSection.defaultReturnValue(minSectionY); ++ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data ++ ++ // Paper start - avoid copying light data ++ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object arrays, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int columnToTopSection, int minSectionY, boolean isVisible) { ++ super(arrays, isVisible); ++ this.otherData = columnToTopSection; ++ otherData.queueDefaultReturnValue(minSectionY); ++ // Paper end + this.currentLowestY = minSectionY; + } + + @Override + public SkyLightSectionStorage.SkyDataLayerStorageMap copy() { +- return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.map.clone(), this.topSections.clone(), this.currentLowestY); ++ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data ++ return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.data, this.otherData, this.currentLowestY, true); // Paper - avoid copying light data + } + } + } diff --git a/patches/server/String-based-Action-Bar-API.patch b/patches/server/String-based-Action-Bar-API.patch new file mode 100644 index 0000000000..eb04429ce8 --- /dev/null +++ b/patches/server/String-based-Action-Bar-API.patch @@ -0,0 +1,58 @@ +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/network/protocol/game/ClientboundSetActionBarTextPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.Packet; + public class ClientboundSetActionBarTextPacket implements Packet { + private final Component text; + public net.kyori.adventure.text.Component adventure$text; // Paper ++ public net.md_5.bungee.api.chat.BaseComponent[] components; // Paper + + public ClientboundSetActionBarTextPacket(Component message) { + this.text = message; +@@ -0,0 +0,0 @@ public class ClientboundSetActionBarTextPacket implements Packet(Lists.transform(this.lore, CraftChatMessage::fromJSONComponent)); } @@ -68,7 +68,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end @Override public boolean hasCustomModelData() { - return customModelData != null; + return this.customModelData != null; @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { } diff --git a/patches/server/Support-old-UUID-format-for-NBT.patch b/patches/server/Support-old-UUID-format-for-NBT.patch new file mode 100644 index 0000000000..022f678510 --- /dev/null +++ b/patches/server/Support-old-UUID-format-for-NBT.patch @@ -0,0 +1,100 @@ +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/CompoundTag.java b/src/main/java/net/minecraft/nbt/CompoundTag.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/nbt/CompoundTag.java ++++ b/src/main/java/net/minecraft/nbt/CompoundTag.java +@@ -0,0 +0,0 @@ public class CompoundTag implements Tag { + } + + public void putUUID(String key, UUID value) { ++ // Paper start - support old format ++ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ this.tags.remove(key + "Most"); ++ this.tags.remove(key + "Least"); ++ } ++ // Paper end + this.tags.put(key, NbtUtils.createUUID(value)); + } + +@@ -0,0 +0,0 @@ public class CompoundTag implements Tag { + * You must use {@link #hasUUID(String)} before or else it will throw an NPE. + */ + public UUID getUUID(String key) { ++ // Paper start - support old format ++ if (!contains(key, 11) && this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ return new UUID(this.getLong(key + "Most"), this.getLong(key + "Least")); ++ } ++ // Paper end + return NbtUtils.loadUUID(this.get(key)); + } + + public boolean hasUUID(String key) { ++ // Paper start - support old format ++ if (this.contains(key + "Most", 99) && this.contains(key + "Least", 99)) { ++ return true; ++ } ++ // Paper end + Tag tag = this.get(key); + return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4; + } +diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/nbt/NbtUtils.java ++++ b/src/main/java/net/minecraft/nbt/NbtUtils.java +@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + + public final class NbtUtils { +- private static final Comparator YXZ_LISTTAG_INT_COMPARATOR = Comparator.comparingInt((listTag) -> { ++ private static final Comparator YXZ_LISTTAG_INT_COMPARATOR = Comparator.comparingInt((listTag) -> { // Paper - decompile fix + return listTag.getInt(1); + }).thenComparingInt((listTag) -> { + return listTag.getInt(0); + }).thenComparingInt((listTag) -> { + return listTag.getInt(2); + }); +- private static final Comparator YXZ_LISTTAG_DOUBLE_COMPARATOR = Comparator.comparingDouble((listTag) -> { ++ private static final Comparator YXZ_LISTTAG_DOUBLE_COMPARATOR = Comparator.comparingDouble((listTag) -> { // Paper - decompile fix + return listTag.getDouble(1); + }).thenComparingDouble((listTag) -> { + return listTag.getDouble(0); +@@ -0,0 +0,0 @@ public final class NbtUtils { + string = compound.getString("Name"); + } + ++ // Paper start - support string UUID's ++ if (compound.contains("Id", 8)) { ++ uUID = UUID.fromString(compound.getString("Id")); ++ } ++ // Paper end + if (compound.hasUUID("Id")) { + uUID = compound.getUUID("Id"); + } +@@ -0,0 +0,0 @@ public final class NbtUtils { + } + + public static CompoundTag update(DataFixer fixer, DataFixTypes fixTypes, CompoundTag compound, int oldVersion, int targetVersion) { +- return fixer.update(fixTypes.getType(), new Dynamic<>(NbtOps.INSTANCE, compound), oldVersion, targetVersion).getValue(); ++ return (CompoundTag) fixer.update(fixTypes.getType(), new com.mojang.serialization.Dynamic<>(NbtOps.INSTANCE, compound), oldVersion, targetVersion).getValue(); // Paper - decompile fix + } + + public static Component toPrettyComponent(Tag element) { +@@ -0,0 +0,0 @@ public final class NbtUtils { + CompoundTag compoundTag2 = new CompoundTag(); + if (i + 2 <= string.length()) { + String string3 = string.substring(i + 1, string.indexOf(125, i)); +- COMMA_SPLITTER.split(string3).forEach((string2) -> { +- List list = COLON_SPLITTER.splitToList(string2); ++ COMMA_SPLITTER.split(string3).forEach(it -> { // Paper - decompile fix ++ List list = COLON_SPLITTER.splitToList(it); // Paper - decompile fix + if (list.size() == 2) { + compoundTag2.putString(list.get(0), list.get(1)); + } else { diff --git a/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLo.patch b/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLo.patch new file mode 100644 index 0000000000..b5588eae44 --- /dev/null +++ b/patches/server/Synchronize-PalettedContainer-instead-of-ReentrantLo.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 29 May 2020 20:29:02 -0400 +Subject: [PATCH] Synchronize PalettedContainer 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/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + private final DebugBuffer> traces = null; + + public void acquire() { ++ /* // Paper start - disable this - use proper synchronization + if (this.traces != null) { + Thread thread = Thread.currentThread(); + this.traces.push(Pair.of(thread, thread.getStackTrace())); + } + + ThreadingDetector.checkAndLock(this.lock, this.traces, "PalettedContainer"); ++ */ // Paper end + } + + public void release() { +- this.lock.release(); ++ //this.lock.release(); // Paper - disable this + } + + // Paper start - Anti-Xray - Add predefined objects +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + return this.palette.idFor(objectAdded); + } + +- public T getAndSet(int x, int y, int z, T value) { ++ public synchronized T getAndSet(int x, int y, int z, T value) { // Paper - synchronize + Object var6; + try { + this.acquire(); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + return (T)(object == null ? this.defaultValue : object); + } + +- public void set(int i, int j, int k, T object) { ++ public synchronized void set(int i, int j, int k, T object) { // Paper - synchronize + try { + this.acquire(); + this.set(getIndex(i, j, k), object); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + return (T)(object == null ? this.defaultValue : object); + } + +- public void read(FriendlyByteBuf buf) { ++ public synchronized void read(FriendlyByteBuf buf) { // Paper - synchronize + try { + this.acquire(); + int i = buf.readByte(); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + @Deprecated public void write(FriendlyByteBuf buf) { + write(buf, null, 0); + } +- public void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int bottomBlockY) { ++ public synchronized void write(FriendlyByteBuf buf, com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int bottomBlockY) { // Paper - synchronize + // Paper end + try { + this.acquire(); +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + + } + +- public void read(ListTag paletteNbt, long[] data) { ++ public synchronized void read(ListTag paletteNbt, long[] data) { // Paper - synchronize + try { + this.acquire(); + // 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)? +@@ -0,0 +0,0 @@ public class PalettedContainer implements PaletteResize { + + } + +- public void write(CompoundTag nbt, String paletteKey, String dataKey) { ++ public synchronized void write(CompoundTag nbt, String paletteKey, String dataKey) { // Paper - synchronize + try { + this.acquire(); + HashMapPalette hashMapPalette = new HashMapPalette<>(this.registry, this.bits, this.dummyPaletteResize, this.reader, this.writer); diff --git a/Spigot-Server-Patches/System-property-for-disabling-watchdoge.patch b/patches/server/System-property-for-disabling-watchdoge.patch similarity index 67% rename from Spigot-Server-Patches/System-property-for-disabling-watchdoge.patch rename to patches/server/System-property-for-disabling-watchdoge.patch index f59f1d69b9..c5213c8c5a 100644 --- a/Spigot-Server-Patches/System-property-for-disabling-watchdoge.patch +++ b/patches/server/System-property-for-disabling-watchdoge.patch @@ -9,11 +9,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 ) + while ( !this.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 +- if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.timeoutTime ) ++ if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.monotonicMillis() > this.lastTick + this.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/patches/server/Tameable-getOwnerUniqueId-API.patch similarity index 89% rename from Spigot-Server-Patches/Tameable-getOwnerUniqueId-API.patch rename to patches/server/Tameable-getOwnerUniqueId-API.patch index 5f74fcd941..012589c671 100644 --- a/Spigot-Server-Patches/Tameable-getOwnerUniqueId-API.patch +++ b/patches/server/Tameable-getOwnerUniqueId-API.patch @@ -14,23 +14,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } ++ @Override + public UUID getOwnerUniqueId() { + return getOwnerUUID(); + } public UUID getOwnerUUID() { - return getHandle().getOwnerUUID(); + return this.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(); + return (TamableAnimal) super.getHandle(); } ++ @Override + public UUID getOwnerUniqueId() { + return getOwnerUUID(); + } public UUID getOwnerUUID() { try { - return getHandle().getOwnerUUID(); + return this.getHandle().getOwnerUUID(); diff --git a/patches/server/Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/Thread-Safe-Vanilla-Command-permission-checking.patch new file mode 100644 index 0000000000..7161c7c2f2 --- /dev/null +++ b/patches/server/Thread-Safe-Vanilla-Command-permission-checking.patch @@ -0,0 +1,53 @@ +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 CommandSourceStack) { + try { +- ((CommandSourceStack) source).currentCommand = this; ++ ((CommandSourceStack) source).currentCommand.set(this); // Paper + return this.requirement.test(source); + } finally { +- ((CommandSourceStack) source).currentCommand = null; ++ ((CommandSourceStack) source).currentCommand.set(null); // Paper + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java ++++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java +@@ -0,0 +0,0 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + private final ResultConsumer consumer; + private final EntityAnchorArgument.Anchor anchor; + private final Vec2 rotation; +- public volatile CommandNode currentCommand; // CraftBukkit ++ public ThreadLocal currentCommand = new ThreadLocal<>(); // CraftBukkit // Paper + + public CommandSourceStack(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity) { + this(output, pos, rot, world, level, simpleName, name, server, entity, false, (commandcontext, flag, j) -> { +@@ -0,0 +0,0 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy + @Override + public boolean hasPermission(int level) { + // CraftBukkit start +- CommandNode currentCommand = this.currentCommand; ++ // Paper start - fix concurrency issue ++ CommandNode currentCommand = this.currentCommand.get(); + if (currentCommand != null) { + return this.hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand)); ++ // Paper end + } + // CraftBukkit end + diff --git a/patches/server/Throw-proper-exception-on-empty-JsonList-file.patch b/patches/server/Throw-proper-exception-on-empty-JsonList-file.patch new file mode 100644 index 0000000000..9f9ac5fbf7 --- /dev/null +++ b/patches/server/Throw-proper-exception-on-empty-JsonList-file.patch @@ -0,0 +1,18 @@ +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/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java +@@ -0,0 +0,0 @@ public abstract class StoredUserList> { + + try { + JsonArray jsonarray = (JsonArray) StoredUserList.GSON.fromJson(bufferedreader, JsonArray.class); ++ com.google.common.base.Preconditions.checkState(jsonarray != null, "The file \"" + this.file.getName() + "\" is either empty or corrupt"); // Paper + + this.map.clear(); + Iterator iterator = jsonarray.iterator(); diff --git a/Spigot-Server-Patches/Timings-v2.patch b/patches/server/Timings-v2.patch similarity index 66% rename from Spigot-Server-Patches/Timings-v2.patch rename to patches/server/Timings-v2.patch index 8f3f81270f..674b561ec3 100644 --- a/Spigot-Server-Patches/Timings-v2.patch +++ b/patches/server/Timings-v2.patch @@ -13,10 +13,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package co.aikar.timings; + +import com.google.common.collect.MapMaker; -+import net.minecraft.commands.CustomFunction; ++import net.minecraft.commands.CommandFunction; +import net.minecraft.network.protocol.Packet; +import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.TileEntity; ++import net.minecraft.world.level.block.entity.BlockEntity; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; + @@ -130,7 +130,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param entity + * @return + */ -+ public static Timing getTileEntityTimings(TileEntity entity) { ++ public static Timing getTileEntityTimings(BlockEntity entity) { + String entityType = entity.getClass().getName(); + return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); + } @@ -157,8 +157,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); + } + -+ public static Timing getCommandFunctionTiming(CustomFunction function) { -+ return Timings.ofSafe("Command Function - " + function.getMinecraftKey().toString()); ++ public static Timing getCommandFunctionTiming(CommandFunction function) { ++ return Timings.ofSafe("Command Function - " + function.getId()); + } +} diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java @@ -278,9 +278,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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))); ++ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedPacks(), pack -> { ++ return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.getChatLink(true))); + })) + ); + if (!TimingsManager.privacy) { @@ -316,13 +315,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ) + ); + -+ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getWorlds(), world -> { -+ if (world.getWorldData().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorldData().getName(), createObject( ++ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { ++ 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)); + })), -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()) + )); + })); + @@ -552,9 +551,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -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; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.storage.PrimaryLevelData; + +/** + * Set of timers per world, to track world specific timings. @@ -610,8 +609,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public final Timing miscMobSpawning; + -+ public WorldTimingsHandler(World server) { -+ String name = ((WorldDataServer) server.getWorldData()).getName() + " - "; ++ public WorldTimingsHandler(Level server) { ++ String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; + + mobSpawn = Timings.ofSafe(name + "mobSpawn"); + doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); @@ -665,8 +664,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); + } + -+ public static Timing getTickList(WorldServer worldserver, String timingsType) { -+ return Timings.ofSafe(((WorldDataServer) worldserver.getWorldData()).getName() + " - Scheduled " + timingsType); ++ public static Timing getTickList(ServerLevel worldserver, String timingsType) { ++ return Timings.ofSafe(((PrimaryLevelData) worldserver.getLevelData()).getLevelName() + " - Scheduled " + timingsType); + } +} diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java @@ -720,14 +719,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + " - Server Name: " + timingsServerName); + } } -diff --git a/src/main/java/net/minecraft/commands/CustomFunction.java b/src/main/java/net/minecraft/commands/CustomFunction.java +diff --git a/src/main/java/net/minecraft/commands/CommandFunction.java b/src/main/java/net/minecraft/commands/CommandFunction.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; +--- a/src/main/java/net/minecraft/commands/CommandFunction.java ++++ b/src/main/java/net/minecraft/commands/CommandFunction.java +@@ -0,0 +0,0 @@ import net.minecraft.server.ServerFunctionManager; + public class CommandFunction { + private final CommandFunction.Entry[] entries; + final ResourceLocation id; + // Paper start + public co.aikar.timings.Timing timing; + public co.aikar.timings.Timing getTiming() { @@ -738,21 +737,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // 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 + public CommandFunction(ResourceLocation id, CommandFunction.Entry[] elements) { + this.id = id; +diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.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; +--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java ++++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java +@@ -0,0 +0,0 @@ package net.minecraft.network.protocol; + import net.minecraft.network.PacketListener; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import co.aikar.timings.MinecraftTimings; // Paper @@ -760,33 +752,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start import net.minecraft.server.MinecraftServer; -@@ -0,0 +0,0 @@ public class PlayerConnectionUtils { +@@ -0,0 +0,0 @@ public class PacketUtils { - public static void ensureMainThread(Packet packet, T t0, IAsyncTaskHandler iasynctaskhandler) throws CancelledPacketHandleException { - if (!iasynctaskhandler.isMainThread()) { + public static void ensureRunningOnSameThread(Packet packet, T listener, BlockableEventLoop engine) throws RunningOnDifferentThreadException { + if (!engine.isSameThread()) { + 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()) { + engine.execute(() -> { + if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590 + if (listener.getConnection().isConnected()) { + try (Timing ignored = timing.startTiming()) { // Paper - timings - packet.a(t0); + packet.handle(listener); + } // Paper - timings } else { - PlayerConnectionUtils.LOGGER.debug("Ignoring packet due to disconnection: " + packet); + PacketUtils.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 @@ -799,19 +778,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 implements SnooperPopulator, CommandSource, AutoCloseable { +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- return !this.canSleepForTick(); + this.managedBlock(() -> { +- return !this.haveTime(); + return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick }); } -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { ++ this.managedBlock(() -> { + 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= 5000000000L) { +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit + if (this.autosavePeriod > 0 && this.tickCount % this.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(); + this.profiler.push("save"); + this.playerList.saveAll(); + this.saveAllChunks(true, false, false); + this.profiler.pop(); MinecraftServer.LOGGER.debug("Autosave finished"); - SpigotTimings.worldSaveTimer.stopTiming(); // Spigot } - this.methodProfiler.enter("snooper"); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { + this.rconConsoleSource.prepareForCommand(); + this.executeBlocking(() -> { // CraftBukkit start - fire RemoteServerCommandEvent -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface if (event.isCancelled()) { return; } + // Paper start -+ if (s.toLowerCase().startsWith("timings") && s.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { ++ if (command.toLowerCase().startsWith("timings") && command.toLowerCase().matches("timings (report|paste|get|merged|seperate)")) { + org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); + Waitable waitable = new Waitable() { + @Override @@ -1039,7 +1020,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); + } else { + // Paper end - ServerCommand serverCommand = new ServerCommand(event.getCommand(), remoteControlCommandListener.getWrapper()); + ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), this.rconConsoleSource.createCommandSourceStack()); server.dispatchServerCommand(remoteConsole, serverCommand); + } // Paper // CraftBukkit end @@ -1051,117 +1032,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + try { + return waitable.get(); + } catch (java.util.concurrent.ExecutionException e) { -+ throw new RuntimeException("Exception processing rcon command " + s, e.getCause()); ++ throw new RuntimeException("Exception processing rcon command " + command, e.getCause()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // Maintain interrupted state -+ throw new RuntimeException("Interrupted processing rcon command " + s, e); ++ throw new RuntimeException("Interrupted processing rcon command " + command, e); + } + + } + // Paper end - return this.remoteControlCommandListener.getMessages(); + return this.rconConsoleSource.getCommandResponse(); } -diff --git a/src/main/java/net/minecraft/server/level/ChunkProviderServer.java b/src/main/java/net/minecraft/server/level/ChunkProviderServer.java +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -0,0 +0,0 @@ package net.minecraft.server.level; @@ -1172,218 +1057,312 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private CompletableFuture> f(ChunkCoordIntPair chunkcoordintpair) { + private CompletableFuture> scheduleChunkLoad(ChunkPos pos) { 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); ++ try (Timing ignored = this.level.timings.chunkLoad.startTimingIfSync()) { // Paper + this.level.getProfiler().incrementCounter("chunkLoad"); +- CompoundTag nbttagcompound = this.readChunk(pos); ++ CompoundTag nbttagcompound; // Paper ++ try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings ++ nbttagcompound = this.readChunk(pos); + } // 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 (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings + boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8); if (flag) { -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair); + ChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", pos); - } + }} // 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()); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + ChunkStatus chunkstatus = ChunkHolder.getStatus(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 !chunkstatus.isOrAfter(ChunkStatus.FULL) ? ChunkHolder.UNLOADED_CHUNK : either.mapLeft((ichunkaccess) -> { ++ try (Timing ignored = level.timings.chunkPostLoad.startTimingIfSync()) { // Paper + ChunkPos chunkcoordintpair = playerchunk.getPos(); + ProtoChunk protochunk = (ProtoChunk) ichunkaccess; + LevelChunk chunk; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } return chunk; + } // Paper }); }, (runnable) -> { - Mailbox mailbox = this.mailboxMain; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + ProcessorHandle mailbox = this.mainThreadMailbox; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - PlayerChunkMap.EntityTracker playerchunkmap_entitytracker; + ChunkMap.TrackedEntity playerchunkmap_entitytracker; ObjectIterator objectiterator; -+ world.timings.tracker1.startTiming(); // Paper ++ level.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; + for (objectiterator = this.entityMap.values().iterator(); objectiterator.hasNext(); playerchunkmap_entitytracker.serverEntity.sendChanges()) { + playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + playerchunkmap_entitytracker.lastSectionPos = sectionposition1; } } -+ world.timings.tracker1.stopTiming(); // Paper ++ level.timings.tracker1.stopTiming(); // Paper if (!list.isEmpty()) { - objectiterator = this.trackedEntities.values().iterator(); + objectiterator = this.entityMap.values().iterator(); -+ world.timings.tracker2.startTiming(); // Paper ++ level.timings.tracker2.startTiming(); // Paper while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); - playerchunkmap_entitytracker.track(list); + playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); + playerchunkmap_entitytracker.updatePlayers(list); } -+ world.timings.tracker2.stopTiming(); // Paper ++ level.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 + public void broadcast(Entity entity, Packet packet) { +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.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; +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + } + + gameprofilerfiller.incrementCounter("getChunkCacheMiss"); +- level.timings.syncChunkLoadTimer.startTiming(); // Spigot + CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); + ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor; + + Objects.requireNonNull(completablefuture); ++ if (!completablefuture.isDone()) { // Paper ++ this.level.timings.syncChunkLoad.startTiming(); // Paper + chunkproviderserver_a.managedBlock(completablefuture::isDone); +- level.timings.syncChunkLoadTimer.stopTiming(); // Spigot ++ this.level.timings.syncChunkLoad.stopTiming(); // Paper ++ } // Paper + ichunkaccess = (ChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> { + return ichunkaccess1; + }, (playerchunk_failure) -> { +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + + public void save(boolean flush) { + this.runDistanceManagerUpdates(); ++ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings + this.chunkMap.saveAllChunks(flush); ++ } // Paper - Timings + } + + @Override +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.runDistanceManagerUpdates(); + this.level.timings.doChunkMap.stopTiming(); // Spigot + this.level.getProfiler().popPush("chunks"); ++ this.level.timings.chunks.startTiming(); // Paper - timings + this.tickChunks(); ++ this.level.timings.chunks.stopTiming(); // Paper - timings + this.level.timings.doChunkUnload.startTiming(); // Spigot + this.level.getProfiler().popPush("unload"); + this.chunkMap.tick(booleansupplier); +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 0L; // CraftBukkit + + this.level.getProfiler().push("naturalSpawnCount"); ++ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.distanceManager.getNaturalSpawnChunkCount(); + NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); ++ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings + + this.lastSpawnState = spawnercreature_d; + this.level.getProfiler().pop(); + //List list = Lists.newArrayList(this.playerChunkMap.f()); // Paper + //Collections.shuffle(list); // Paper ++ this.level.timings.chunkTicks.startTiming(); // Paper + this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no... + Optional optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); + +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().push("broadcast"); + LevelChunk chunk = (LevelChunk) optional.get(); + ++ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timings + playerchunk.broadcastChanges(chunk); ++ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings + this.level.getProfiler().pop(); + ChunkPos chunkcoordintpair = chunk.getPos(); + +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2); + } + +- this.level.timings.doTickTiles.startTiming(); // Spigot ++ // this.level.timings.doTickTiles.startTiming(); // Spigot // Paper + this.level.tickChunk(chunk, k); +- this.level.timings.doTickTiles.stopTiming(); // Spigot ++ // this.level.timings.doTickTiles.stopTiming(); // Spigot // Paper + } + } + }); ++ this.level.timings.chunkTicks.stopTiming(); // Paper + this.level.getProfiler().push("customSpawners"); + if (flag1) { ++ try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings + this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); ++ } // Paper - timings + } + + this.level.getProfiler().pop(); + this.level.getProfiler().pop(); + } + +- this.level.timings.tracker.startTiming(); // Spigot + this.chunkMap.tick(); +- this.level.timings.tracker.stopTiming(); // Spigot + } + + private void getFullChunk(long pos, Consumer chunkConsumer) { +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.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 com.mojang.datafixers.DataFixer; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; + import java.util.logging.Level; 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"); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + DefaultedRegistry registryblocks = Registry.BLOCK; + + Objects.requireNonNull(registryblocks); +- this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock); // CraftBukkit - decompile error ++ this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings + Predicate predicate2 = (fluidtype) -> { // CraftBukkit - decompile error + return fluidtype == null || fluidtype == Fluids.EMPTY; + }; + registryblocks = Registry.FLUID; + Objects.requireNonNull(registryblocks); +- this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid); // CraftBukkit - decompile error ++ this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // CraftBukkit - decompile error // Paper - Timings + this.navigatingMobs = new ObjectOpenHashSet(); + this.blockEvents = new ObjectLinkedOpenHashSet(); + this.dragonParts = new Int2ObjectOpenHashMap(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.updateSkyBrightness(); + this.tickTime(); + gameprofilerfiller.popPush("chunkSource"); + this.timings.chunkProviderTick.startTiming(); // Paper - timings - this.getChunkProvider().tick(booleansupplier); + this.getChunkSource().tick(shouldKeepTicking); + this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("tickPending"); + gameprofilerfiller.popPush("tickPending"); - timings.doTickPending.startTiming(); // Spigot + timings.scheduledBlocks.startTiming(); // Paper - if (!this.isDebugWorld()) { - this.nextTickListBlock.b(); - this.nextTickListFluid.b(); + if (!this.isDebug()) { + this.blockTicks.tick(); + this.liquidTicks.tick(); } - timings.doTickPending.stopTiming(); // Spigot + timings.scheduledBlocks.stopTiming(); // Paper - gameprofilerfiller.exitEnter("raid"); + gameprofilerfiller.popPush("raid"); + this.timings.raids.startTiming(); // Paper - timings - this.persistentRaid.a(); + this.raids.tick(); + this.timings.raids.stopTiming(); // Paper - timings - gameprofilerfiller.exitEnter("blockEvents"); + gameprofilerfiller.popPush("blockEvents"); timings.doSounds.startTiming(); // Spigot - this.ak(); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { + this.runBlockEvents(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } - gameprofilerfiller.exitEnter("tickBlocks"); + gameprofilerfiller.popPush("tickBlocks"); + timings.chunkTicksBlocks.startTiming(); // Paper - if (i > 0) { - ChunkSection[] achunksection = chunk.getSections(); + if (randomTickSpeed > 0) { + LevelChunkSection[] achunksection = chunk.getSections(); int l = achunksection.length; -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } } } - + timings.chunkTicksBlocks.stopTiming(); // Paper - gameprofilerfiller.exit(); + gameprofilerfiller.pop(); } -@@ -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 ServerLevel extends net.minecraft.world.level.Level implements Worl + } + public void tickNonPassenger(Entity entity) { ++ ++TimingHistory.entityTicks; // Paper - timings + // Spigot start ++ co.aikar.timings.Timing timer; // Paper + if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { + entity.tickCount++; ++ timer = entity.getType().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.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ try { ++ // Paper end - timings + entity.setOldPosAndRot(); + ProfilerFiller gameprofilerfiller = this.getProfiler(); + +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + + this.tickPassenger(entity, entity1); + } +- entity.tickTimer.stopTiming(); // Spigot ++ ++ } finally { timer.stopTiming(); } // Paper - timings + } -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { + +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl 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")); + if (progressListener != null) { + progressListener.progressStartNoAbort(new TranslatableComponent("menu.savingLevel")); } -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { - iprogressupdate.c(new ChatMessage("menu.savingChunks")); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + progressListener.progressStage(new TranslatableComponent("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 ++ timings.worldSaveChunks.startTiming(); // Paper + chunkproviderserver.save(flush); ++ timings.worldSaveChunks.stopTiming(); // Paper ++ }// Paper + if (flush) { + this.entityManager.saveAll(); + } else { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -0,0 +0,0 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.SmithingInventory; @@ -1391,34 +1370,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import co.aikar.timings.MinecraftTimings; // Paper // CraftBukkit end - public class PlayerConnection implements PacketListenerPlayIn { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { + public class ServerGamePacketListenerImpl implements ServerPlayerConnection, ServerGamePacketListener { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // 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")); + this.resetPosition(); + this.player.xo = this.player.getX(); + this.player.yo = this.player.getY(); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect(new TranslatableComponent("multiplayer.disconnect.idling")); } - org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot } -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser // CraftBukkit end - private void handleCommand(String s) { + private void handleCommand(String input) { - 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); + this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + input); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + this.cserver.getPluginManager().callEvent(event); if (event.isCancelled()) { - org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot @@ -1426,8 +1405,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); return; } finally { - org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot @@ -1449,16 +1428,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class PlayerList { } - public void savePlayers() { + public void saveAll() { + MinecraftTimings.savePlayers.startTiming(); // Paper for (int i = 0; i < this.players.size(); ++i) { - this.savePlayerFile((EntityPlayer) this.players.get(i)); + this.save((ServerPlayer) this.players.get(i)); } - + MinecraftTimings.savePlayers.stopTiming(); // Paper } - public WhiteList getWhitelist() { + public UserWhiteList 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 @@ -1471,7 +1450,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only public boolean forceExplosionKnockback; // SPIGOT-949 public boolean persistentInvisibility = false; @@ -1479,119 +1458,52 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } - public void move(EnumMoveType enummovetype, Vec3D vec3d) { + public void move(MoverType movementType, Vec3 movement) { - 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(); + if (this.noPhysics) { + this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z); + } else { +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + this.level.getProfiler().pop(); + } } - 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 + protected void tryCheckInsideBlocks() { +diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.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 +--- a/src/main/java/net/minecraft/world/entity/EntityType.java ++++ b/src/main/java/net/minecraft/world/entity/EntityType.java +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + return Registry.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); } - 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 EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, int maxTrackDistance, int trackTickInterval) { +- this.factory = factory; +- this.category = spawnGroup; +- this.canSpawnFarFromPlayer = spawnableFarFromPlayer; +- this.serialize = saveable; +- this.summon = summonable; +- this.fireImmune = fireImmune; ++ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, int maxTrackDistance, int trackTickInterval) { this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, canSpawnInside, dimensions, maxTrackDistance, trackTickInterval, "custom"); } // Paper - old signature ++ + 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; ++ ++ public EntityType(EntityType.EntityFactory entitytypes_b, MobCategory enumcreaturetype, boolean flag, boolean flag1, boolean flag2, boolean flag3, ImmutableSet canSpawnInside, EntityDimensions dimensions, int maxTrackDistance, int trackTickInterval, String id) { // Paper - add id ++ this.factory = entitytypes_b; ++ this.category = enumcreaturetype; ++ this.canSpawnFarFromPlayer = flag3; ++ this.serialize = flag; ++ this.summon = flag1; ++ this.fireImmune = flag2; + this.immuneTo = canSpawnInside; + this.dimensions = dimensions; + this.clientTrackingRange = maxTrackDistance; + this.updateInterval = trackTickInterval; + + // Paper start - timings + this.id = id; @@ -1603,8 +1515,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @Nullable -@@ -0,0 +0,0 @@ public class EntityTypes { - return this.bn; +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + return this.updateInterval; } + // Paper start - timings @@ -1613,32 +1525,161 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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; + public boolean trackDeltas() { + return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.GLOW_ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; } -@@ -0,0 +0,0 @@ public class EntityTypes { - SystemUtils.a(DataConverterTypes.ENTITY_TREE, s); +@@ -0,0 +0,0 @@ public class EntityType implements EntityTypeTest { + Util.fetchChoiceType(References.ENTITY_TREE, id); } -- 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 +- return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval); ++ return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions, this.clientTrackingRange, this.updateInterval, id); // 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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; +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end -- 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; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import co.aikar.timings.MinecraftTimings; // Paper + + public abstract class LivingEntity extends Entity { + +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + + @Override + public void tick() { +- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot + super.tick(); + this.updatingUsingItem(); + this.updateSwimAmount(); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + } + +- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot + this.aiStep(); +- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot + double d0 = this.getX() - this.xo; + double d1 = this.getZ() - this.zo; + float f = (float) (d0 * d0 + d1 * d1); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + if (this.isSleeping()) { + this.setXRot(0.0F); + } +- +- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot + } + + public void detectEquipmentUpdates() { +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + + this.setDeltaMovement(d4, d5, d6); + this.level.getProfiler().push("ai"); +- SpigotTimings.timerEntityAI.startTiming(); // Spigot + if (this.isImmobile()) { + this.jumping = false; + this.xxa = 0.0F; +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.serverAiStep(); + this.level.getProfiler().pop(); + } +- SpigotTimings.timerEntityAI.stopTiming(); // Spigot + + this.level.getProfiler().pop(); + this.level.getProfiler().push("jump"); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.updateFallFlying(); + AABB axisalignedbb = this.getBoundingBox(); + +- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.startTiming(); // Spigot // Paper + this.travel(new Vec3((double) this.xxa, (double) this.yya, (double) this.zza)); +- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot ++ // SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot // Paper + this.level.getProfiler().pop(); + this.level.getProfiler().push("freezing"); + boolean flag1 = this.getType().is((Tag) EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); + } + +- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot + this.pushEntities(); +- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot + this.level.getProfiler().pop(); + if (!this.level.isClientSide && this.isSensitiveToWater() && this.isInWaterRainOrBubble()) { + this.hurt(DamageSource.DROWN, 1.0F); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ import org.bukkit.Bukkit; + import org.bukkit.Location; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.block.CapturedBlockState; + import org.bukkit.craftbukkit.block.CraftBlockState; + import org.bukkit.craftbukkit.block.data.CraftBlockData; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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 BlockPos lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + }); + // CraftBukkit end +- this.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 Level implements LevelAccessor, AutoCloseable { + + timings.tileEntityTick.stopTiming(); // Spigot + this.tickingBlockEntities = false; ++ co.aikar.timings.TimingHistory.tileEntityTicks += this.getBlockTicks().size(); // Paper + gameprofilerfiller.pop(); + spigotConfig.currentPrimedTnt = 0; // Spigot + } + + public void guardEntityTick(Consumer tickConsumer, T entity) { + try { +- SpigotTimings.tickEntityTimer.startTiming(); // Spigot + tickConsumer.accept(entity); +- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/ServerTickList.java ++++ b/src/main/java/net/minecraft/world/level/ServerTickList.java +@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { + private final List> alreadyTicked = Lists.newArrayList(); + private final Consumer> ticker; + +- public ServerTickList(ServerLevel world, Predicate invalidObjPredicate, Function idToName, Consumer> tickConsumer) { +- this.ignore = invalidObjPredicate; +- this.toId = idToName; +- this.level = world; +- this.ticker = tickConsumer; ++ public ServerTickList(ServerLevel worldserver, Predicate predicate, Function function, Consumer> consumer, String timingsType) { ++ this.ignore = predicate; ++ this.toId = function; ++ this.level = worldserver; ++ this.ticker = consumer; + this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Cleanup"); + this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(worldserver, timingsType + " - Ticking"); } @@ -1646,89 +1687,42 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 { + public void tick() { + int i = this.tickNextTickList.size(); +@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { - this.e.getMethodProfiler().enter("cleaning"); + this.level.getProfiler().push("cleaning"); + this.timingCleanup.startTiming(); // Paper - NextTickListEntry nextticklistentry; + TickNextTickData nextticklistentry; while (i > 0 && iterator.hasNext()) { -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { +@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { --i; } } + this.timingCleanup.stopTiming(); // Paper + this.timingTicking.startTiming(); // Paper - this.e.getMethodProfiler().exitEnter("ticking"); + this.level.getProfiler().popPush("ticking"); - while ((nextticklistentry = (NextTickListEntry) this.f.poll()) != null) { -@@ -0,0 +0,0 @@ public class TickListServer implements TickList { + while ((nextticklistentry = (TickNextTickData) this.currentlyTicking.poll()) != null) { +@@ -0,0 +0,0 @@ public class ServerTickList 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"); + this.level.getProfiler().pop(); + this.alreadyTicked.clear(); + this.currentlyTicking.clear(); 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; +@@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike { + public static final int UPDATE_LIMIT = 512; + protected final StateDefinition stateDefinition; + private BlockState defaultBlockState; + // Paper start + public co.aikar.timings.Timing timing; + public co.aikar.timings.Timing getTiming() { @@ -1739,12 +1733,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end @Nullable - private String name; + private String descriptionId; @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 +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.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 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -0,0 +0,0 @@ import org.bukkit.inventory.InventoryHolder; // CraftBukkit end @@ -1752,62 +1746,63 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import co.aikar.timings.MinecraftTimings; // Paper +import co.aikar.timings.Timing; // Paper - public abstract class TileEntity implements net.minecraft.server.KeyedObject { // Paper + public abstract class BlockEntity 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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.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 { +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { 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 ++ try (co.aikar.timings.Timing ignored = this.level.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 { + random.setSeed(this.level.getSeed()); +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { } } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); + server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(this.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 +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.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 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.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 +@@ -0,0 +0,0 @@ public class ChunkSerializer { + private static void postLoadChunk(ServerLevel world, CompoundTag nbt, LevelChunk chunk) { + ListTag nbttaglist; - 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.startTiming(); // Spigot + if (nbt.contains("Entities", 9)) { + nbttaglist = nbt.getList("Entities", 10); + if (!nbttaglist.isEmpty()) { +@@ -0,0 +0,0 @@ public class ChunkSerializer { + } } - world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot - world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot - NBTTagList nbttaglist1 = nbttagcompound.getList("TileEntities", 10); + nbttaglist = nbt.getList("TileEntities", 10); - for (int j = 0; j < nbttaglist1.size(); ++j) { -@@ -0,0 +0,0 @@ public class ChunkRegionLoader { + for (int i = 0; i < nbttaglist.size(); ++i) { +@@ -0,0 +0,0 @@ public class ChunkSerializer { } } } @@ -1815,7 +1810,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - } - private static NBTTagCompound a(ChunkCoordIntPair chunkcoordintpair, Map, StructureStart> map, Map, LongSet> map1) { + private static CompoundTag packStructureData(ServerLevel world, ChunkPos 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 @@ -1853,17 +1848,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +deleted file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -+++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ /dev/null @@ -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 net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.storage.PrimaryLevelData; -import org.bukkit.craftbukkit.scheduler.CraftTask; -import org.bukkit.plugin.java.JavaPluginLoader; -import org.bukkit.scheduler.BukkitTask; @@ -1931,10 +1927,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - } else { - name += "(Single)"; - } -- CustomTimingsHandler result = pluginTaskTimingMap.get(name); +- CustomTimingsHandler result = SpigotTimings.pluginTaskTimingMap.get(name); - if (result == null) { - result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); -- pluginTaskTimingMap.put(name, result); +- SpigotTimings.pluginTaskTimingMap.put(name, result); - } - return result; - } @@ -1946,10 +1942,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - */ - public static CustomTimingsHandler getEntityTimings(Entity entity) { - String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = entityTypeTimingMap.get(entityType); +- CustomTimingsHandler result = SpigotTimings.entityTypeTimingMap.get(entityType); - if (result == null) { -- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), activatedEntityTimer); -- entityTypeTimingMap.put(entityType, result); +- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), SpigotTimings.activatedEntityTimer); +- SpigotTimings.entityTypeTimingMap.put(entityType, result); - } - return result; - } @@ -1959,12 +1955,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - * @param entity - * @return - */ -- public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) { +- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { - String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); +- CustomTimingsHandler result = SpigotTimings.tileEntityTypeTimingMap.get(entityType); - if (result == null) { -- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), tickTileEntityTimer); -- tileEntityTypeTimingMap.put(entityType, result); +- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), SpigotTimings.tickTileEntityTimer); +- SpigotTimings.tileEntityTypeTimingMap.put(entityType, result); - } - return result; - } @@ -1993,30 +1989,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - public final CustomTimingsHandler syncChunkLoadTileTicksTimer; - public final CustomTimingsHandler syncChunkLoadPostTimer; - -- public WorldTimingsHandler(World server) { -- String name = ((WorldDataServer) server.worldData).getName() + " - "; +- public WorldTimingsHandler(Level server) { +- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; - -- 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"); +- this.mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); +- this.doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); +- this.doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); +- this.doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); +- this.doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); +- this.doSounds = new CustomTimingsHandler("** " + name + "doSounds"); +- this.entityTick = new CustomTimingsHandler("** " + name + "entityTick"); +- this.tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); +- this.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"); +- this.syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); +- this.syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); +- this.syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); +- this.syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); +- this.syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); +- this.syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); - - -- tracker = new CustomTimingsHandler(name + "tracker"); -- doTick = new CustomTimingsHandler(name + "doTick"); -- tickEntities = new CustomTimingsHandler(name + "tickEntities"); +- this.tracker = new CustomTimingsHandler(name + "tracker"); +- this.doTick = new CustomTimingsHandler(name + "doTick"); +- this.tickEntities = new CustomTimingsHandler(name + "tickEntities"); - } - } -} @@ -2026,14 +2022,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + CraftPlayer.this.getHandle().connection.send(packet); } + + // Paper start + @Override + public int getPing() + { -+ return getHandle().ping; ++ return getHandle().latency; + } + // Paper end }; @@ -2066,8 +2062,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - }); + }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + this.handle(task, 0L); + for (CraftTask taskPending = this.head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { if (taskPending == task) { @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { } @@ -2075,12 +2071,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - }); + }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper - handle(task, 0L); - for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { + this.handle(task, 0L); + for (CraftTask taskPending = this.head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { if (taskPending == task) { @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { if (task.isSync()) { - currentTask = task; + this.currentTask = task; try { - task.timings.startTiming(); // Spigot task.run(); @@ -2089,14 +2085,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper start String msg = String.format( @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - runners.remove(task.getTaskId()); + this.runners.remove(task.getTaskId()); } } -+ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); - pending.addAll(temp); ++ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); // Paper + this.pending.addAll(temp); temp.clear(); -+ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); - debugHead = debugHead.getNextHead(currentTick); ++ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper + this.debugHead = this.debugHead.getNextHead(currentTick); } @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { @@ -2175,10 +2171,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void run() { + try (Timing ignored = timings.startTiming()) { // Paper - if (rTask != null) { - rTask.run(); + if (this.rTask != null) { + this.rTask.run(); } else { - cTask.accept(this); + this.cTask.accept(this); } + } // Paper } @@ -2189,8 +2185,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - Class getTaskClass() { -+ public Class getTaskClass() { - return (rTask != null) ? rTask.getClass() : ((cTask != null) ? cTask.getClass() : null); ++ public Class getTaskClass() { // Paper + return (this.rTask != null) ? this.rTask.getClass() : ((this.cTask != null) ? this.cTask.getClass() : null); } @@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot @@ -2199,7 +2195,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - // Spigot start - public String getTaskName() { -- return (getTaskClass() == null) ? "Unknown" : getTaskClass().getName(); +- return (this.getTaskClass() == null) ? "Unknown" : this.getTaskClass().getName(); - } - // Spigot end } @@ -2230,7 +2226,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end - public static byte toLegacyData(IBlockData data) { + public static byte toLegacyData(BlockState data) { return CraftLegacy.toLegacyData(data); @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { return clazz; @@ -2250,10 +2246,10 @@ diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org 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; +@@ -0,0 +0,0 @@ import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.entity.raid.Raider; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.AABB; -import org.bukkit.craftbukkit.SpigotTimings; +import co.aikar.timings.MinecraftTimings; @@ -2272,7 +2268,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) @@ -0,0 +0,0 @@ public class ActivationRange */ - public static void activateEntities(World world) + public static void activateEntities(Level world) { - SpigotTimings.entityActivationCheckTimer.startTiming(); + MinecraftTimings.entityActivationCheckTimer.startTiming(); @@ -2280,8 +2276,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 final int raiderActivationRange = world.spigotConfig.raiderActivationRange; final int animalActivationRange = world.spigotConfig.animalActivationRange; @@ -0,0 +0,0 @@ public class ActivationRange - } - } + + world.getEntities().get(maxBB, ActivationRange::activateEntity); } - SpigotTimings.entityActivationCheckTimer.stopTiming(); + MinecraftTimings.entityActivationCheckTimer.stopTiming(); @@ -2294,7 +2290,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 { - SpigotTimings.checkIfActiveTimer.startTiming(); // Never safe to skip fireworks or entities not yet added to chunk - if ( !entity.inChunk || entity instanceof EntityFireworks ) { + if ( entity instanceof FireworkRocketEntity ) { - SpigotTimings.checkIfActiveTimer.stopTiming(); return true; } diff --git a/Spigot-Server-Patches/Toggle-for-removing-existing-dragon.patch b/patches/server/Toggle-for-removing-existing-dragon.patch similarity index 58% rename from Spigot-Server-Patches/Toggle-for-removing-existing-dragon.patch rename to patches/server/Toggle-for-removing-existing-dragon.patch index 36919d8300..f1373df509 100644 --- a/Spigot-Server-Patches/Toggle-for-removing-existing-dragon.patch +++ b/patches/server/Toggle-for-removing-existing-dragon.patch @@ -9,10 +9,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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); @@ -20,17 +19,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 ++ + public short keepLoadedRange; + private void keepLoadedRange() { + keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); +diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.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); +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -0,0 +0,0 @@ public class EndDragonFight { + this.dragonUUID = enderDragon.getUUID(); + LOGGER.info("Found that there's a dragon still alive ({})", (Object)enderDragon); 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(); +- if (!bl) { ++ if (!bl && this.level.paperConfig.shouldRemoveDragon) { + LOGGER.info("But we didn't have a portal, let's remove it."); + enderDragon.discard(); this.dragonUUID = null; diff --git a/Spigot-Server-Patches/Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server/Toggleable-player-crits-helps-mitigate-hacked-client.patch similarity index 70% rename from Spigot-Server-Patches/Toggleable-player-crits-helps-mitigate-hacked-client.patch rename to patches/server/Toggleable-player-crits-helps-mitigate-hacked-client.patch index 16884a84bc..cffd24ee4f 100644 --- a/Spigot-Server-Patches/Toggleable-player-crits-helps-mitigate-hacked-client.patch +++ b/patches/server/Toggleable-player-crits-helps-mitigate-hacked-client.patch @@ -20,15 +20,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.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 { +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { - boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.isClimbing() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && entity instanceof EntityLiving; + boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity; -+ flag2 = flag2 && !world.paperConfig.disablePlayerCrits; // Paper ++ flag2 = flag2 && !level.paperConfig.disablePlayerCrits; // Paper flag2 = flag2 && !this.isSprinting(); if (flag2) { f *= 1.5F; diff --git a/Spigot-Server-Patches/Tracking-Range-Improvements.patch b/patches/server/Tracking-Range-Improvements.patch similarity index 64% rename from Spigot-Server-Patches/Tracking-Range-Improvements.patch rename to patches/server/Tracking-Range-Improvements.patch index 280370212c..55d5e8e25b 100644 --- a/Spigot-Server-Patches/Tracking-Range-Improvements.patch +++ b/patches/server/Tracking-Range-Improvements.patch @@ -7,14 +7,14 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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 { +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially while (iterator.hasNext()) { Entity entity = (Entity) iterator.next(); - int j = entity.getEntityType().getChunkRange() * 16; + int j = entity.getType().clientTrackingRange() * 16; + j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper if (j > i) { @@ -23,14 +23,22 @@ diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/s index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/spigotmc/TrackingRange.java +++ b/src/main/java/org/spigotmc/TrackingRange.java +@@ -0,0 +0,0 @@ import net.minecraft.world.entity.ExperienceOrb; + import net.minecraft.world.entity.decoration.ItemFrame; + import net.minecraft.world.entity.decoration.Painting; + import net.minecraft.world.entity.item.ItemEntity; +-import net.minecraft.world.entity.monster.Ghast; + + public class TrackingRange + { @@ -0,0 +0,0 @@ public class TrackingRange - if ( entity instanceof EntityPlayer ) + if ( entity instanceof ServerPlayer ) { return config.playerTrackingRange; - } else if ( entity.activationType == ActivationRange.ActivationType.MONSTER || entity.activationType == ActivationRange.ActivationType.RAIDER ) - { - return config.monsterTrackingRange; -- } else if ( entity instanceof EntityGhast ) +- } else if ( entity instanceof Ghast ) - { - if ( config.monsterTrackingRange > config.monsterActivationRange ) - { @@ -48,20 +56,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - } else if ( entity.activationType == ActivationRange.ActivationType.ANIMAL ) - { - return config.animalTrackingRange; -- } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) +- } else if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) + case WATER: + case VILLAGER: + case ANIMAL: + return config.animalTrackingRange; + case MISC: + } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) ++ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) + // 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 ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt return config.otherTrackingRange; } } diff --git a/patches/server/Turtle-API.patch b/patches/server/Turtle-API.patch new file mode 100644 index 0000000000..1f3622f2e5 --- /dev/null +++ b/patches/server/Turtle-API.patch @@ -0,0 +1,111 @@ +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/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal { + protected int nextStartTick; + protected int tryTicks; + private int maxStayTicks; +- protected BlockPos blockPos = BlockPos.ZERO; ++ protected BlockPos blockPos = BlockPos.ZERO; @Deprecated public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER + private boolean reachedTarget; + private final int searchRange; + private final int verticalSearchRange; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java +@@ -0,0 +0,0 @@ import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.server.MCUtil; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; +@@ -0,0 +0,0 @@ public class Turtle extends Animal { + this.entityData.set(Turtle.HOME_POS, pos); + } + +- BlockPos getHomePos() { ++ public BlockPos getHomePos() { // Paper - public + return (BlockPos) this.entityData.get(Turtle.HOME_POS); + } + +@@ -0,0 +0,0 @@ public class Turtle extends Animal { + + if (!this.turtle.isInWater() && this.isReachedTarget()) { + if (this.turtle.layEggCounter < 1) { +- this.turtle.setLayingEgg(true); ++ this.turtle.setLayingEgg(new com.destroystokyo.paper.event.entity.TurtleStartDiggingEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.getTargetPosition())).callEvent()); // Paper + } else if (this.turtle.layEggCounter > 200) { + Level world = this.turtle.level; + + // CraftBukkit start +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1)).isCancelled()) { ++ // Paper start ++ int eggCount = this.turtle.random.nextInt(4) + 1; ++ com.destroystokyo.paper.event.entity.TurtleLayEggEvent layEggEvent = new com.destroystokyo.paper.event.entity.TurtleLayEggEvent((org.bukkit.entity.Turtle) this.turtle.getBukkitEntity(), MCUtil.toLocation(this.turtle.level, this.blockPos.above()), eggCount); ++ if (layEggEvent.callEvent() && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this.turtle, this.blockPos.above(), Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount())).isCancelled()) { + world.playSound((Player) null, blockposition, SoundEvents.TURTLE_LAY_EGG, SoundSource.BLOCKS, 0.3F, 0.9F + world.random.nextFloat() * 0.2F); +- world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, this.turtle.random.nextInt(4) + 1), 3); ++ world.setBlock(this.blockPos.above(), (BlockState) Blocks.TURTLE_EGG.defaultBlockState().setValue(TurtleEggBlock.EGGS, layEggEvent.getEggCount()), 3); + } + // CraftBukkit end + this.turtle.setHasEgg(false); +@@ -0,0 +0,0 @@ public class Turtle extends Animal { + + @Override + public boolean canUse() { +- return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))); ++ return this.turtle.isBaby() ? false : (this.turtle.hasEgg() ? true : (this.turtle.getRandom().nextInt(700) != 0 ? false : !this.turtle.getHomePos().closerThan((Position) this.turtle.position(), 64.0D))) && new com.destroystokyo.paper.event.entity.TurtleGoHomeEvent((org.bukkit.entity.Turtle) this.turtle.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().level, 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().isLayingEgg(); ++ } ++ ++ @Override ++ public boolean hasEgg() { ++ return getHandle().hasEgg(); ++ } ++ ++ @Override ++ public void setHasEgg(boolean hasEgg) { ++ getHandle().setHasEgg(hasEgg); ++ } ++ // Paper end + } diff --git a/patches/server/Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server/Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch new file mode 100644 index 0000000000..9e2b2334bd --- /dev/null +++ b/patches/server/Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch @@ -0,0 +1,19 @@ +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/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -0,0 +0,0 @@ public class Creeper extends Monster implements PowerableMob { + this.spawnLingeringCloud(); + } else { + this.swell = 0; ++ this.entityData.set(DATA_IS_IGNITED, Boolean.valueOf(false)); // Paper + } + // CraftBukkit end + } diff --git a/patches/server/Update-entity-Metadata-for-all-tracked-players.patch b/patches/server/Update-entity-Metadata-for-all-tracked-players.patch new file mode 100644 index 0000000000..b1d07c2080 --- /dev/null +++ b/patches/server/Update-entity-Metadata-for-all-tracked-players.patch @@ -0,0 +1,43 @@ +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/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntity.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntity.java +@@ -0,0 +0,0 @@ public class ServerEntity { + return ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp); + } + ++ // Paper start - Add broadcast method ++ void broadcast(Packet packet) { ++ this.broadcast.accept(packet); ++ } ++ // Paper end ++ + private void broadcastAndSend(Packet packet) { + this.broadcast.accept(packet); + if (this.entity instanceof ServerPlayer) { +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + if (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem) { + // Refresh the current entity metadata +- ServerGamePacketListenerImpl.this.send(new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true)); ++ // Paper start - update entity for all players ++ ClientboundSetEntityDataPacket packet1 = new ClientboundSetEntityDataPacket(entity.getId(), entity.getEntityData(), true); ++ if (entity.tracker != null) { ++ entity.tracker.broadcast(packet1); ++ } else { ++ ServerGamePacketListenerImpl.this.send(packet1); ++ } ++ // Paper end + } + + if (event.isCancelled()) { diff --git a/patches/server/Update-itemstack-legacy-name-and-lore.patch b/patches/server/Update-itemstack-legacy-name-and-lore.patch new file mode 100644 index 0000000000..53c5ba5f07 --- /dev/null +++ b/patches/server/Update-itemstack-legacy-name-and-lore.patch @@ -0,0 +1,63 @@ +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 @@ public final class ItemStack { + list.sort((Comparator) enchantSorter); // Paper + } catch (Exception ignored) {} + } ++ ++ private void processText() { ++ CompoundTag display = getTagElement("display"); ++ if (display != null) { ++ if (display.contains("Name", 8)) { ++ String json = display.getString("Name"); ++ if (json != null && json.contains("\u00A7")) { ++ try { ++ display.put("Name", convert(json)); ++ } catch (JsonParseException jsonparseexception) { ++ display.remove("Name"); ++ } ++ } ++ } ++ if (display.contains("Lore", 9)) { ++ ListTag 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, net.minecraft.nbt.StringTag.valueOf(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(new TextComponent("")))); ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ private net.minecraft.nbt.StringTag convert(String json) { ++ Component component = Component.Serializer.fromJson(json); ++ if (component instanceof TextComponent && component.getContents().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.getContents())[0]; ++ } ++ return net.minecraft.nbt.StringTag.valueOf(org.bukkit.craftbukkit.util.CraftChatMessage.toJSON(component)); ++ } + // Paper end + + public ItemStack(ItemLike item) { +@@ -0,0 +0,0 @@ public final class ItemStack { + this.tag = (CompoundTag) nbttagcompound.getCompound("tag").copy(); + // CraftBukkit end + this.processEnchantOrder(this.tag); // Paper ++ this.processText(); // Paper + this.getItem().verifyTagAfterLoad(this.tag); + } + diff --git a/patches/server/Update-oshi-core-dependency.patch b/patches/server/Update-oshi-core-dependency.patch new file mode 100644 index 0000000000..ae86648ec6 --- /dev/null +++ b/patches/server/Update-oshi-core-dependency.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Nassim Jahnke +Date: Sat, 19 Jun 2021 09:55:41 +0200 +Subject: [PATCH] Update oshi-core dependency + +This is fixed in Vanilla 1.17.1, so remove this patch when updating. + +diff --git a/build.gradle.kts b/build.gradle.kts +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + implementation("co.aikar:cleaner:1.0-SNAPSHOT") // Paper + implementation("io.netty:netty-all:4.1.65.Final") // Paper + ++ implementation("com.github.oshi:oshi-core:5.7.5") // Paper - fix startup delay and warning ++ + testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test + testImplementation("junit:junit:4.13.1") + testImplementation("org.hamcrest:hamcrest-library:1.3") diff --git a/Spigot-Server-Patches/Use-ConcurrentHashMap-in-JsonList.patch b/patches/server/Use-ConcurrentHashMap-in-JsonList.patch similarity index 54% rename from Spigot-Server-Patches/Use-ConcurrentHashMap-in-JsonList.patch rename to patches/server/Use-ConcurrentHashMap-in-JsonList.patch index 675c2f0006..33c5c83701 100644 --- a/Spigot-Server-Patches/Use-ConcurrentHashMap-in-JsonList.patch +++ b/patches/server/Use-ConcurrentHashMap-in-JsonList.patch @@ -22,12 +22,23 @@ 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 +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/JsonList.java -+++ b/src/main/java/net/minecraft/server/players/JsonList.java +--- 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 (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) { ++ } else if (this.getIpBans().isBanned(socketaddress) && getIpBans().get(socketaddress) != null && !this.getIpBans().get(socketaddress).hasExpired()) { // Paper - fix NPE with temp ip bans + IpBanListEntry ipbanentry = this.ipBans.get(socketaddress); + + chatmessage = new TranslatableComponent("multiplayer.disconnect.banned_ip.reason", new Object[]{ipbanentry.getReason()}); +diff --git a/src/main/java/net/minecraft/server/players/StoredUserList.java b/src/main/java/net/minecraft/server/players/StoredUserList.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/players/StoredUserList.java ++++ b/src/main/java/net/minecraft/server/players/StoredUserList.java @@ -0,0 +0,0 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; @@ -37,17 +48,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.Iterator; -@@ -0,0 +0,0 @@ public abstract class JsonList> { +@@ -0,0 +0,0 @@ public abstract class StoredUserList> { 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(); + private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create(); + private final File file; +- private final Map map = Maps.newHashMap(); + // Paper - replace HashMap is ConcurrentHashMap -+ private final Map d = Maps.newConcurrentMap(); private final Map getBackingMap() { return this.d; } // Paper - OBFHELPER ++ private final Map map = Maps.newConcurrentMap(); + private boolean e = true; + private static final ParameterizedType f = new ParameterizedType() { + public Type[] getActualTypeArguments() { -+ return new Type[]{JsonListEntry.class}; ++ return new Type[]{StoredUserEntry.class}; + } + + public Type getRawType() { @@ -59,78 +70,71 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }; - public JsonList(File file) { - this.c = file; -@@ -0,0 +0,0 @@ public abstract class JsonList> { + public StoredUserList(File file) { + this.file = file; +@@ -0,0 +0,0 @@ public abstract class StoredUserList> { @Nullable - public V get(K k0) { -- this.g(); -- return (V) this.d.get(this.a(k0)); // CraftBukkit - fix decompile error + public V get(K key) { +- this.removeExpired(); +- return (V) this.map.get(this.getKeyForUser(key)); // 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) this.map.computeIfPresent(this.getKeyForUser(key), (k, v) -> { + return v.hasExpired() ? null : v; + }); + // Paper end } - public void remove(K k0) { -@@ -0,0 +0,0 @@ public abstract class JsonList> { + public void remove(K key) { +@@ -0,0 +0,0 @@ public abstract class StoredUserList> { // CraftBukkit end public boolean isEmpty() { -- return this.d.size() < 1; +- return this.map.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 ++ return this.map.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)); + protected String getKeyForUser(K profile) { +@@ -0,0 +0,0 @@ public abstract class StoredUserList> { } -+ private void removeStaleEntries() { g(); } // Paper - OBFHELPER - private void g() { + private void removeExpired() { - List list = Lists.newArrayList(); +- Iterator iterator = this.map.values().iterator(); + /*List list = Lists.newArrayList(); - Iterator iterator = this.d.values().iterator(); ++ Iterator iterator = this.d.values().iterator(); while (iterator.hasNext()) { -@@ -0,0 +0,0 @@ public abstract class JsonList> { + V v0 = (V) iterator.next(); // CraftBukkit - decompile error + + if (v0.hasExpired()) { +- list.add(v0.getUser()); ++ list.add(v0.getKey()); + } + } + +@@ -0,0 +0,0 @@ public abstract class StoredUserList> { + while (iterator.hasNext()) { K k0 = (K) iterator.next(); // CraftBukkit - decompile error - this.d.remove(this.a(k0)); +- this.map.remove(this.getKeyForUser(k0)); - } ++ this.d.remove(this.a(k0)); + }*/ -+ this.getBackingMap().values().removeIf(JsonListEntry::hasExpired); ++ this.map.values().removeIf(StoredUserEntry::hasExpired); + // Paper end } - protected abstract JsonListEntry a(JsonObject jsonobject); -@@ -0,0 +0,0 @@ public abstract class JsonList> { + protected abstract StoredUserEntry createEntry(JsonObject json); +@@ -0,0 +0,0 @@ public abstract class StoredUserList> { } public void save() throws IOException { -+ this.removeStaleEntries(); // Paper - remove expired values before saving ++ this.removeExpired(); // 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()}); + Stream stream = this.map.values().stream().map((jsonlistentry) -> { // CraftBukkit - decompile error + JsonObject jsonobject = new JsonObject(); diff --git a/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch similarity index 82% rename from Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch rename to patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch index 029125f61a..dbf4730264 100644 --- a/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/Use-TerminalConsoleAppender-for-console-improvements.patch @@ -18,60 +18,29 @@ Other changes: - Server starts 1-2 seconds faster thanks to optimizations in Log4j configuration -diff --git a/pom.xml b/pom.xml +diff --git a/build.gradle.kts b/build.gradle.kts 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 ++ */ ++ runtimeOnly("org.apache.logging.log4j:log4j-core:2.14.1") ++ // Paper end + implementation("org.apache.logging.log4j:log4j-iostreams:2.14.1") // Paper + implementation("org.apache.logging.log4j:log4j-api:2.14.1") // Paper + implementation("org.ow2.asm:asm:9.1") 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 @@ -110,12 +79,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + protected void runCommand(String command) { -+ this.server.issueCommand(command, this.server.getServerCommandListener()); ++ this.server.handleConsoleInput(command, this.server.createCommandSourceStack()); + } + + @Override + protected void shutdown() { -+ this.server.safeShutdown(false); ++ this.server.halt(false); + } + +} @@ -152,8 +121,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.PaperAdventure; // Paper import it.unimi.dsi.fastutil.longs.LongIterator; + import java.awt.GraphicsEnvironment; 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; @@ -161,9 +130,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 -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 0) { // Trim to filter lines which are just spaces +- DedicatedServer.this.handleConsoleInput(s, DedicatedServer.this.createCommandSourceStack()); ++ DedicatedServer.this.issueCommand(s, DedicatedServer.this.getServerCommandListener()); + } + // CraftBukkit end + } +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface DedicatedServer.LOGGER.error("Exception handling console input", ioexception); } @@ -232,7 +210,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } }; -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } global.addHandler(new org.bukkit.craftbukkit.util.ForwardLogHandler()); @@ -242,7 +220,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 final org.apache.logging.log4j.core.Logger logger = ((org.apache.logging.log4j.core.Logger) LogManager.getRootLogger()); for (org.apache.logging.log4j.core.Appender appender : logger.getAppenders().values()) { if (appender instanceof org.apache.logging.log4j.core.appender.ConsoleAppender) { -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } new org.bukkit.craftbukkit.util.TerminalConsoleWriterThread(System.out, this.reader).start(); @@ -257,14 +235,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -0,0 +0,0 @@ public abstract class PlayerList { - public PlayerList(MinecraftServer minecraftserver, IRegistryCustom.Dimension iregistrycustom_dimension, WorldNBTStorage worldnbtstorage, int i) { - this.cserver = minecraftserver.server = new CraftServer((DedicatedServer) minecraftserver, this); -- minecraftserver.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); -- minecraftserver.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(minecraftserver.server)); -+ minecraftserver.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper + public PlayerList(MinecraftServer server, RegistryAccess.RegistryHolder registryManager, PlayerDataStorage saveHandler, int maxPlayers) { + this.cserver = server.server = new CraftServer((DedicatedServer) server, this); +- server.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance(); +- server.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(server.server)); ++ server.console = new com.destroystokyo.paper.console.TerminalConsoleCommandSender(); // Paper // CraftBukkit end - this.k = new GameProfileBanList(PlayerList.b); + this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); 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 @@ -275,18 +253,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import javax.imageio.ImageIO; -import jline.console.ConsoleReader; import net.minecraft.advancements.Advancement; - import net.minecraft.commands.CommandDispatcher; - import net.minecraft.commands.CommandListenerWrapper; -@@ -0,0 +0,0 @@ import net.minecraft.nbt.NBTBase; - import net.minecraft.resources.MinecraftKey; - import net.minecraft.resources.RegistryReadOps; + import net.minecraft.commands.CommandSourceStack; + import net.minecraft.commands.Commands; +@@ -0,0 +0,0 @@ import net.minecraft.resources.RegistryReadOps; import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.ConsoleInput; +//import jline.console.ConsoleReader; // Paper import net.minecraft.server.MinecraftServer; - import net.minecraft.server.ServerCommand; - import net.minecraft.server.bossevents.BossBattleCustom; + import net.minecraft.server.bossevents.CustomBossEvent; + import net.minecraft.server.commands.ReloadCommand; @@ -0,0 +0,0 @@ public final class CraftServer implements Server { - return logger; + return this.logger; } + // Paper start - JLine update @@ -334,12 +312,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end if (options.has("noconsole")) { - useConsole = false; + Main.useConsole = false; + useJline = false; // Paper + System.setProperty(TerminalConsoleAppender.JLINE_OVERRIDE_PROPERTY, "false"); // Paper } - if (false && Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { + if (Main.class.getPackage().getImplementationVendor() != null && System.getProperty("IReallyKnowWhatIAmDoingISwear") == null) { @@ -0,0 +0,0 @@ public class Main { System.out.println("Unable to read system info"); } @@ -418,7 +396,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Waitable> waitable = new Waitable>() { @Override protected List evaluate() { -@@ -0,0 +0,0 @@ public class ConsoleCommandCompleter implements Completer { +- List offers = ConsoleCommandCompleter.this.server.getCommandMap().tabComplete(ConsoleCommandCompleter.this.server.getConsoleSender(), buffer); ++ List offers = server.getCommandMap().tabComplete(server.getConsoleSender(), buffer); // Paper - fix remap + +- TabCompleteEvent tabEvent = new TabCompleteEvent(ConsoleCommandCompleter.this.server.getConsoleSender(), buffer, (offers == null) ? Collections.EMPTY_LIST : offers); +- ConsoleCommandCompleter.this.server.getPluginManager().callEvent(tabEvent); ++ TabCompleteEvent tabEvent = new TabCompleteEvent(server.getConsoleSender(), buffer, (offers == null) ? Collections.EMPTY_LIST : offers); // Paper - fix remap ++ server.getPluginManager().callEvent(tabEvent); // Paper - fix remap + return tabEvent.isCancelled() ? Collections.EMPTY_LIST : tabEvent.getCompletions(); } }; @@ -466,7 +451,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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(); + this.server.close(); } finally { try { - server.reader.getTerminal().restore(); diff --git a/Spigot-Server-Patches/Use-UserCache-for-player-heads.patch b/patches/server/Use-UserCache-for-player-heads.patch similarity index 72% rename from Spigot-Server-Patches/Use-UserCache-for-player-heads.patch rename to patches/server/Use-UserCache-for-player-heads.patch index 4fa377ff8f..3f82c823a8 100644 --- a/Spigot-Server-Patches/Use-UserCache-for-player-heads.patch +++ b/patches/server/Use-UserCache-for-player-heads.patch @@ -10,15 +10,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + this.setProfile(null); } else { -- setProfile(new GameProfile(null, name)); +- this.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(); ++ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(name); ++ if (player != null) newProfile = player.getGameProfile(); + if (newProfile == null) newProfile = new GameProfile(null, name); -+ setProfile(newProfile); ++ this.setProfile(newProfile); + // Paper end } diff --git a/Spigot-Server-Patches/Use-Vanilla-Minecart-Speeds.patch b/patches/server/Use-Vanilla-Minecart-Speeds.patch similarity index 68% rename from Spigot-Server-Patches/Use-Vanilla-Minecart-Speeds.patch rename to patches/server/Use-Vanilla-Minecart-Speeds.patch index 303baa58c3..a4f56cd66a 100644 --- a/Spigot-Server-Patches/Use-Vanilla-Minecart-Speeds.patch +++ b/patches/server/Use-Vanilla-Minecart-Speeds.patch @@ -5,11 +5,11 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.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 { +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +@@ -0,0 +0,0 @@ public abstract class AbstractMinecart extends Entity { private double derailedX = 0.5; private double derailedY = 0.5; private double derailedZ = 0.5; diff --git a/patches/server/Use-a-Queue-for-Queueing-Commands.patch b/patches/server/Use-a-Queue-for-Queueing-Commands.patch new file mode 100644 index 0000000000..7aa41a394d --- /dev/null +++ b/patches/server/Use-a-Queue-for-Queueing-Commands.patch @@ -0,0 +1,39 @@ +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 ServerInterface + private static final int CONVERSION_RETRY_DELAY_MS = 5000; + private static final int CONVERSION_RETRIES = 2; + private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$"); +- private final List consoleInput = Collections.synchronizedList(Lists.newArrayList()); ++ private final java.util.Queue serverCommandQueue = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - use a proper queue + private QueryThreadGs4 queryThreadGs4; + public final RconConsoleSource rconConsoleSource; + private RconThread rconThread; +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } + + public void handleConsoleInput(String command, CommandSourceStack commandSource) { +- this.consoleInput.add(new ConsoleInput(command, commandSource)); ++ this.serverCommandQueue.add(new ConsoleInput(command, commandSource)); + } + + public void handleConsoleInputs() { + MinecraftTimings.serverCommandTimer.startTiming(); // Spigot +- while (!this.consoleInput.isEmpty()) { +- ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); ++ // Paper start - use proper queue ++ ConsoleInput servercommand; ++ while ((servercommand = this.serverCommandQueue.poll()) != null) { ++ // Paper end + + // CraftBukkit start - ServerCommand for preprocessing + ServerCommandEvent event = new ServerCommandEvent(console, servercommand.msg); diff --git a/patches/server/Use-a-Shared-Random-for-Entities.patch b/patches/server/Use-a-Shared-Random-for-Entities.patch new file mode 100644 index 0000000000..f5ed6f69a2 --- /dev/null +++ b/patches/server/Use-a-Shared-Random-for-Entities.patch @@ -0,0 +1,55 @@ +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 Nameable, EntityAccess, CommandSource, n + return tag.contains("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 Nameable, EntityAccess, CommandSource, n + this.bb = Entity.INITIAL_AABB; + this.stuckSpeedMultiplier = Vec3.ZERO; + this.nextStep = 1.0F; +- this.random = new Random(); ++ this.random = SHARED_RANDOM; // Paper + this.remainingFireTicks = -this.getFireImmuneTicks(); + this.fluidHeight = new Object2DoubleArrayMap(2); + this.firstTick = true; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -0,0 +0,0 @@ public class Squid extends WaterAnimal { + + public Squid(EntityType type, Level world) { + super(type, world); +- this.random.setSeed((long) this.getId()); ++ //this.random.setSeed((long) this.getId()); // Paper - we set the random to shared, do not clobber the seed + this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; + } + diff --git a/Spigot-Server-Patches/Use-asynchronous-Log4j-2-loggers.patch b/patches/server/Use-asynchronous-Log4j-2-loggers.patch similarity index 75% rename from Spigot-Server-Patches/Use-asynchronous-Log4j-2-loggers.patch rename to patches/server/Use-asynchronous-Log4j-2-loggers.patch index 56d85b045d..2e4b7dd4b4 100644 --- a/Spigot-Server-Patches/Use-asynchronous-Log4j-2-loggers.patch +++ b/patches/server/Use-asynchronous-Log4j-2-loggers.patch @@ -4,24 +4,18 @@ Date: Tue, 17 Jul 2018 16:42:17 +0200 Subject: [PATCH] Use asynchronous Log4j 2 loggers -diff --git a/pom.xml b/pom.xml +diff --git a/build.gradle.kts b/build.gradle.kts 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 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -0,0 +0,0 @@ dependencies { + } + runtimeOnly("org.xerial:sqlite-jdbc:3.34.0") + runtimeOnly("mysql:mysql-connector-java:8.0.23") // Paper ++ runtimeOnly("com.lmax:disruptor:3.4.2") // Paper + + runtimeOnly("org.apache.maven:maven-resolver-provider:3.8.1") + runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.0") 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 diff --git a/Spigot-Server-Patches/Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/Use-distance-map-to-optimise-entity-tracker.patch similarity index 55% rename from Spigot-Server-Patches/Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/Use-distance-map-to-optimise-entity-tracker.patch index cb657d3f50..5b77fa2478 100644 --- a/Spigot-Server-Patches/Use-distance-map-to-optimise-entity-tracker.patch +++ b/patches/server/Use-distance-map-to-optimise-entity-tracker.patch @@ -5,46 +5,22 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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; +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; + import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; + import net.minecraft.network.protocol.game.DebugPackets; 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<>(); + import net.minecraft.server.level.progress.ChunkProgressListener; + import net.minecraft.server.network.ServerPlayerConnection; + import net.minecraft.util.CsvOutput; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceTickMap; + public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerViewDistanceNoTickMap; + // Paper end - no-tick view distance + // Paper start - use distance map to optimise tracker + public static boolean isLegacyTrackingEntity(Entity entity) { + return entity.isLegacyTrackingEntity; @@ -56,13 +32,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final int[] entityTrackerTrackRanges; + + private int convertSpigotRangeToVanilla(final int vanilla) { -+ return MinecraftServer.getServer().applyTrackingRangeScale(vanilla); ++ return MinecraftServer.getServer().getScaledTrackingDistance(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()); + void addPlayerToDistanceMaps(ServerPlayer player) { + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); // 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) { @@ -72,20 +48,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, this.getEffectiveViewDistance())); + } + // Paper end - use distance map to optimise entity tracker + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - void removePlayerFromDistanceMaps(EntityPlayer player) { + void removePlayerFromDistanceMaps(ServerPlayer 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()); + // Paper start - no-tick view distance + this.playerViewDistanceBroadcastMap.remove(player); + this.playerViewDistanceTickMap.remove(player); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); // 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) { @@ -95,18 +76,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); + this.playerMobDistanceMap = this.level.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; ++ org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.level.spigotConfig; + + for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { + org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; @@ -128,7 +109,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + configuredSpigotValue = spigotWorldConfig.otherTrackingRange; + break; + case ENDERDRAGON: -+ configuredSpigotValue = EntityTypes.ENDER_DRAGON.getChunkRange() * 16; ++ configuredSpigotValue = EntityType.ENDER_DRAGON.clientTrackingRange() * 16; + break; + default: + throw new IllegalStateException("Missing case for enum " + trackingRangeType); @@ -141,105 +122,105 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); + } + // Paper end - use distance map to optimise entity tracker + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - 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(); + public void move(ServerPlayer player) { +- ObjectIterator objectiterator = this.entityMap.values().iterator(); - - while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); +- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); - -- if (playerchunkmap_entitytracker.tracker == entityplayer) { -- playerchunkmap_entitytracker.track(this.world.getPlayers()); +- if (playerchunkmap_entitytracker.entity == player) { +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); - } else { -- playerchunkmap_entitytracker.updatePlayer(entityplayer); +- playerchunkmap_entitytracker.updatePlayer(player); - } - } + // 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 { + int i = SectionPos.blockToSectionCoord(player.getBlockX()); + int j = SectionPos.blockToSectionCoord(player.getBlockZ()); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - 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; + entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker + this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); ++ playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players + if (entity instanceof ServerPlayer) { + ServerPlayer entityplayer = (ServerPlayer) entity; -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider entity.tracker = null; // Paper - We're no longer tracked } + // Paper start - optimised tracker + private final void processTrackQueue() { -+ this.world.timings.tracker1.startTiming(); ++ this.level.timings.tracker1.startTiming(); + try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { ++ for (TrackedEntity tracker : this.entityMap.values()) { + // update tracker entry -+ tracker.updatePlayers(tracker.tracker.getPlayersInTrackRange()); ++ tracker.updatePlayers(tracker.entity.getPlayersInTrackRange()); + } + } finally { -+ this.world.timings.tracker1.stopTiming(); ++ this.level.timings.tracker1.stopTiming(); + } + + -+ this.world.timings.tracker2.startTiming(); ++ this.level.timings.tracker2.startTiming(); + try { -+ for (EntityTracker tracker : this.trackedEntities.values()) { -+ tracker.trackerEntry.tick(); ++ for (TrackedEntity tracker : this.entityMap.values()) { ++ tracker.serverEntity.sendChanges(); + } + } finally { -+ this.world.timings.tracker2.stopTiming(); ++ this.level.timings.tracker2.stopTiming(); + } + } + // Paper end - optimised tracker + - protected void g() { + protected void tick() { + // Paper start - optimized tracker + if (true) { + this.processTrackQueue(); + return; + } + // Paper end - optimized tracker - List list = Lists.newArrayList(); - List list1 = this.world.getPlayers(); + List list = Lists.newArrayList(); + List list1 = this.level.players(); -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - PacketDebug.a(this.world, chunk.getPos()); +@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); List list = Lists.newArrayList(); List list1 = Lists.newArrayList(); -- ObjectIterator objectiterator = this.trackedEntities.values().iterator(); +- ObjectIterator objectiterator = this.entityMap.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) { ++ if (entity == player) { + continue; + } -+ PlayerChunkMap.EntityTracker tracker = this.trackedEntities.get(entity.getId()); ++ ChunkMap.TrackedEntity tracker = this.entityMap.get(entity.getId()); + if (tracker != null) { // dumb plugins... move on... -+ tracker.updatePlayer(entityplayer); ++ tracker.updatePlayer(player); + } - while (objectiterator.hasNext()) { -- PlayerChunkMap.EntityTracker playerchunkmap_entitytracker = (PlayerChunkMap.EntityTracker) objectiterator.next(); -- Entity entity = playerchunkmap_entitytracker.tracker; +- ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); +- Entity entity = playerchunkmap_entitytracker.entity; + // 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) { +- if (entity != player && entity.chunkPosition().equals(chunk.getPos())) { +- playerchunkmap_entitytracker.updatePlayer(player); +- if (entity instanceof Mob && ((Mob) entity).getLeashHolder() != null) { - list.add(entity); - } -+ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).getLeashHolder() != null) { ++ if (entity instanceof Mob && ((Mob)entity).getLeashHolder() != null) { + list.add(entity); + } @@ -254,34 +235,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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); +@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + this.lastSectionPos = SectionPos.of(entity); } + // Paper start - use distance map to optimise tracker -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet lastTrackerCandidates; ++ 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; ++ 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)) { ++ if (!(raw instanceof ServerPlayer)) { + continue; + } -+ EntityPlayer player = (EntityPlayer)raw; ++ ServerPlayer player = (ServerPlayer)raw; + this.updatePlayer(player); + } + } @@ -295,19 +267,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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); ++ for (ServerPlayerConnection conn : this.seenBy.toArray(new ServerPlayerConnection[0])) { // avoid CME ++ if (newTrackerCandidates == null || !newTrackerCandidates.contains(conn)) { ++ this.updatePlayer(conn.getPlayer()); + } + } + } + // 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; + return object instanceof ChunkMap.TrackedEntity ? ((ChunkMap.TrackedEntity) object).entity.getId() == this.entity.getId() : false; } -@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - int j = entity.getEntityType().getChunkRange() * 16; +@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially + int j = entity.getType().clientTrackingRange() * 16; j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper - if (j > i) { @@ -319,15 +291,15 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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; +@@ -0,0 +0,0 @@ import net.minecraft.network.syncher.EntityDataSerializers; + import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceKey; + import net.minecraft.resources.ResourceLocation; +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 + import net.minecraft.server.level.ServerLevel; + import net.minecraft.server.level.ServerPlayer; +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // CraftBukkit end @@ -340,32 +312,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.isLegacyTrackingEntity = isLegacyTrackingEntity; + } + -+ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { -+ return ((WorldServer)this.world).getChunkProvider().playerChunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] ++ public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { ++ return ((ServerLevel)this.level).getChunkSource().chunkMap.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(); + public Entity(EntityType type, Level world) { + this.id = Entity.ENTITY_COUNTER.incrementAndGet(); + this.passengers = ImmutableList.of(); 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 ) + { + return defaultRange; + } ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return defaultRange; // Paper - enderdragon is exempt + SpigotWorldConfig config = entity.level.spigotConfig; + if ( entity instanceof ServerPlayer ) { @@ -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 +- if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return ((net.minecraft.server.level.ServerLevel)(entity.getCommandSenderWorld())).getChunkSource().chunkMap.getLoadViewDistance(); // Paper - enderdragon is exempt return config.otherTrackingRange; } } @@ -374,8 +346,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 ) ++ if (entity instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon) return TrackingRangeType.ENDERDRAGON; // Paper - enderdragon is exempt ++ if ( entity instanceof ServerPlayer ) + { + return TrackingRangeType.PLAYER; + // Paper start - Simplify and set water mobs to animal tracking range @@ -391,7 +363,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return TrackingRangeType.ANIMAL; + case MISC: + } -+ if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) ++ if ( entity instanceof ItemFrame || entity instanceof Painting || entity instanceof ItemEntity || entity instanceof ExperienceOrb ) + // Paper end + { + return TrackingRangeType.MISC; diff --git a/patches/server/Use-proper-max-length-when-serialising-BungeeCord-te.patch b/patches/server/Use-proper-max-length-when-serialising-BungeeCord-te.patch new file mode 100644 index 0000000000..dc7d33890a --- /dev/null +++ b/patches/server/Use-proper-max-length-when-serialising-BungeeCord-te.patch @@ -0,0 +1,32 @@ +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/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java +@@ -0,0 +0,0 @@ import net.minecraft.network.chat.Component; + import net.minecraft.network.protocol.Packet; + + public class ClientboundChatPacket implements Packet { +- ++ private static final int MAX_LENGTH = Short.MAX_VALUE * 8 + 8; // Paper + private final Component message; + 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 ClientboundChatPacket implements Packet { + // buf.writeUtf(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) { +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0])); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components[0]), MAX_LENGTH); // Paper - use proper max length + } else { +- buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components)); ++ buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(this.components), MAX_LENGTH); // Paper - use proper max length + } + // Paper end + } else { diff --git a/patches/server/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch b/patches/server/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch new file mode 100644 index 0000000000..befe2c79c2 --- /dev/null +++ b/patches/server/Use-seed-based-lookup-for-Treasure-Maps-Fixes-lag-fr.patch @@ -0,0 +1,20 @@ +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/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/MapItem.java ++++ b/src/main/java/net/minecraft/world/item/MapItem.java +@@ -0,0 +0,0 @@ public class MapItem extends ComplexItem { + + for (l = 0; l < 128 * i; ++l) { + for (i1 = 0; i1 < 128 * i; ++i1) { +- abiomebase[l * 128 * i + i1] = world.getBiome(new BlockPos((j / i - 64) * i + i1, 0, (k / i - 64) * i + l)); ++ abiomebase[l * 128 * i + i1] = world.getUncachedNoiseBiome((j / i - 64) * i + i1, 0, (k / i - 64) * i + l); // Paper + } + } + diff --git a/patches/server/Validate-PickItem-Packet-and-kick-for-invalid.patch b/patches/server/Validate-PickItem-Packet-and-kick-for-invalid.patch new file mode 100644 index 0000000000..7c700b1639 --- /dev/null +++ b/patches/server/Validate-PickItem-Packet-and-kick-for-invalid.patch @@ -0,0 +1,26 @@ +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + @Override + public void handlePickItem(ServerboundPickItemPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); +- this.player.getInventory().pickSlot(packet.getSlot()); ++ // Paper start - validate pick item position ++ if (!(packet.getSlot() >= 0 && packet.getSlot() < this.player.getInventory().items.size())) { ++ ServerGamePacketListenerImpl.LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); ++ this.disconnect("Invalid hotbar selection (Hacking?)"); ++ return; ++ } ++ this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed ++ // Paper end + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected))); + this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot()))); + this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); diff --git a/patches/server/Validate-tripwire-hook-placement-before-update.patch b/patches/server/Validate-tripwire-hook-placement-before-update.patch new file mode 100644 index 0000000000..a8abbf7d6b --- /dev/null +++ b/patches/server/Validate-tripwire-hook-placement-before-update.patch @@ -0,0 +1,18 @@ +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/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -0,0 +0,0 @@ public class TripWireHookBlock extends Block { + + this.playSound(world, pos, flag4, flag5, flag2, flag3); + if (!beingRemoved) { ++ if (world.getBlockState(pos).getBlock() == Blocks.TRIPWIRE_HOOK) // Paper - validate + world.setBlock(pos, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection), 3); + if (flag1) { + this.notifyNeighbors(world, pos, enumdirection); diff --git a/patches/server/Vanished-players-don-t-have-rights.patch b/patches/server/Vanished-players-don-t-have-rights.patch new file mode 100644 index 0000000000..40aba05c43 --- /dev/null +++ b/patches/server/Vanished-players-don-t-have-rights.patch @@ -0,0 +1,119 @@ +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/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +@@ -0,0 +0,0 @@ public abstract class Projectile extends Entity { + if (!entity.isSpectator() && entity.isAlive() && entity.isPickable()) { + Entity entity1 = this.getOwner(); + ++ // Paper start - Cancel hit for vanished players ++ if (entity1 instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer) { ++ 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.leftOwner || !entity1.isPassengerOfSameVehicle(entity); ++ // Paper end + } else { + return false; + } +diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/BlockItem.java ++++ b/src/main/java/net/minecraft/world/item/BlockItem.java +@@ -0,0 +0,0 @@ public class BlockItem extends Item { + Player entityhuman = context.getPlayer(); + CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of((Entity) entityhuman); + // CraftBukkit start - store default return +- boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision); ++ Level world = context.getLevel(); // Paper ++ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper + org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null; + + BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn); +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.saveddata.maps.MapItemSavedData; + import net.minecraft.world.level.storage.LevelData; + import net.minecraft.world.level.storage.WritableLevelData; + import net.minecraft.world.phys.AABB; ++import net.minecraft.world.phys.shapes.BooleanOp; ++import net.minecraft.world.phys.shapes.CollisionContext; ++import net.minecraft.world.phys.shapes.Shapes; ++import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.scores.Scoreboard; + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime); + } + ++ // Paper start ++ // ret true if no collision ++ public final boolean checkEntityCollision(BlockState data, Entity source, CollisionContext voxelshapedcollision, ++ BlockPos 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.move((double) position.getX(), (double) position.getY(), (double) position.getZ()); ++ if (voxelshape.isEmpty()) { ++ return true; ++ } ++ ++ List entities = this.getEntities(null, voxelshape.bounds()); ++ for (int i = 0, len = entities.size(); i < len; ++i) { ++ Entity entity = entities.get(i); ++ ++ if (checkCanSee && source instanceof net.minecraft.server.level.ServerPlayer && entity instanceof net.minecraft.server.level.ServerPlayer ++ && !((net.minecraft.server.level.ServerPlayer) source).getBukkitEntity().canSee(((net.minecraft.server.level.ServerPlayer) 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.isRemoved() || !entity.blocksBuilding) { ++ continue; ++ } ++ ++ if (Shapes.joinIsNotEmpty(voxelshape, Shapes.create(entity.getBoundingBox()), BooleanOp.AND)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end + @Override + public boolean isClientSide() { + 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 { + 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/patches/server/Vex-get-setSummoner-API.patch similarity index 51% rename from Spigot-Server-Patches/Vex-getSummoner-API.patch rename to patches/server/Vex-get-setSummoner-API.patch index 8e6eba25ae..75e5f3a21d 100644 --- a/Spigot-Server-Patches/Vex-getSummoner-API.patch +++ b/patches/server/Vex-get-setSummoner-API.patch @@ -1,35 +1,32 @@ 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 +Subject: [PATCH] Vex#get/setSummoner API -Get's the NPC that summoned this Vex +Get's the NPC that summoned this Vex and +Allow setting the vex's summoner + +Co-authored-by: BillyGalbreath -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(); + return (net.minecraft.world.entity.monster.Vex) super.getHandle(); } + // Paper start ++ @Override + public org.bukkit.entity.Mob getSummoner() { -+ net.minecraft.world.entity.EntityInsentient owner = getHandle().getOwner(); ++ net.minecraft.world.entity.Mob owner = getHandle().getOwner(); + return owner != null ? (org.bukkit.entity.Mob) owner.getBukkitEntity() : null; + } ++ ++ @Override ++ public void setSummoner(org.bukkit.entity.Mob summoner) { ++ getHandle().setOwner(summoner == null ? null : ((CraftMob) summoner).getHandle()); ++ } + // Paper end + @Override diff --git a/patches/server/Villager-Restocks-API.patch b/patches/server/Villager-Restocks-API.patch new file mode 100644 index 0000000000..c45bd8246e --- /dev/null +++ b/patches/server/Villager-Restocks-API.patch @@ -0,0 +1,29 @@ +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/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 { + this.getHandle().setVillagerXp(experience); + } + ++ // Paper start ++ @Override ++ public int getRestocksToday() { ++ return getHandle().numberOfRestocksToday; ++ } ++ ++ @Override ++ public void setRestocksToday(int restocksToday) { ++ getHandle().numberOfRestocksToday = 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/patches/server/Villager-resetOffers.patch similarity index 54% rename from Spigot-Server-Patches/Villager-resetOffers.patch rename to patches/server/Villager-resetOffers.patch index e9f74fb34f..292d90f3cf 100644 --- a/Spigot-Server-Patches/Villager-resetOffers.patch +++ b/patches/server/Villager-resetOffers.patch @@ -4,39 +4,31 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.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 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -0,0 +0,0 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa return this.tradingPlayer != null; } + // Paper start + public void resetOffers() { -+ this.trades = new MerchantRecipeList(); ++ this.offers = new MerchantOffers(); + 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) { + public MerchantOffers getOffers() { + if (this.offers == null) { 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(); + return this.getMerchant().getTrader(); } + + // Paper start diff --git a/Spigot-Server-Patches/Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/Wait-for-Async-Tasks-during-shutdown.patch similarity index 93% rename from Spigot-Server-Patches/Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/Wait-for-Async-Tasks-during-shutdown.patch index 0a4383c036..3088afdad6 100644 --- a/Spigot-Server-Patches/Wait-for-Async-Tasks-during-shutdown.patch +++ b/patches/server/Wait-for-Async-Tasks-during-shutdown.patch @@ -13,14 +13,14 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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 = PotionUtil.getEffects(itemstack); + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); + if (itemstack.is(Items.POTION)) { +- List list = PotionUtils.getMobEffects(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; ++ List list = event.callEvent() ? PotionUtils.getMobEffects(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion())) : null; + // Paper end if (list != null) { diff --git a/patches/server/WitchReadyPotionEvent.patch b/patches/server/WitchReadyPotionEvent.patch new file mode 100644 index 0000000000..e732db2dea --- /dev/null +++ b/patches/server/WitchReadyPotionEvent.patch @@ -0,0 +1,23 @@ +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/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -0,0 +0,0 @@ public class Witch extends Raider implements RangedAttackMob { + } + + if (potionregistry != null) { +- this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry)); ++ // Paper start ++ ItemStack potion = PotionUtils.setPotion(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.setItemSlot(EquipmentSlot.MAINHAND, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bukkitStack)); ++ // Paper end + this.usingTime = this.getMainHandItem().getUseDuration(); + this.setUsingItem(true); + if (!this.isSilent()) { diff --git a/patches/server/WitchThrowPotionEvent.patch b/patches/server/WitchThrowPotionEvent.patch new file mode 100644 index 0000000000..74fc80827d --- /dev/null +++ b/patches/server/WitchThrowPotionEvent.patch @@ -0,0 +1,30 @@ +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/Witch.java b/src/main/java/net/minecraft/world/entity/monster/Witch.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Witch.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Witch.java +@@ -0,0 +0,0 @@ public class Witch extends Raider implements RangedAttackMob { + potionregistry = Potions.WEAKNESS; + } + ++ // Paper start ++ ItemStack potion = PotionUtils.setPotion(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) target.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potion)); ++ if (!event.callEvent()) { ++ return; ++ } ++ potion = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); + ThrownPotion entitypotion = new ThrownPotion(this.level, this); +- +- entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); ++ entitypotion.setItem(potion); ++ // Paper end + entitypotion.setXRot(entitypotion.getXRot() - -20.0F); + entitypotion.shoot(d0, d1 + d3 * 0.2D, d2, 0.75F, 8.0F); + if (!this.isSilent()) { diff --git a/Spigot-Server-Patches/Workaround-for-setting-passengers-on-players.patch b/patches/server/Workaround-for-setting-passengers-on-players.patch similarity index 86% rename from Spigot-Server-Patches/Workaround-for-setting-passengers-on-players.patch rename to patches/server/Workaround-for-setting-passengers-on-players.patch index 1ff477848c..87510db76c 100644 --- a/Spigot-Server-Patches/Workaround-for-setting-passengers-on-players.patch +++ b/patches/server/Workaround-for-setting-passengers-on-players.patch @@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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())); ++ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSetPassengersPacket(this.getHandle())); + } + return wasSet; + } @@ -26,4 +26,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public void setSneaking(boolean sneak) { - getHandle().setSneaking(sneak); + this.getHandle().setShiftKeyDown(sneak); diff --git a/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/patches/server/Workaround-for-vehicle-tracking-issue-on-disconnect.patch similarity index 59% rename from Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch rename to patches/server/Workaround-for-vehicle-tracking-issue-on-disconnect.patch index ecbdab0838..fac4882100 100644 --- a/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ b/patches/server/Workaround-for-vehicle-tracking-issue-on-disconnect.patch @@ -4,21 +4,21 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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; +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public void disconnect() { + this.disconnected = 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) { ++ if (this.isPassenger() && this.getVehicle() instanceof ServerPlayer) { + this.stopRiding(); + } + // Paper end + if (this.isSleeping()) { - this.wakeup(true, false); + this.stopSleepInBed(true, false); } diff --git a/Spigot-Server-Patches/Zombie-API-breaking-doors.patch b/patches/server/Zombie-API-breaking-doors.patch similarity index 53% rename from Spigot-Server-Patches/Zombie-API-breaking-doors.patch rename to patches/server/Zombie-API-breaking-doors.patch index ac8e982fca..720a6f2832 100644 --- a/Spigot-Server-Patches/Zombie-API-breaking-doors.patch +++ b/patches/server/Zombie-API-breaking-doors.patch @@ -4,23 +4,6 @@ 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 diff --git a/patches/server/add-DragonEggFormEvent.patch b/patches/server/add-DragonEggFormEvent.patch new file mode 100644 index 0000000000..db6e96e172 --- /dev/null +++ b/patches/server/add-DragonEggFormEvent.patch @@ -0,0 +1,36 @@ +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/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java ++++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +@@ -0,0 +0,0 @@ public class EndDragonFight { + this.dragonEvent.setVisible(false); + this.spawnExitPortal(true); + this.spawnNewGateway(); ++ // Paper start - DragonEggFormEvent ++ BlockPos eggPosition = this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION); ++ org.bukkit.craftbukkit.block.CraftBlock eggBlock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, eggPosition); ++ org.bukkit.craftbukkit.block.CraftBlockState eggState = new org.bukkit.craftbukkit.block.CraftBlockState(eggBlock); ++ eggState.setData(Blocks.DRAGON_EGG.defaultBlockState()); ++ io.papermc.paper.event.block.DragonEggFormEvent eggEvent = new io.papermc.paper.event.block.DragonEggFormEvent(eggBlock, eggState, ++ new org.bukkit.craftbukkit.boss.CraftDragonBattle(this)); ++ // Paper end - DragonEggFormEvent + if (this.level.paperConfig.enderDragonsDeathAlwaysPlacesDragonEgg || !this.previouslyKilled) { // Paper - always place dragon egg +- this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); ++ // 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/Spigot-Server-Patches/add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 53% rename from Spigot-Server-Patches/add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/server/add-RespawnFlags-to-PlayerRespawnEvent.patch index b458277981..34ea6c0ada 100644 --- a/Spigot-Server-Patches/add-RespawnFlags-to-PlayerRespawnEvent.patch +++ b/patches/server/add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -4,17 +4,17 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser 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); + if (this.player.wonGame) { + this.player.wonGame = false; +- this.player = this.server.getPlayerList().respawn(this.player, true); ++ this.player = this.server.getPlayerList().moveToWorld(this.player, this.server.getLevel(this.player.getRespawnDimension()), true, null, true, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - add isEndCreditsRespawn argument + CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.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 @@ -22,25 +22,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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) { + public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation) { ++ // Paper start + 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) { ++ public ServerPlayer moveToWorld(ServerPlayer entityplayer, ServerLevel 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 + this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot @@ -0,0 +0,0 @@ public abstract class PlayerList { } - Player respawnPlayer = cserver.getPlayer(entityplayer1); + Player respawnPlayer = this.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); + this.cserver.getPluginManager().callEvent(respawnEvent); // Spigot Start - if (entityplayer.playerConnection.isDisconnected()) { + if (entityplayer.connection.isDisconnected()) { diff --git a/patches/server/add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/server/add-consumeFuel-to-FurnaceBurnEvent.patch new file mode 100644 index 0000000000..a6434c40c9 --- /dev/null +++ b/patches/server/add-consumeFuel-to-FurnaceBurnEvent.patch @@ -0,0 +1,19 @@ +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/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +@@ -0,0 +0,0 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit + if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) { + // CraftBukkit end + flag1 = true; +- if (!itemstack.isEmpty()) { ++ if (!itemstack.isEmpty() && furnaceBurnEvent.willConsumeFuel()) { // Paper + Item item = itemstack.getItem(); + + itemstack.shrink(1); diff --git a/Spigot-Server-Patches/add-get-set-drop-chance-to-EntityEquipment.patch b/patches/server/add-get-set-drop-chance-to-EntityEquipment.patch similarity index 87% rename from Spigot-Server-Patches/add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/server/add-get-set-drop-chance-to-EntityEquipment.patch index 9b432c03f3..a3b38854b9 100644 --- a/Spigot-Server-Patches/add-get-set-drop-chance-to-EntityEquipment.patch +++ b/patches/server/add-get-set-drop-chance-to-EntityEquipment.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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); + this.setDropChance(net.minecraft.world.entity.EquipmentSlot.FEET, chance); } + // Paper start + @Override @@ -24,8 +24,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end - private void setDropChance(EnumItemSlot slot, float chance) { - if (slot == EnumItemSlot.MAINHAND || slot == EnumItemSlot.OFFHAND) { + private void setDropChance(net.minecraft.world.entity.EquipmentSlot slot, float chance) { + if (slot == net.minecraft.world.entity.EquipmentSlot.MAINHAND || slot == net.minecraft.world.entity.EquipmentSlot.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 diff --git a/Spigot-Server-Patches/add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/add-hand-to-BlockMultiPlaceEvent.patch similarity index 96% rename from Spigot-Server-Patches/add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/add-hand-to-BlockMultiPlaceEvent.patch index 074230b73f..030a9527aa 100644 --- a/Spigot-Server-Patches/add-hand-to-BlockMultiPlaceEvent.patch +++ b/patches/server/add-hand-to-BlockMultiPlaceEvent.patch @@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 org.bukkit.inventory.ItemStack item; + //Paper start - add hand to BlockMultiPlaceEvent + EquipmentSlot equipmentSlot; - if (hand == EnumHand.MAIN_HAND) { + if (hand == InteractionHand.MAIN_HAND) { item = player.getInventory().getItemInMainHand(); + equipmentSlot = EquipmentSlot.HAND; } else { diff --git a/Spigot-Server-Patches/add-isDeeplySleeping-to-HumanEntity.patch b/patches/server/add-isDeeplySleeping-to-HumanEntity.patch similarity index 89% rename from Spigot-Server-Patches/add-isDeeplySleeping-to-HumanEntity.patch rename to patches/server/add-isDeeplySleeping-to-HumanEntity.patch index 527787e29d..e911b3d4ae 100644 --- a/Spigot-Server-Patches/add-isDeeplySleeping-to-HumanEntity.patch +++ b/patches/server/add-isDeeplySleeping-to-HumanEntity.patch @@ -15,10 +15,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + @Override + public boolean isDeeplySleeping() { -+ return getHandle().isDeeplySleeping(); ++ return getHandle().isSleepingLongEnough(); + } + // Paper end + @Override public int getSleepTicks() { - return getHandle().sleepTicks; + return this.getHandle().sleepCounter; diff --git a/Spigot-Server-Patches/add-more-information-to-Entity.toString.patch b/patches/server/add-more-information-to-Entity.toString.patch similarity index 52% rename from Spigot-Server-Patches/add-more-information-to-Entity.toString.patch rename to patches/server/add-more-information-to-Entity.toString.patch index 47eff4262d..b0a1eeb914 100644 --- a/Spigot-Server-Patches/add-more-information-to-Entity.toString.patch +++ b/patches/server/add-more-information-to-Entity.toString.patch @@ -9,12 +9,12 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } 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 +- return String.format(Locale.ROOT, "%s['%s'/%d, l='%s', x=%.2f, y=%.2f, z=%.2f]", this.getClass().getSimpleName(), this.getName().getString(), this.id, this.level == null ? "~NULL~" : this.level.toString(), this.getX(), this.getY(), this.getZ()); ++ return String.format(Locale.ROOT, "%s['%s'/%d, uuid='%s', l='%s', x=%.2f, y=%.2f, z=%.2f, cpos=%s, tl=%d, v=%b, rR=%s]", new Object[] { this.getClass().getSimpleName(), this.getName().getString(), Integer.valueOf(this.id), this.uuid.toString(), this.level == null ? "~NULL~" : this.level.toString(), Double.valueOf(this.getX()), Double.valueOf(this.getY()), Double.valueOf(this.getZ()), this.chunkPosition(), this.tickCount, this.valid, this.removalReason}); // Paper - add more information } - public boolean isInvulnerable(DamageSource damagesource) { + public boolean isInvulnerableTo(DamageSource damageSource) { diff --git a/Spigot-Server-Patches/add-per-world-spawn-limits.patch b/patches/server/add-per-world-spawn-limits.patch similarity index 98% rename from Spigot-Server-Patches/add-per-world-spawn-limits.patch rename to patches/server/add-per-world-spawn-limits.patch index 4f20bb5ca2..d039827a05 100644 --- a/Spigot-Server-Patches/add-per-world-spawn-limits.patch +++ b/patches/server/add-per-world-spawn-limits.patch @@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftWorld implements World { this.generator = gen; - environment = env; + this.environment = env; + // Paper start - per world spawn limits + this.monsterSpawn = this.world.paperConfig.spawnLimitMonsters; + this.animalSpawn = this.world.paperConfig.spawnLimitAnimals; diff --git a/patches/server/added-PlayerNameEntityEvent.patch b/patches/server/added-PlayerNameEntityEvent.patch new file mode 100644 index 0000000000..757009a9bc --- /dev/null +++ b/patches/server/added-PlayerNameEntityEvent.patch @@ -0,0 +1,38 @@ +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/NameTagItem.java b/src/main/java/net/minecraft/world/item/NameTagItem.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/NameTagItem.java ++++ b/src/main/java/net/minecraft/world/item/NameTagItem.java +@@ -0,0 +0,0 @@ + package net.minecraft.world.item; + ++// Paper start ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.event.player.PlayerNameEntityEvent; ++// Paper end + import net.minecraft.world.InteractionHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.LivingEntity; +@@ -0,0 +0,0 @@ public class NameTagItem extends Item { + public InteractionResult interactLivingEntity(ItemStack stack, Player user, LivingEntity entity, InteractionHand hand) { + if (stack.hasCustomHoverName() && !(entity instanceof Player)) { + if (!user.level.isClientSide && entity.isAlive()) { +- entity.setCustomName(stack.getHoverName()); +- if (entity instanceof Mob) { +- ((Mob)entity).setPersistenceRequired(); ++ // Paper start ++ PlayerNameEntityEvent event = new PlayerNameEntityEvent(((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), PaperAdventure.asAdventure(stack.getHoverName()), true); ++ if (!event.callEvent()) return InteractionResult.PASS; ++ LivingEntity newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); ++ newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null); ++ if (event.isPersistent() && newEntityLiving instanceof Mob) { ++ ((Mob) newEntityLiving).setPersistenceRequired(); ++ // Paper end + } + + stack.shrink(1); diff --git a/patches/server/added-PlayerTradeEvent.patch b/patches/server/added-PlayerTradeEvent.patch new file mode 100644 index 0000000000..2b9ae0dfe0 --- /dev/null +++ b/patches/server/added-PlayerTradeEvent.patch @@ -0,0 +1,40 @@ +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/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +@@ -0,0 +0,0 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa + + @Override + public void notifyTrade(MerchantOffer offer) { +- offer.increaseUses(); +- this.ambientSoundTime = -this.getAmbientSoundInterval(); +- this.rewardTradeXp(offer); ++ // Paper - moved down ++ // Paper start + if (this.tradingPlayer instanceof ServerPlayer) { +- CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, offer.getResult()); ++ io.papermc.paper.event.player.PlayerTradeEvent event = new io.papermc.paper.event.player.PlayerTradeEvent(((ServerPlayer) this.tradingPlayer).getBukkitEntity(), (org.bukkit.entity.AbstractVillager) this.getBukkitEntity(), offer.asBukkit(), true, true); ++ event.callEvent(); ++ if (!event.isCancelled()) { ++ MerchantOffer recipe = CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft(); ++ if (event.willIncreaseTradeUses()) recipe.increaseUses(); ++ this.ambientSoundTime = -this.getAmbientSoundInterval(); ++ if (event.isRewardingExp()) this.rewardTradeXp(recipe); ++ CriteriaTriggers.TRADE.trigger((ServerPlayer) this.tradingPlayer, this, recipe.getResult()); ++ } ++ } else { ++ offer.increaseUses(); ++ this.ambientSoundTime = -getAmbientSoundInterval(); ++ this.rewardTradeXp(offer); + } +- ++ // Paper end + } + + protected abstract void rewardTradeXp(MerchantOffer offer); diff --git a/Spigot-Server-Patches/added-Wither-API.patch b/patches/server/added-Wither-API.patch similarity index 54% rename from Spigot-Server-Patches/added-Wither-API.patch rename to patches/server/added-Wither-API.patch index 4473f7889e..30377fb621 100644 --- a/Spigot-Server-Patches/added-Wither-API.patch +++ b/patches/server/added-Wither-API.patch @@ -4,36 +4,28 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.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(); +--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java ++++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java +@@ -0,0 +0,0 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob + return entityliving.getMobType() != MobType.UNDEAD && entityliving.attackable(); }; - private static final PathfinderTargetCondition bz = (new PathfinderTargetCondition()).a(20.0D).a(EntityWither.by); + private static final TargetingConditions TARGETING_CONDITIONS = TargetingConditions.forCombat().range(20.0D).selector(WitherBoss.LIVING_ENTITY_SELECTOR); + // 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 { + public WitherBoss(EntityType type, Level world) { + super(type, world); +@@ -0,0 +0,0 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob @Override - public boolean canPortal() { + public boolean canChangeDimensions() { - return false; -+ return super.canPortal() && canPortal; // Paper ++ return super.canChangeDimensions() && canPortal; // Paper } @Override @@ -43,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ 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; + return this.bossBar; } + + // Paper start @@ -54,17 +46,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public int getInvulnerableTicks() { -+ return getHandle().getInvul(); ++ return getHandle().getInvulnerableTicks(); + } + + @Override + public void setInvulnerableTicks(int ticks) { -+ getHandle().setInvul(ticks); ++ getHandle().setInvulnerableTicks(ticks); + } + + @Override + public boolean canTravelThroughPortals() { -+ return getHandle().canPortal(); ++ return getHandle().canChangeDimensions(); + } + + @Override diff --git a/Spigot-Server-Patches/added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/added-option-to-disable-pathfinding-updates-on-block.patch similarity index 62% rename from Spigot-Server-Patches/added-option-to-disable-pathfinding-updates-on-block.patch rename to patches/server/added-option-to-disable-pathfinding-updates-on-block.patch index 389d10bd76..5e644cf687 100644 --- a/Spigot-Server-Patches/added-option-to-disable-pathfinding-updates-on-block.patch +++ b/patches/server/added-option-to-disable-pathfinding-updates-on-block.patch @@ -18,21 +18,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.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 { +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl @Override - public void notify(BlockPosition blockposition, IBlockData iblockdata, IBlockData iblockdata1, int i) { - this.getChunkProvider().flagDirty(blockposition); + public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { + this.getChunkSource().blockChanged(pos); + if(this.paperConfig.updatePathfindingOnBlockUpdate) { // Paper - option to disable pathfinding updates - VoxelShape voxelshape = iblockdata.getCollisionShape(this, blockposition); - VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); + VoxelShape voxelshape = oldState.getCollisionShape(this, pos); + VoxelShape voxelshape1 = newState.getCollisionShape(this, pos); -@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed { +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + } - this.tickingEntities = wasTicking; // Paper } + } // Paper } diff --git a/patches/server/additions-to-PlayerGameModeChangeEvent.patch b/patches/server/additions-to-PlayerGameModeChangeEvent.patch new file mode 100644 index 0000000000..d57a20a9a6 --- /dev/null +++ b/patches/server/additions-to-PlayerGameModeChangeEvent.patch @@ -0,0 +1,150 @@ +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/DefaultGameModeCommands.java b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java ++++ b/src/main/java/net/minecraft/server/commands/DefaultGameModeCommands.java +@@ -0,0 +0,0 @@ public class DefaultGameModeCommands { + GameType gameType = minecraftServer.getForcedGameType(); + if (gameType != null) { + for(ServerPlayer serverPlayer : minecraftServer.getPlayerList().getPlayers()) { +- if (serverPlayer.setGameMode(gameType)) { +- ++i; ++ // Paper start - extend PlayerGameModeChangeEvent ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.empty()); ++ if (event != null && event.isCancelled()) { ++ source.sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), false); + } ++ // Paper end ++ ++i; + } + } + +diff --git a/src/main/java/net/minecraft/server/commands/GameModeCommand.java b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/commands/GameModeCommand.java ++++ b/src/main/java/net/minecraft/server/commands/GameModeCommand.java +@@ -0,0 +0,0 @@ public class GameModeCommand { + int i = 0; + + for(ServerPlayer serverPlayer : targets) { +- if (serverPlayer.setGameMode(gameMode)) { ++ // Paper start - extend PlayerGameModeChangeEvent ++ org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.empty()); ++ if (event != null && !event.isCancelled()) { + logGamemodeChange(context.getSource(), serverPlayer, gameMode); + ++i; ++ } else if (event != null && event.cancelMessage() != null) { ++ context.getSource().sendSuccess(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), true); ++ // Paper end + } + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } + + public boolean setGameMode(GameType gameMode) { +- if (!this.gameMode.changeGameModeForPlayer(gameMode)) { +- return false; ++ // Paper start - Add cause and nullable message to event ++ PlayerGameModeChangeEvent event = this.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); ++ return event == null ? false : event.isCancelled(); ++ } ++ public PlayerGameModeChangeEvent setGameMode(GameType gameMode, PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component message) { ++ PlayerGameModeChangeEvent event = this.gameMode.changeGameModeForPlayer(gameMode, cause, message); ++ if (event == null || event.isCancelled()) { ++ // Paper end ++ return null; + } else { + this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float) gameMode.getId())); + if (gameMode == GameType.SPECTATOR) { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + + this.onUpdateAbilities(); + this.updateEffectVisibility(); +- return true; ++ return event; // Paper + } + } + +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + } + + public void loadGameTypes(@Nullable CompoundTag nbt) { ++ if (this.server.getForcedGameType() != null && this.server.getForcedGameType() != ServerPlayer.readPlayerMode(nbt, "playerGameType")) { ++ if (new PlayerGameModeChangeEvent(this.getBukkitEntity(), GameMode.getByValue(this.server.getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { ++ this.gameMode.setGameModeForPlayer(this.server.getForcedGameType(), GameType.DEFAULT_MODE); ++ } else { ++ this.gameMode.setGameModeForPlayer(ServerPlayer.readPlayerMode(nbt,"playerGameType"), ServerPlayer.readPlayerMode(nbt, "previousPlayerGameType")); ++ } ++ return; ++ } + this.gameMode.setGameModeForPlayer(this.calculateGameModeForNewPlayer(ServerPlayer.readPlayerMode(nbt, "playerGameType")), ServerPlayer.readPlayerMode(nbt, "previousPlayerGameType")); + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +@@ -0,0 +0,0 @@ public class ServerPlayerGameMode { + } + + public boolean changeGameModeForPlayer(GameType gameMode) { ++ // Paper end ++ PlayerGameModeChangeEvent event = this.changeGameModeForPlayer(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.UNKNOWN, null); ++ return event == null ? false : event.isCancelled(); ++ } ++ public PlayerGameModeChangeEvent changeGameModeForPlayer(GameType gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause cause, net.kyori.adventure.text.Component component) { ++ // Paper end + if (gameMode == this.gameModeForPlayer) { +- return false; ++ return null; // Paper + } else { + // CraftBukkit start + PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(this.player.getBukkitEntity(), GameMode.getByValue(gameMode.getId())); + this.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { +- return false; ++ return event; // Paper + } + // CraftBukkit end + this.setGameModeForPlayer(gameMode, this.gameModeForPlayer); +- return true; ++ return event; // Paper + } + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + + this.player = this.server.getPlayerList().respawn(this.player, false); + if (this.server.isHardcore()) { +- this.player.setGameMode(GameType.SPECTATOR); ++ this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper + ((GameRules.BooleanValue) this.player.getLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, this.server); + } + } +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"); + } + +- this.getHandle().setGameMode(GameType.byId(mode.getValue())); ++ this.getHandle().setGameMode(GameType.byId(mode.getValue()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.PLUGIN, null); // Paper + } + + @Override diff --git a/patches/server/call-PortalCreateEvent-players-and-end-platform.patch b/patches/server/call-PortalCreateEvent-players-and-end-platform.patch new file mode 100644 index 0000000000..6c3038b29e --- /dev/null +++ b/patches/server/call-PortalCreateEvent-players-and-end-platform.patch @@ -0,0 +1,33 @@ +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/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + private void createEndPlatform(ServerLevel world, BlockPos centerPos) { + BlockPos.MutableBlockPos blockposition_mutableblockposition = centerPos.mutable(); + ++ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(world); // Paper + for (int i = -2; i <= 2; ++i) { + for (int j = -2; j <= 2; ++j) { + for (int k = -1; k < 3; ++k) { + BlockState iblockdata = k == -1 ? Blocks.OBSIDIAN.defaultBlockState() : Blocks.AIR.defaultBlockState(); + +- world.setBlockAndUpdate(blockposition_mutableblockposition.set(centerPos).move(j, k, i), iblockdata); ++ blockList.setBlock(blockposition_mutableblockposition.set(centerPos).move(j, k, i), iblockdata, 3); // Paper + } + } + } ++ // Paper start ++ if (new org.bukkit.event.world.PortalCreateEvent((List< org.bukkit.block.BlockState>) (List) blockList.getList(), world.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/patches/server/copy-TESign-isEditable-from-snapshots.patch similarity index 95% rename from Spigot-Server-Patches/copy-TESign-isEditable-from-snapshots.patch rename to patches/server/copy-TESign-isEditable-from-snapshots.patch index 9a05a49b11..42d8e2dc64 100644 --- a/Spigot-Server-Patches/copy-TESign-isEditable-from-snapshots.patch +++ b/patches/server/copy-TESign-isEditable-from-snapshots.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/mai 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 +@@ -0,0 +0,0 @@ public class CraftSign extends CraftBlockEntityState implements } // Paper end } diff --git a/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/patches/server/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch similarity index 76% rename from Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch rename to patches/server/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch index 3a8d4ae75f..948779b89a 100644 --- a/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch +++ b/patches/server/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch @@ -5,11 +5,11 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.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 { +--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java +@@ -0,0 +0,0 @@ public class ItemEntity 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; @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.age != -32768) this.age += elapsedTicks; this.lastTick = MinecraftServer.currentTick; // CraftBukkit end -@@ -0,0 +0,0 @@ public class EntityItem extends Entity { +@@ -0,0 +0,0 @@ public class ItemEntity 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; diff --git a/patches/server/fix-PigZombieAngerEvent-cancellation.patch b/patches/server/fix-PigZombieAngerEvent-cancellation.patch new file mode 100644 index 0000000000..930286d797 --- /dev/null +++ b/patches/server/fix-PigZombieAngerEvent-cancellation.patch @@ -0,0 +1,35 @@ +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/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -0,0 +0,0 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + private static final int ALERT_RANGE_Y = 10; + private static final UniformInt ALERT_INTERVAL = TimeUtil.rangeOfSeconds(4, 6); + private int ticksUntilNextAlert; ++ private HurtByTargetGoal pathfinderGoalHurtByTarget; // Paper + + public ZombifiedPiglin(EntityType type, Level world) { + super(type, world); +@@ -0,0 +0,0 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + protected void addBehaviourGoals() { + this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error ++ this.targetSelector.addGoal(1, pathfinderGoalHurtByTarget = new HurtByTargetGoal(this).setAlertOthers(new Class[0])); // CraftBukkit - decompile error // Paper - assign field + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); + this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); + } +@@ -0,0 +0,0 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + this.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setPersistentAngerTarget(null); ++ pathfinderGoalHurtByTarget.stop(); // Paper - clear goalTargets to fix cancellation + return; + } + this.setRemainingPersistentAngerTime(event.getNewAnger()); diff --git a/patches/server/fix-PlayerItemHeldEvent-firing-twice.patch b/patches/server/fix-PlayerItemHeldEvent-firing-twice.patch new file mode 100644 index 0000000000..3b2c2d38b4 --- /dev/null +++ b/patches/server/fix-PlayerItemHeldEvent-firing-twice.patch @@ -0,0 +1,18 @@ +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/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); + if (this.player.isImmobile()) return; // CraftBukkit + if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) { ++ if (packet.getSlot() == this.player.getInventory().selected) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); + this.cserver.getPluginManager().callEvent(event); + if (event.isCancelled()) { diff --git a/patches/server/fix-cancelling-block-falling-causing-client-desync.patch b/patches/server/fix-cancelling-block-falling-causing-client-desync.patch new file mode 100644 index 0000000000..945d909520 --- /dev/null +++ b/patches/server/fix-cancelling-block-falling-causing-client-desync.patch @@ -0,0 +1,31 @@ +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/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -0,0 +0,0 @@ public class FallingBlockEntity extends Entity { + + if (this.time++ == 0) { + blockposition = this.blockPosition(); +- if (this.level.getBlockState(blockposition).is(block) && !CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { +- this.level.removeBlock(blockposition, false); ++ // Paper start - fix cancelling block falling causing client desync ++ if (this.level.getBlockState(blockposition).is(block)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, Blocks.AIR.defaultBlockState()).isCancelled()) { ++ if (this.level.getBlockState(blockposition).is(block)) { //if listener didn't update the block ++ ((ServerLevel) level).getChunkSource().blockChanged(blockposition); ++ } ++ this.discard(); ++ return; ++ } else { ++ this.level.removeBlock(blockposition, false); ++ } ++ // Paper end - fix cancelling block falling causing client desync + } else if (!this.level.isClientSide) { + this.discard(); + return; diff --git a/Spigot-Server-Patches/fix-converting-txt-to-json-file.patch b/patches/server/fix-converting-txt-to-json-file.patch similarity index 64% rename from Spigot-Server-Patches/fix-converting-txt-to-json-file.patch rename to patches/server/fix-converting-txt-to-json-file.patch index af2d3905a7..d1be4a99df 100644 --- a/Spigot-Server-Patches/fix-converting-txt-to-json-file.patch +++ b/patches/server/fix-converting-txt-to-json-file.patch @@ -9,66 +9,53 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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()); + DedicatedServerProperties dedicatedServerProperties = server.getProperties(); + this.setViewDistance(dedicatedServerProperties.viewDistance); + super.setUsingWhiteList(dedicatedServerProperties.whiteList.get()); + // Paper start - moved from constructor + } + @Override + public void loadAndSaveFiles() { + // Paper end - this.y(); - this.w(); - this.x(); + this.loadUserBanList(); + this.saveUserBanList(); + this.loadIpBanList(); 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 +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface 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 ++ if (this.convertOldUsers()) { ++ this.getProfileCache().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 +@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface 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 (this.convertOldUsers()) { +- this.getProfileCache().save(false); // Paper - } -- - if (!NameReferencingFileConverter.e(this)) { + + if (!OldUsersConverter.serverReadyAfterUserconversion(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; + this.maxPlayers = maxPlayers; + this.playerIo = saveHandler; } + 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(); + public void placeNewPlayer(Connection connection, ServerPlayer player) { + ServerPlayer prev = pendingPlayers.put(player.getUUID(), player);// Paper diff --git a/Spigot-Server-Patches/fix-dead-slime-setSize-invincibility.patch b/patches/server/fix-dead-slime-setSize-invincibility.patch similarity index 80% rename from Spigot-Server-Patches/fix-dead-slime-setSize-invincibility.patch rename to patches/server/fix-dead-slime-setSize-invincibility.patch index f98f485947..ba340689e1 100644 --- a/Spigot-Server-Patches/fix-dead-slime-setSize-invincibility.patch +++ b/patches/server/fix-dead-slime-setSize-invincibility.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void setSize(int size) { -- getHandle().setSize(size, true); -+ getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility +- this.getHandle().setSize(size, true); ++ this.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/patches/server/force-entity-dismount-during-teleportation.patch similarity index 69% rename from Spigot-Server-Patches/force-entity-dismount-during-teleportation.patch rename to patches/server/force-entity-dismount-during-teleportation.patch index 9c49c2044b..2224f223c2 100644 --- a/Spigot-Server-Patches/force-entity-dismount-during-teleportation.patch +++ b/patches/server/force-entity-dismount-during-teleportation.patch @@ -19,11 +19,11 @@ 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 +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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 { +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { } } @@ -39,18 +39,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + super.stopRiding(suppressCancellation); // Paper Entity entity1 = this.getVehicle(); - if (entity1 != entity && this.playerConnection != null) { + if (entity1 != entity && this.connection != 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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } -- public void bf() { +- public void removeVehicle() { + // Paper start -+ public void bf() { stopRiding(false); } ++ public void removeVehicle() { stopRiding(false); } + public void stopRiding(boolean suppressCancellation) { + // Paper end if (this.vehicle != null) { @@ -62,7 +62,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n return true; // CraftBukkit } @@ -74,16 +74,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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) { +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n + if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { VehicleExitEvent event = new VehicleExitEvent( - (Vehicle) getBukkitEntity(), + (Vehicle) this.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 +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } // CraftBukkit end // Spigot start @@ -92,12 +92,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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 +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.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; +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 4) != 0; } - @Override @@ -110,25 +110,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - super.stopRiding(); + super.stopRiding(suppressCancellation); // Paper - suppress - if (entity != null && entity != this.getVehicle() && !this.world.isClientSide) { - this.a(entity); + if (entity != null && entity != this.getVehicle() && !this.level.isClientSide) { + this.dismountVehicle(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 +diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.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 { +--- a/src/main/java/net/minecraft/world/entity/player/Player.java ++++ b/src/main/java/net/minecraft/world/entity/player/Player.java +@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { return -0.35D; } - @Override -- public void bf() { -- super.bf(); +- public void removeVehicle() { +- super.removeVehicle(); + // Paper start -+ @Override public void bf() { stopRiding(false); } ++ @Override public void removeVehicle() { stopRiding(false); } + @Override public void stopRiding(boolean suppressCancellation) { + // Paper end + super.stopRiding(suppressCancellation); // Paper - suppress - this.j = 0; + this.boardingCooldown = 0; } diff --git a/patches/server/forced-whitelist-use-configurable-kick-message.patch b/patches/server/forced-whitelist-use-configurable-kick-message.patch new file mode 100644 index 0000000000..8e0f9b4a97 --- /dev/null +++ b/patches/server/forced-whitelist-use-configurable-kick-message.patch @@ -0,0 +1,27 @@ +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 @@ import net.minecraft.nbt.NbtOps; + import net.minecraft.nbt.Tag; + import net.minecraft.network.chat.Component; + import net.minecraft.network.chat.TextComponent; +-import net.minecraft.network.chat.TranslatableComponent; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; + import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +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/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + + @Override + public void readAdditionalSaveData(CompoundTag nbt) { +- this.setAbsorptionAmount(nbt.getFloat("AbsorptionAmount")); ++ // Paper start - jvm keeps optimizing the setter ++ float absorptionAmount = nbt.getFloat("AbsorptionAmount"); ++ if (Float.isNaN(absorptionAmount)) { ++ absorptionAmount = 0; ++ } ++ this.setAbsorptionAmount(absorptionAmount); ++ // Paper end + if (nbt.contains("Attributes", 9) && this.level != null && !this.level.isClientSide) { + this.getAttributes().load(nbt.getList("Attributes", 10)); + } +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + public void setHealth(float health) { ++ // Paper start ++ if (Float.isNaN(health)) { health = getMaxHealth(); if (this.valid) { ++ System.err.println("[NAN-HEALTH] " + getScoreboardName() + " had NaN health set"); ++ } } // Paper end + // CraftBukkit start - Handle scaled health + if (this instanceof ServerPlayer) { + org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + } + + public void setAbsorptionAmount(float amount) { +- if (amount < 0.0F) { ++ if (amount < 0.0F || Float.isNaN(amount)) { // Paper + amount = 0.0F; + } + +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { + this.setDeltaMovement((double) ((float) packet.getXd() / 8000.0F), (double) ((float) packet.getYd() / 8000.0F), (double) ((float) packet.getZd() / 8000.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/patches/server/handle-PacketPlayInKeepAlive-async.patch similarity index 52% rename from Spigot-Server-Patches/handle-PacketPlayInKeepAlive-async.patch rename to patches/server/handle-PacketPlayInKeepAlive-async.patch index b85929f2db..dd80e48e9e 100644 --- a/Spigot-Server-Patches/handle-PacketPlayInKeepAlive-async.patch +++ b/patches/server/handle-PacketPlayInKeepAlive-async.patch @@ -14,25 +14,25 @@ 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 +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.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 { +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser @Override - public void a(PacketPlayInKeepAlive packetplayinkeepalive) { -- PlayerConnectionUtils.ensureMainThread(packetplayinkeepalive, this, this.player.getWorldServer()); // CraftBukkit + public void handleKeepAlive(ServerboundKeepAlivePacket packet) { +- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // 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); + if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) { + int i = (int) (Util.getMillis() - this.keepAliveTime); - this.player.ping = (this.player.ping * 3 + i) / 4; - this.awaitingKeepAlive = false; - } else if (!this.isExemptPlayer()) { + this.player.latency = (this.player.latency * 3 + i) / 4; + this.keepAlivePending = false; + } else if (!this.isSingleplayerOwner()) { + // Paper start - This needs to be handled on the main thread for plugins -+ minecraftServer.scheduleOnMain(() -> { - this.disconnect(new ChatMessage("disconnect.timeout")); ++ server.submit(() -> { + this.disconnect(new TranslatableComponent("disconnect.timeout")); + }); + // Paper end } diff --git a/Spigot-Server-Patches/implement-optional-per-player-mob-spawns.patch b/patches/server/implement-optional-per-player-mob-spawns.patch similarity index 60% rename from Spigot-Server-Patches/implement-optional-per-player-mob-spawns.patch rename to patches/server/implement-optional-per-player-mob-spawns.patch index c616567c91..86b17a39c1 100644 --- a/Spigot-Server-Patches/implement-optional-per-player-mob-spawns.patch +++ b/patches/server/implement-optional-per-player-mob-spawns.patch @@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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"); } } + @@ -38,6 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 @@ -51,48 +52,48 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +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 net.minecraft.core.SectionPos; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.level.ChunkPos; +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 static final PooledHashSets.PooledObjectLinkedOpenHashSet EMPTY_SET = new PooledHashSets.PooledObjectLinkedOpenHashSet<>(); + -+ private final Map players = new HashMap<>(); ++ private final Map players = new HashMap<>(); + // we use linked for better iteration. -+ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); ++ private final Long2ObjectOpenHashMap> playerMap = new Long2ObjectOpenHashMap<>(32, 0.5f); + private int viewDistance; + -+ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); ++ private final PooledHashSets pooledHashSets = new PooledHashSets<>(); + -+ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkCoordIntPair chunkPos) { ++ public PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final ChunkPos 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 PooledHashSets.PooledObjectLinkedOpenHashSet getPlayersInRange(final int chunkX, final int chunkZ) { ++ return this.playerMap.getOrDefault(ChunkPos.asLong(chunkX, chunkZ), EMPTY_SET); + } + -+ public void update(final List currentPlayers, final int newViewDistance) { ++ public void update(final List currentPlayers, final int newViewDistance) { + AsyncCatcher.catchOp("Distance map update"); -+ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); ++ final ObjectLinkedOpenHashSet gone = new ObjectLinkedOpenHashSet<>(this.players.keySet()); + + final int oldViewDistance = this.viewDistance; + this.viewDistance = newViewDistance; + -+ for (final EntityPlayer player : currentPlayers) { ++ for (final ServerPlayer 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); ++ final SectionPos newPosition = player.getLastSectionPos(); ++ final SectionPos oldPosition = this.players.put(player, newPosition); + + if (oldPosition == null) { + this.addNewPlayer(player, newPosition, newViewDistance); @@ -102,8 +103,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + //this.validatePlayer(player, newViewDistance); // debug only + } + -+ for (final EntityPlayer player : gone) { -+ final SectionPosition oldPosition = this.players.remove(player); ++ for (final ServerPlayer player : gone) { ++ final SectionPos oldPosition = this.players.remove(player); + if (oldPosition != null) { + this.removePlayer(player, oldPosition, oldViewDistance); + } @@ -111,19 +112,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + // expensive op, only for debug -+ private void validatePlayer(final EntityPlayer player, final int viewDistance) { ++ private void validatePlayer(final ServerPlayer player, final int viewDistance) { + int entiesGot = 0; + int expectedEntries = (2 * viewDistance + 1); + expectedEntries *= expectedEntries; + -+ final SectionPosition currPosition = player.getPlayerMapSection(); ++ final SectionPos currPosition = player.getLastSectionPos(); + + final int centerX = currPosition.getX(); + final int centerZ = currPosition.getZ(); + -+ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { ++ for (final Long2ObjectLinkedOpenHashMap.Entry> entry : this.playerMap.long2ObjectEntrySet()) { + final long key = entry.getLongKey(); -+ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); ++ final PooledHashSets.PooledObjectLinkedOpenHashSet map = entry.getValue(); + + if (map.referenceCount == 0) { + throw new IllegalStateException("Invalid map"); @@ -132,8 +133,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (map.set.contains(player)) { + ++entiesGot; + -+ final int chunkX = ChunkCoordIntPair.getX(key); -+ final int chunkZ = ChunkCoordIntPair.getZ(key); ++ final int chunkX = ChunkPos.getX(key); ++ final int chunkZ = ChunkPos.getZ(key); + + final int dist = Math.max(Math.abs(chunkX - centerX), Math.abs(chunkZ - centerZ)); + @@ -148,8 +149,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ 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) -> { ++ private void addPlayerTo(final ServerPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkPos.asLong(chunkX, chunkZ), (final Long key, final PooledHashSets.PooledObjectLinkedOpenHashSet players) -> { + if (players == null) { + return player.cachedSingleMobDistanceMap; + } else { @@ -158,13 +159,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + -+ 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) -> { ++ private void removePlayerFrom(final ServerPlayer player, final int chunkX, final int chunkZ) { ++ this.playerMap.compute(ChunkPos.asLong(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) { ++ private void updatePlayer(final ServerPlayer player, final SectionPos oldPosition, final SectionPos newPosition, final int oldViewDistance, final int newViewDistance) { + final int toX = newPosition.getX(); + final int toZ = newPosition.getZ(); + final int fromX = oldPosition.getX(); @@ -274,7 +275,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private void removePlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { ++ private void removePlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { + final int x = position.getX(); + final int z = position.getZ(); + @@ -285,7 +286,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private void addNewPlayer(final EntityPlayer player, final SectionPosition position, final int viewDistance) { ++ private void addNewPlayer(final ServerPlayer player, final SectionPos position, final int viewDistance) { + final int x = position.getX(); + final int z = position.getZ(); + @@ -542,268 +543,254 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 ++} +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.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); +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + private final Long2ByteMap chunkTypeCache; + private final Queue unloadQueue; + int viewDistance; ++ 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 ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + this.overworldDataStorage = persistentStateManagerFactory; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); ++ this.playerMobDistanceMap = this.level.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end - no-tick view distance + } + ++ // Paper start ++ public void updatePlayerMobTypeMap(Entity entity) { ++ if (!this.level.paperConfig.perPlayerMobSpawns) { ++ return; ++ } ++ int chunkX = (int)Math.floor(entity.getX()) >> 4; ++ int chunkZ = (int)Math.floor(entity.getZ()) >> 4; ++ int index = entity.getType().getCategory().ordinal(); ++ ++ for (ServerPlayer player : this.playerMobDistanceMap.getPlayersInRange(chunkX, chunkZ)) { ++ ++player.mobCounts[index]; ++ } ++ } ++ ++ public int getMobCountNear(ServerPlayer entityPlayer, net.minecraft.world.entity.MobCategory enumCreatureType) { ++ return entityPlayer.mobCounts[enumCreatureType.ordinal()]; ++ } ++ // Paper end ++ + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { + double d0 = (double) SectionPos.sectionToBlockCoord(pos.x, 8); + double d1 = (double) SectionPos.sectionToBlockCoord(pos.z, 8); +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.level.getProfiler().push("naturalSpawnCount"); + this.level.timings.countNaturalMobs.startTiming(); // Paper - timings + int l = this.distanceManager.getNaturalSpawnChunkCount(); +- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk); + // Paper start - per player mob spawning -+ SpawnerCreature.d spawnercreature_d; // moved down -+ if (this.playerChunkMap.playerMobDistanceMap != null) { ++ NaturalSpawner.SpawnState spawnercreature_d; // moved down ++ if (this.chunkMap.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(); ++ this.level.timings.playerMobDistanceMapUpdate.startTiming(); ++ this.chunkMap.playerMobDistanceMap.update(this.level.players, this.chunkMap.viewDistance); ++ this.level.timings.playerMobDistanceMapUpdate.stopTiming(); + // re-set mob counts -+ for (EntityPlayer player : this.world.players) { ++ for (ServerPlayer player : this.level.players) { + Arrays.fill(player.mobCounts, 0); + } -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, true); ++ spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, true); + } else { -+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, false); ++ spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, false); + } + // Paper end - this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings + this.level.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 + this.lastSpawnState = spawnercreature_d; +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.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 { +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -0,0 +0,0 @@ import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.damagesource.EntityDamageSource; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; +-import net.minecraft.world.entity.Entity; +-import net.minecraft.world.entity.EntitySelector; +-import net.minecraft.world.entity.HumanoidArm; +-import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.NeutralMob; ++import net.minecraft.world.entity.*; + import net.minecraft.world.entity.animal.horse.AbstractHorse; + import net.minecraft.world.entity.item.ItemEntity; + import net.minecraft.world.entity.monster.Monster; +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { public boolean queueHealthUpdatePacket = false; - public net.minecraft.network.protocol.game.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; + public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; // Paper end + // Paper start - mob spawning rework -+ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = EnumCreatureType.values().length; ++ public static final int ENUMCREATURETYPE_TOTAL_ENUMS = MobCategory.values().length; + public final int[] mobCounts = new int[ENUMCREATURETYPE_TOTAL_ENUMS]; // Paper -+ public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet cachedSingleMobDistanceMap; ++ 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; +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper + this.bukkitPickUpLoot = 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 +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.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; +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -0,0 +0,0 @@ import net.minecraft.core.Registry; + import net.minecraft.core.SectionPos; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.tags.BlockTags; + import net.minecraft.tags.FluidTags; import net.minecraft.tags.Tag; - import net.minecraft.tags.TagsBlock; -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - }); +@@ -0,0 +0,0 @@ public final class NaturalSpawner { - 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); + private NaturalSpawner() {} + ++ // Paper start - add countMobs parameter + public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource) { ++ return createState(spawningChunkCount, entities, chunkSource, 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 { ++ public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable entities, NaturalSpawner.ChunkGetter chunkSource, boolean countMobs) { ++ // Paper end - add countMobs parameter + PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); + Object2IntOpenHashMap object2intopenhashmap = new Object2IntOpenHashMap(); + Iterator iterator = entities.iterator(); +@@ -0,0 +0,0 @@ public final class NaturalSpawner { } object2intopenhashmap.addTo(enumcreaturetype, 1); + // Paper start + if (countMobs) { -+ ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity); ++ chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); + } + // Paper end }); } } -@@ -0,0 +0,0 @@ public final class SpawnerCreature { +@@ -0,0 +0,0 @@ public final class NaturalSpawner { continue; } -- if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && spawnercreature_d.a(enumcreaturetype, limit)) { +- if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && info.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 currEntityCount = info.mobCategoryCounts.getInt(enumcreaturetype); ++ int k1 = limit * info.getSpawnableChunkCount() / NaturalSpawner.MAGIC_NUMBER; + int difference = k1 - currEntityCount; + -+ if (worldserver.paperConfig.perPlayerMobSpawns) { ++ if (world.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); ++ for (ServerPlayer entityplayer : world.getChunkSource().chunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) { ++ minDiff = Math.min(limit - world.getChunkSource().chunkMap.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) { ++ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (spawnAnimals || !enumcreaturetype.isPersistent()) && info.a(enumcreaturetype, limit) && 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); + Objects.requireNonNull(info); + NaturalSpawner.SpawnPredicate spawnercreature_c = info::canSpawn; + + Objects.requireNonNull(info); +- NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn); ++ int spawnCount = NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn, ++ difference, world.paperConfig.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null); ++ info.mobCategoryCounts.mergeInt(enumcreaturetype, spawnCount, Integer::sum); + // Paper end - per player mob spawning } } -@@ -0,0 +0,0 @@ public final class SpawnerCreature { +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + world.getProfiler().pop(); } - 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); ++ // Paper start - add parameters and int ret type + public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { ++ spawnCategoryForChunk(group, world, chunk, checker, runner); + } -+ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer trackEntity) { ++ public static int spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer trackEntity) { + // Paper end - add parameters and int ret type - BlockPosition blockposition = getRandomPosition(worldserver, chunk); + BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, 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); + if (blockposition.getY() >= world.getMinBuildHeight() + 1) { +- NaturalSpawner.spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner); ++ return NaturalSpawner.spawnCategoryForPosition(group, world, (ChunkAccess) chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper } + 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); + @VisibleForDebug +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + }); + } + ++ // Paper start - add maxSpawns parameter and return spawned mobs + public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { ++ spawnCategoryForPosition(group, world,chunk, pos, checker, runner); + } -+ 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 ++ public static int spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer trackEntity) { ++ // Paper end - add maxSpawns parameter and return spawned mobs + StructureFeatureManager structuremanager = world.structureFeatureManager(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + int i = pos.getY(); + BlockState iblockdata = world.getTypeIfLoadedAndInBounds(pos); // 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(); + if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); - int j = 0; + // Paper - moved up int k = 0; while (k < 3) { -@@ -0,0 +0,0 @@ public final class SpawnerCreature { +@@ -0,0 +0,0 @@ public final class NaturalSpawner { // Paper start - Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); + Boolean doSpawning = isValidSpawnPostitionForType(world, group, 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)) { + if (doSpawning && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) { // Paper end -@@ -0,0 +0,0 @@ public final class SpawnerCreature { - + Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type); 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 + entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F); +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + ++j; ++k1; - spawnercreature_a.run(entityinsentient, ichunkaccess); + runner.run(entityinsentient, chunk); + // Paper start + if (trackEntity != null) { + trackEntity.accept(entityinsentient); @@ -811,38 +798,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end } // CraftBukkit end -- if (j >= entityinsentient.getMaxSpawnGroup()) { +- if (j >= entityinsentient.getMaxSpawnClusterSize()) { - return; -+ if (j >= entityinsentient.getMaxSpawnGroup() || j >= maxSpawns) { // Paper ++ if (j >= entityinsentient.getMaxSpawnClusterSize() || j >= maxSpawns) { // Paper + return j; // Paper } - if (entityinsentient.c(k1)) { -@@ -0,0 +0,0 @@ public final class SpawnerCreature { + if (entityinsentient.isMaxGroupSizeReached(k1)) { +@@ -0,0 +0,0 @@ public final class NaturalSpawner { } } + 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; + private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) { diff --git a/Spigot-Server-Patches/improve-CraftWorld-isChunkLoaded.patch b/patches/server/improve-CraftWorld-isChunkLoaded.patch similarity index 68% rename from Spigot-Server-Patches/improve-CraftWorld-isChunkLoaded.patch rename to patches/server/improve-CraftWorld-isChunkLoaded.patch index 013b83f911..706c993b65 100644 --- a/Spigot-Server-Patches/improve-CraftWorld-isChunkLoaded.patch +++ b/patches/server/improve-CraftWorld-isChunkLoaded.patch @@ -16,15 +16,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean isChunkLoaded(int x, int z) { -- return world.getChunkProvider().isChunkLoaded(x, z); -+ return world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z) != null; // Paper +- return this.world.getChunkSource().isChunkLoaded(x, z); ++ return this.world.getChunkSource().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) +- return this.isChunkLoaded(x, z) || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; ++ return this.world.getChunkSource().getChunkAtIfCachedImmediately(x, z) != null || this.world.getChunkSource().chunkMap.read(new ChunkPos(x, z)) != null; // Paper (TODO check if the first part can be removed) } catch (IOException ex) { throw new RuntimeException(ex); } diff --git a/patches/server/incremental-chunk-saving.patch b/patches/server/incremental-chunk-saving.patch new file mode 100644 index 0000000000..019eaa3319 --- /dev/null +++ b/patches/server/incremental-chunk-saving.patch @@ -0,0 +1,333 @@ +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 { + 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); ++ } ++ + 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)); +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 ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); + public int autosavePeriod; ++ public boolean serverAutoSave = false; // Paper + public Commands vanillaCommandDispatcher; + public boolean forceTicks; // Paper + // CraftBukkit end +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit +- MinecraftServer.LOGGER.debug("Autosave started"); ++ // if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // CraftBukkit // Paper - move down ++ // MinecraftServer.LOGGER.debug("Autosave started"); // Paper ++ serverAutoSave = (autosavePeriod > 0 && this.tickCount % autosavePeriod == 0); // Paper + this.profiler.push("save"); ++ if (this.autosavePeriod > 0 && this.tickCount % this.autosavePeriod == 0) { // Paper - moved from above + this.playerList.saveAll(); +- this.saveAllChunks(true, false, false); +- this.profiler.pop(); +- MinecraftServer.LOGGER.debug("Autosave finished"); ++ // this.saveAllChunks(true, false, false); // Paper - saved incrementally below ++ } // Paper start ++ for (ServerLevel level : this.getAllLevels()) { ++ if (level.paperConfig.autoSavePeriod > 0) { ++ level.saveIncrementally(this.serverAutoSave); ++ } + } ++ // Paper end ++ this.profiler.pop(); ++ // MinecraftServer.LOGGER.debug("Autosave finished"); // Paper ++ //} // Paper + + this.profiler.push("snooper"); + if (((DedicatedServer) this).getProperties().snooperEnabled && !this.snooper.isStarted() && this.tickCount > 100) { // Spigot +diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java ++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java +@@ -0,0 +0,0 @@ public class ChunkHolder { + this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key); + } + // Paper end - optimise isOutsideOfRange ++ long lastAutoSaveTime; // Paper - incremental autosave ++ long inactiveTimeStart; // Paper - incremental autosave + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); +@@ -0,0 +0,0 @@ public class ChunkHolder { + boolean flag2 = playerchunk_state.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + boolean flag3 = playerchunk_state1.isOrAfter(ChunkHolder.FullChunkStatus.BORDER); + ++ boolean prevHasBeenLoaded = this.wasAccessibleSinceLastSave; // Paper + this.wasAccessibleSinceLastSave |= flag3; ++ // Paper start - incremental autosave ++ if (this.wasAccessibleSinceLastSave & !prevHasBeenLoaded) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } ++ // Paper end + if (!flag2 && flag3) { + int expectCreateCount = ++this.fullChunkCreateCount; // Paper + this.fullChunkFuture = chunkStorage.prepareAccessibleChunk(this); +@@ -0,0 +0,0 @@ public class ChunkHolder { + } + + public void refreshAccessibility() { ++ boolean prev = this.wasAccessibleSinceLastSave; // Paper + this.wasAccessibleSinceLastSave = ChunkHolder.getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); ++ // Paper start - incremental autosave ++ if (prev != this.wasAccessibleSinceLastSave) { ++ if (this.wasAccessibleSinceLastSave) { ++ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime; ++ if (timeSinceAutoSave < 0) { ++ // safest bet is to assume autosave is needed here ++ timeSinceAutoSave = this.chunkMap.level.paperConfig.autoSavePeriod; ++ } ++ this.lastAutoSaveTime = this.chunkMap.level.getGameTime() - timeSinceAutoSave; ++ this.chunkMap.autoSaveQueue.add(this); ++ } else { ++ this.inactiveTimeStart = this.chunkMap.level.getGameTime(); ++ this.chunkMap.autoSaveQueue.remove(this); ++ } ++ } ++ // Paper end + } + ++ // Paper start - incremental autosave ++ public boolean setHasBeenLoaded() { ++ this.wasAccessibleSinceLastSave = getFullChunkStatus(this.ticketLevel).isOrAfter(ChunkHolder.FullChunkStatus.BORDER); ++ return this.wasAccessibleSinceLastSave; ++ } ++ // Paper end ++ + public void replaceProtoChunk(ImposterProtoChunk chunk) { + for (int i = 0; i < this.futures.length(); ++i) { + CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureMana + import net.minecraft.world.level.storage.DimensionDataStorage; + import net.minecraft.world.level.storage.LevelStorageSource; + import net.minecraft.world.phys.Vec3; ++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 ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + } + ++ // 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.pos), MCUtil.getCoordinateKey(playerchunk2.pos)); ++ }); ++ ++ 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.level.paperConfig.maxAutoSaveChunksPerTick); ++ long currentTick = this.level.getGameTime(); ++ long maxSaveTime = currentTick - this.level.paperConfig.autoSavePeriod; ++ ++ for (Iterator iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) { ++ ChunkHolder playerchunk = iterator.next(); ++ if (playerchunk.lastAutoSaveTime > maxSaveTime) { ++ break; ++ } ++ ++ iterator.remove(); ++ ++ ChunkAccess ichunkaccess = playerchunk.getChunkToSave().getNow(null); ++ if (ichunkaccess instanceof LevelChunk) { ++ boolean shouldSave = ((LevelChunk)ichunkaccess).lastSaveTime <= maxSaveTime; ++ ++ if (shouldSave && this.save(ichunkaccess) && this.level.entityManager.storeChunkSections(playerchunk.pos.toLong(), entity -> {})) { ++ ++savedThisTick; ++ ++ if (!playerchunk.setHasBeenLoaded()) { ++ // do not fall through to reschedule logic ++ playerchunk.inactiveTimeStart = currentTick; ++ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ continue; ++ } ++ } ++ } ++ ++ reschedule.add(playerchunk); ++ ++ if (savedThisTick >= this.level.paperConfig.maxAutoSaveChunksPerTick) { ++ break; ++ } ++ } ++ ++ for (int i = 0, len = reschedule.size(); i < len; ++i) { ++ ChunkHolder playerchunk = reschedule.get(i); ++ playerchunk.lastAutoSaveTime = this.level.getGameTime(); ++ this.autoSaveQueue.add(playerchunk); ++ } ++ } ++ // Paper end ++ + protected void saveAllChunks(boolean flush) { + Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) + if (flush) { +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + asyncSaveData, chunk); + + chunk.setUnsaved(false); ++ chunk.setLastSaved(this.level.getGameTime()); // Paper - track last saved time + } + // Paper end + +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + this.level.unload(chunk); + } ++ this.autoSaveQueue.remove(holder); // Paper + + this.lightEngine.updateChunkStatus(ichunkaccess.getPos()); + this.lightEngine.tryScheduleUpdate(); +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + if (!chunk.isUnsaved()) { + return false; + } else { ++ chunk.setLastSaved(this.level.getGameTime()); // Paper - track save time + chunk.setUnsaved(false); + ChunkPos chunkcoordintpair = chunk.getPos(); + +diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java ++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + } // Paper - Timings + } + ++ // Paper start - duplicate save, but call incremental ++ public void saveIncrementally() { ++ this.runDistanceManagerUpdates(); ++ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings ++ this.chunkMap.saveIncrementally(); ++ } // Paper - Timings ++ } ++ // Paper end ++ + @Override + public void close() throws IOException { + // CraftBukkit start +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); + } + ++ // Paper start - derived from below ++ public void saveIncrementally(boolean doFull) { ++ ServerChunkCache chunkproviderserver = this.getChunkSource(); ++ ++ if (doFull) { ++ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); ++ } ++ ++ try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) { ++ if (doFull) { ++ this.saveLevelData(); ++ } ++ ++ this.timings.worldSaveChunks.startTiming(); // Paper ++ if (!this.noSave()) chunkproviderserver.saveIncrementally(); ++ this.timings.worldSaveChunks.stopTiming(); // Paper ++ ++ // Copied from save() ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ if (doFull) { // Paper ++ ServerLevel worldserver1 = this; ++ ++ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); ++ this.convertable.saveDataTag(this.server.registryHolder, this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ } ++ // CraftBukkit end ++ } ++ } ++ // Paper end ++ + public void save(@Nullable ProgressListener progressListener, boolean flush, boolean flag1) { + ServerChunkCache chunkproviderserver = this.getChunkSource(); + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -0,0 +0,0 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + return GameEventDispatcher.NOOP; + } + ++ default void setLastSaved(long ticks) {} + // Paper start + default boolean generateFlatBedrock() { + if (this instanceof ProtoChunk) { +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { + private final ShortList[] postProcessing; + private TickList blockTicks; + private TickList liquidTicks; ++ // Paper start - track last save time ++ public long lastSaveTime; ++ @Override ++ public void setLastSaved(long ticks) { ++ this.lastSaveTime = ticks; ++ } ++ // Paper end + private volatile boolean unsaved; + private long inhabitedTime; + @Nullable diff --git a/Spigot-Server-Patches/living-entity-allow-attribute-registration.patch b/patches/server/living-entity-allow-attribute-registration.patch similarity index 63% rename from Spigot-Server-Patches/living-entity-allow-attribute-registration.patch rename to patches/server/living-entity-allow-attribute-registration.patch index a6bf271d9e..7919856caa 100644 --- a/Spigot-Server-Patches/living-entity-allow-attribute-registration.patch +++ b/patches/server/living-entity-allow-attribute-registration.patch @@ -4,28 +4,19 @@ 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 +diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.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 { +--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java ++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java +@@ -0,0 +0,0 @@ public class AttributeMap { } } + + // Paper - start -+ public void registerAttribute(AttributeBase attributeBase) { -+ AttributeModifiable attributeModifiable = new AttributeModifiable(attributeBase, AttributeModifiable::getAttribute); -+ attributeMap.put(attributeBase, attributeModifiable); ++ public void registerAttribute(Attribute attributeBase) { ++ AttributeInstance attributeModifiable = new AttributeInstance(attributeBase, AttributeInstance::getAttribute); ++ attributes.put(attributeBase, attributeModifiable); + } + // Paper - end + @@ -46,15 +37,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + - public static AttributeBase toMinecraft(Attribute attribute) { - return IRegistry.ATTRIBUTE.get(CraftNamespacedKey.toMinecraft(attribute.getKey())); + public static net.minecraft.world.entity.ai.attributes.Attribute toMinecraft(Attribute attribute) { + return net.minecraft.core.Registry.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); + return this.getHandle().craftAttributes.getAttribute(attribute); } + // Paper start @@ -66,4 +57,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override public void setAI(boolean ai) { - if (this.getHandle() instanceof EntityInsentient) { + if (this.getHandle() instanceof Mob) { diff --git a/Spigot-Server-Patches/misc-debugging-dumps.patch b/patches/server/misc-debugging-dumps.patch similarity index 63% rename from Spigot-Server-Patches/misc-debugging-dumps.patch rename to patches/server/misc-debugging-dumps.patch index 1947d7ed92..c27cd1046d 100644 --- a/Spigot-Server-Patches/misc-debugging-dumps.patch +++ b/patches/server/misc-debugging-dumps.patch @@ -32,56 +32,40 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ 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/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java +@@ -0,0 +0,0 @@ public abstract class HangingEntity extends Entity { + protected static final Predicate HANGING_ENTITY = (entity) -> { + return entity instanceof HangingEntity; + }; +- private int checkInterval; ++ private int checkInterval; { this.checkInterval = this.getId() % this.level.spigotConfig.hangingTickFrequency; } // Paper + public BlockPos pos; + protected Direction direction; + diff --git a/Spigot-Server-Patches/provide-a-configurable-option-to-disable-creeper-lin.patch b/patches/server/provide-a-configurable-option-to-disable-creeper-lin.patch similarity index 63% rename from Spigot-Server-Patches/provide-a-configurable-option-to-disable-creeper-lin.patch rename to patches/server/provide-a-configurable-option-to-disable-creeper-lin.patch index f62a4790e7..9b22046211 100644 --- a/Spigot-Server-Patches/provide-a-configurable-option-to-disable-creeper-lin.patch +++ b/patches/server/provide-a-configurable-option-to-disable-creeper-lin.patch @@ -20,16 +20,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 +diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.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(); +--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java +@@ -0,0 +0,0 @@ public class Creeper extends Monster implements PowerableMob { + private void spawnLingeringCloud() { + Collection collection = this.getActiveEffects(); - if (!collection.isEmpty()) { -+ if (!collection.isEmpty() && !world.paperConfig.disableCreeperLingeringEffect) { // Paper - EntityAreaEffectCloud entityareaeffectcloud = new EntityAreaEffectCloud(this.world, this.locX(), this.locY(), this.locZ()); ++ if (!collection.isEmpty() && !level.paperConfig.disableCreeperLingeringEffect) { // Paper + AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level, this.getX(), this.getY(), this.getZ()); - entityareaeffectcloud.setSource(this); // CraftBukkit + entityareaeffectcloud.setOwner(this); // CraftBukkit diff --git a/patches/server/remove-null-possibility-for-getServer-singleton.patch b/patches/server/remove-null-possibility-for-getServer-singleton.patch new file mode 100644 index 0000000000..0d649f0cb8 --- /dev/null +++ b/patches/server/remove-null-possibility-for-getServer-singleton.patch @@ -0,0 +1,36 @@ +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 ReentrantBlockableEventLoop implements SnooperPopulator, CommandSource, AutoCloseable { + ++ private static MinecraftServer SERVER; // Paper + public static final Logger LOGGER = LogManager.getLogger(); + private static final float AVERAGE_TICK_TIME_SMOOTHING = 0.8F; + private static final int TICK_STATS_SPAN = 100; +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +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/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private final MinecraftServer server; + public ServerPlayer player; + private int tickCount; +- private long keepAliveTime; @Deprecated private void setLastPing(long lastPing) { this.keepAliveTime = lastPing;}; @Deprecated private long getLastPing() { return this.keepAliveTime;}; // Paper - OBFHELPER +- private boolean keepAlivePending; @Deprecated private void setPendingPing(boolean isPending) { this.keepAlivePending = isPending;}; @Deprecated private boolean isPendingPing() { return this.keepAlivePending;}; // Paper - OBFHELPER +- private long keepAliveChallenge; @Deprecated private void setKeepAliveID(long keepAliveID) { this.keepAliveChallenge = keepAliveID;}; @Deprecated private long getKeepAliveID() {return this.keepAliveChallenge; }; // Paper - OBFHELPER ++ private long keepAliveTime = Util.getMillis(); ++ private boolean keepAlivePending; ++ private long keepAliveChallenge; + // CraftBukkit start - multithreaded fields + private AtomicInteger chatSpamTickCount = new AtomicInteger(); + // CraftBukkit end +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + private int aboveGroundVehicleTickCount; + private int receivedMovePacketCount; + private int knownMovePacketCount; ++ private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + + public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { + this.server = server; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser + } + + this.server.getProfiler().push("keepAlive"); +- long i = Util.getMillis(); +- +- if (i - this.keepAliveTime >= 25000L) { // CraftBukkit +- if (this.keepAlivePending) { +- this.disconnect(new TranslatableComponent("disconnect.timeout")); +- } else { ++ // 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 = Util.getMillis(); ++ long elapsedTime = currentTime - this.keepAliveTime; ++ ++ if (this.keepAlivePending) { ++ if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected ++ ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info ++ this.disconnect(new TranslatableComponent("disconnect.timeout", new Object[0])); ++ } ++ } else { ++ if (elapsedTime >= 15000L) { // 15 seconds + this.keepAlivePending = true; +- this.keepAliveTime = i; +- this.keepAliveChallenge = i; ++ this.keepAliveTime = currentTime; ++ this.keepAliveChallenge = currentTime; + this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge)); + } + } ++ // Paper end + + this.server.getProfiler().pop(); + // CraftBukkit start diff --git a/patches/server/stop-firing-pressure-plate-EntityInteractEvent-for-i.patch b/patches/server/stop-firing-pressure-plate-EntityInteractEvent-for-i.patch new file mode 100644 index 0000000000..69d455aeeb --- /dev/null +++ b/patches/server/stop-firing-pressure-plate-EntityInteractEvent-for-i.patch @@ -0,0 +1,19 @@ +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/PressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PressurePlateBlock.java +@@ -0,0 +0,0 @@ public class PressurePlateBlock extends BasePressurePlateBlock { + + while (iterator.hasNext()) { + Entity entity = (Entity) iterator.next(); ++ if (entity.isIgnoringBlockTriggers()) continue; // Paper - don't call event for ignored entities + + // CraftBukkit start - Call interact event when turning on a pressure plate + if (this.getSignalForState(world.getBlockState(pos)) == 0) { diff --git a/patches/server/use-CB-BlockState-implementations-for-captured-block.patch b/patches/server/use-CB-BlockState-implementations-for-captured-block.patch new file mode 100644 index 0000000000..e9d3db672e --- /dev/null +++ b/patches/server/use-CB-BlockState-implementations-for-captured-block.patch @@ -0,0 +1,60 @@ +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/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, 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 Level implements LevelAccessor, AutoCloseable { + public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { +- CapturedBlockState blockstate = this.capturedBlockStates.get(pos); ++ CraftBlockState blockstate = this.capturedBlockStates.get(pos); + if (blockstate == null) { + blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); + this.capturedBlockStates.put(pos.immutable(), blockstate); +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // CraftBukkit start - capture blockstates + boolean captured = false; + if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { +- CapturedBlockState blockstate = CapturedBlockState.getBlockState(this, pos, flags); ++ CraftBlockState blockstate = (CraftBlockState) world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()).getState(); // Paper - use CB getState to get a suitable snapshot ++ blockstate.setFlag(flags); // Paper - set flag + this.capturedBlockStates.put(pos.immutable(), blockstate); + captured = true; + } +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public BlockState getBlockState(BlockPos pos) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { +- CapturedBlockState previous = this.capturedBlockStates.get(pos); ++ CraftBlockState previous = this.capturedBlockStates.get(pos); // Paper + if (previous != null) { + return previous.getHandle(); + } diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 4ddd1eb648..0000000000 --- a/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - 4.0.0 - - - com.destroystokyo.paper - paper-parent - dev-SNAPSHOT - pom - - Paper-Parent - Parent project for all Paper modules. - https://github.com/PaperMC/Paper - - - Paper-API - Paper-MojangAPI - Paper-Server - - - - clean install - - - - UTF-8 - - - - - md_5-releases - https://repo.md-5.net/content/repositories/releases/ - - - aikar - https://repo.aikar.co/content/groups/aikar/ - - - destroystokyo-repo - https://papermc.io/repo/repository/maven-public/ - - - - - - papermc-releases - https://papermc.io/repo/repository/maven-releases/ - - - papermc-snapshots - https://papermc.io/repo/repository/maven-snapshots/ - - - diff --git a/scripts/applyPatches.sh b/scripts/applyPatches.sh deleted file mode 100755 index e700fde80b..0000000000 --- a/scripts/applyPatches.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env bash - -( -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -gitcmd="git -c commit.gpgsign=false" -applycmd="$gitcmd am --3way --ignore-whitespace" -# Windows detection to workaround ARG_MAX limitation -windows="$([[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]] && echo "true" || echo "false")" - -echo "Rebuilding Forked projects.... " - -function applyPatch { - what=$1 - what_name=$(basename "$what") - target=$2 - branch=$3 - - cd "$basedir/$what" - $gitcmd fetch - $gitcmd branch -f upstream "$branch" >/dev/null - - cd "$basedir" - if [ ! -d "$basedir/$target" ]; then - $gitcmd clone "$what" "$target" - fi - cd "$basedir/$target" - - echo "Resetting $target to $what_name..." - $gitcmd remote rm upstream > /dev/null 2>&1 - $gitcmd remote add upstream "$basedir/$what" >/dev/null 2>&1 - $gitcmd checkout master 2>/dev/null || $gitcmd checkout -b master - $gitcmd fetch upstream >/dev/null 2>&1 - $gitcmd reset --hard upstream/upstream - - echo " Applying patches to $target..." - - statusfile=".git/patch-apply-failed" - rm -f "$statusfile" - git config commit.gpgsign false - $gitcmd am --abort >/dev/null 2>&1 - - # Special case Windows handling because of ARG_MAX constraint - if [[ $windows == "true" ]]; then - echo " Using workaround for Windows ARG_MAX constraint" - find "$basedir/${what_name}-Patches/"*.patch -print0 | xargs -0 $applycmd - else - $applycmd "$basedir/${what_name}-Patches/"*.patch - fi - - if [ "$?" != "0" ]; then - echo 1 > "$statusfile" - echo " Something did not apply cleanly to $target." - echo " Please review above details and finish the apply then" - echo " save the changes with rebuildPatches.sh" - - # On Windows, finishing the patch apply will only fix the latest patch - # users will need to rebuild from that point and then re-run the patch - # process to continue - if [[ $windows == "true" ]]; then - echo "" - echo " Because you're on Windows you'll need to finish the AM," - echo " rebuild all patches, and then re-run the patch apply again." - echo " Consider using the scripts with Windows Subsystem for Linux." - fi - - exit 1 - else - rm -f "$statusfile" - echo " Patches applied cleanly to $target" - fi -} - -# Move into spigot dir -cd "$workdir/Spigot" -basedir=$(pwd) -# Apply Spigot -( - applyPatch ../Bukkit Spigot-API HEAD && - applyPatch ../CraftBukkit Spigot-Server patched -) || ( - echo "Failed to apply Spigot Patches" - exit 1 -) || exit 1 -# Move out of Spigot -basedir="$1" -cd "$basedir" - -echo "Importing MC Dev" - -./scripts/importmcdev.sh "$basedir" || exit 1 - -# Apply paper -( - applyPatch "work/Spigot/Spigot-API" Paper-API HEAD && - applyPatch "work/Spigot/Spigot-Server" Paper-Server HEAD - cd "$basedir" - - # if we have previously ran ./paper mcdev, update it - if [ -d "$workdir/Minecraft/$minecraftversion/src" ]; then - ./scripts/makemcdevsrc.sh "$basedir" - fi -) || ( - echo "Failed to apply Paper Patches" - exit 1 -) || exit 1 -) || exit 1 diff --git a/scripts/build.sh b/scripts/build.sh deleted file mode 100755 index 9b8fa286a7..0000000000 --- a/scripts/build.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -basedir="$(cd "$1" && pwd -P)" -gitcmd="git -c commit.gpgsign=false" - -($gitcmd submodule update --init && ./scripts/remap.sh "$basedir" && ./scripts/decompile.sh "$basedir" && ./scripts/init.sh "$basedir" && ./scripts/applyPatches.sh "$basedir") || ( - echo "Failed to build Paper" - exit 1 -) || exit 1 -if [ "$2" == "--jar" ]; then - mvn clean install && ./scripts/paperclip.sh "$basedir" -fi -) || exit 1 diff --git a/scripts/decompile.sh b/scripts/decompile.sh deleted file mode 100755 index 0d0467d99a..0000000000 --- a/scripts/decompile.sh +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -windows="$([[ "$OSTYPE" == "cygwin" || "$OSTYPE" == "msys" ]] && echo "true" || echo "false")" -decompiledir="$workdir/Minecraft/$minecraftversion" -spigotdecompiledir="$decompiledir/spigot" -forgedecompiledir="$decompiledir/forge" -forgeflowerversion="1.5.380.19" -forgeflowerurl="http://files.minecraftforge.net/maven/net/minecraftforge/forgeflower/$forgeflowerversion/forgeflower-$forgeflowerversion.jar" -# temp use patched version -forgeflowerurl="https://zachbr.keybase.pub/paper/forgeflower-patched/forgeflower-1.5.380.19.jar?dl=1" -forgeflowerbin="$workdir/ForgeFlower/$forgeflowerversion.jar" -# TODO: Make this better? We don't need spigot compat for this stage -forgefloweroptions="-dgs=1 -hdc=0 -asc=1 -udv=1 -jvn=1" -forgeflowercachefile="$decompiledir/forgeflowercache" -forgeflowercachevalue="$forgeflowerurl - $forgeflowerversion - $forgefloweroptions"; -classdir="$decompiledir/classes" -versionjson="$workdir/Minecraft/$minecraftversion/$minecraftversion.json" - -if [[ ! -f "$versionjson" ]]; then - echo "Downloading $minecraftversion JSON Data" - verescaped=$(echo ${minecraftversion} | sed 's/\-pre/ Pre-Release /g' | sed 's/\./\\./g') - urlescaped=$(echo ${verescaped} | sed 's/ /_/g') - verentry=$(curl -s "https://launchermeta.mojang.com/mc/game/version_manifest.json" | grep -oE "\{\"id\": \"${verescaped}\".*${urlescaped}\.json") - jsonurl=$(echo $verentry | grep -oE https:\/\/.*\.json) - curl -o "$versionjson" "$jsonurl" - echo "$versionjson - $jsonurl" -fi - -function downloadLibraries { - group=$1 - groupesc=$(echo ${group} | sed 's/\./\\./g') - grouppath=$(echo ${group} | sed 's/\./\//g') - libdir="$decompiledir/libraries/${group}/" - mkdir -p "$libdir" - shift - for lib in "$@" - do - jar="$libdir/${lib}-sources.jar" - destlib="$libdir/${lib}" - if [ ! -f "$jar" ]; then - libesc=$(echo ${lib} | sed 's/\./\\]./g') - ver=$(grep -oE "${groupesc}:${libesc}:[0-9\.]+" "$versionjson" | sed "s/${groupesc}:${libesc}://g") - echo "Downloading ${group}:${lib}:${ver} Sources" - curl -s -o "$jar" "https://libraries.minecraft.net/${grouppath}/${lib}/${ver}/${lib}-${ver}-sources.jar" - set +e - grep "" "$jar" && grep -oE ".*?" "$jar" && rm "$jar" && echo "Failed to download $jar" && exit 1 - set -e - fi - - if [ ! -d "$destlib/$grouppath" ]; then - echo "Extracting $group:$lib Sources" - mkdir -p "$destlib" - (cd "$destlib" && jar xf "$jar") - fi - done -} - -downloadLibraries "com.mojang" datafixerupper authlib brigadier - -# prep folders -mkdir -p "$workdir/ForgeFlower" -mkdir -p "$spigotdecompiledir" -mkdir -p "$forgedecompiledir" - -echo "Extracting NMS classes..." -if [ ! -d "$classdir" ]; then - mkdir -p "$classdir" - cd "$classdir" - set +e - jar xf "$decompiledir/$minecraftversion-mapped.jar" net/minecraft com/mojang/math - if [ "$?" != "0" ]; then - cd "$basedir" - echo "Failed to extract NMS classes." - exit 1 - fi - set -e -fi - -#needsDecomp=0 -#if [ ! -f "$forgeflowercachefile" ]; then -# needsDecomp=1 -#elif [ "$(cat ${forgeflowercachefile})" != "$forgeflowercachevalue" ]; then -# needsDecomp=1 -#fi -#if [ "$needsDecomp" == "1" ]; then -# # our local cache is now invalidated, we can update forgeflower to get better deobfuscation -# rm -rf "$forgedecompiledir/net" -#fi - -## Forge (for Paper mc-dev imports, and dev src folders for unimported files) -#if [ ! -d "$forgedecompiledir/net" ] ; then -# echo "Decompiling classes (stage 1)..." -# cd "$basedir" -# -# if [ ! -f "$forgeflowerbin" ]; then -# echo "Downloading ForgeFlower ($forgeflowerversion)..." -# curl -s -o "$forgeflowerbin" "$forgeflowerurl" -# fi -# -# set +e -# java -Ddecomp.renameparams=true -jar "$forgeflowerbin" ${forgefloweroptions} -ind=' ' "$classdir" "$forgedecompiledir" -# if [ "$?" != "0" ]; then -# rm -rf "$forgedecompiledir/net" -# echo "Failed to decompile classes." -# exit 1 -# fi -# echo "$forgeflowercachevalue" > "$forgeflowercachefile" -# set -e -#fi - -# Spigot (for CraftBukkit patches) - -# if we see the old net folder, copy it to spigot to avoid redecompiling -if [ -d "$decompiledir/net" ]; then - cp -r "$decompiledir/net" "$spigotdecompiledir/" -fi - -if [ ! -d "$spigotdecompiledir/net" ]; then - echo "Decompiling classes (stage 2)..." - cd "$basedir" - set +e - java -jar "$workdir/BuildData/bin/fernflower.jar" -dgs=1 -hdc=0 -asc=1 -udv=0 -rsy=1 -aoa=1 "$classdir" "$spigotdecompiledir" - if [ "$?" != "0" ]; then - rm -rf "$spigotdecompiledir/net" - echo "Failed to decompile classes." - exit 1 - fi - set -e -fi - -# set a symlink to current -currentlink="$workdir/Minecraft/current" -if ([ ! -e "$currentlink" ] || [ -L "$currentlink" ]) && [ "$windows" == "false" ]; then - set +e - echo "Pointing $currentlink to $minecraftversion" - rm -rf "$currentlink" || true - ln -sfn "$minecraftversion" "$currentlink" || echo "Failed to set current symlink" -fi - -) diff --git a/scripts/functions.sh b/scripts/functions.sh deleted file mode 100755 index fecad9922d..0000000000 --- a/scripts/functions.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -gitcmd="git -c commit.gpgsign=false" - -color() { - if [ $2 ]; then - printf "\e[$1;$2m" - else - printf "\e[$1m" - fi -} -colorend() { - printf "\e[m" -} - -paperstash() { - STASHED=$($gitcmd stash 2>/dev/null|| return 0) # errors are ok -} - -paperunstash() { - if [[ "$STASHED" != "No local changes to save" ]] ; then - $gitcmd stash pop 2>/dev/null|| return 0 # errors are ok - fi -} diff --git a/scripts/importmcdev.sh b/scripts/importmcdev.sh deleted file mode 100755 index 3e8c8e2169..0000000000 --- a/scripts/importmcdev.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -nms="net/minecraft" -export MODLOG="" -PS1="$" -basedir="$(cd "$1" && pwd -P)" -source "$basedir/scripts/functions.sh" -gitcmd="git -c commit.gpgsign=false" - -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -decompiledir="$workdir/Minecraft/$minecraftversion/forge" -# replace for now -decompiledir="$workdir/Minecraft/$minecraftversion/spigot" -export importedmcdev="" -function import { - export importedmcdev="$importedmcdev $1" - file="${1}.java" - target="$workdir/Spigot/Spigot-Server/src/main/java/$nms/$file" - base="$decompiledir/$nms/$file" - - if [[ ! -f "$target" ]]; then - export MODLOG="$MODLOG Imported $file from mc-dev\n"; - #echo "Copying $base to $target" - mkdir -p "$(dirname "$target")" - cp "$base" "$target" || exit 1 - else - echo "UN-NEEDED IMPORT: $file" - fi -} - -function importLibrary { - group=$1 - lib=$2 - prefix=$3 - shift 3 - for file in "$@"; do - file="$prefix/$file" - target="$workdir/Spigot/Spigot-Server/src/main/java/${file}" - targetdir=$(dirname "$target") - mkdir -p "${targetdir}" - base="$workdir/Minecraft/$minecraftversion/libraries/${group}/${lib}/$file" - if [ ! -f "$base" ]; then - echo "Missing $base" - exit 1 - fi - export MODLOG="$MODLOG Imported $file from $lib\n"; - sed 's/\r$//' "$base" > "$target" || exit 1 - done -} - -( - cd "$workdir/Spigot/Spigot-Server/" - lastlog=$($gitcmd log -1 --oneline) - if [[ "$lastlog" = *"mc-dev Imports"* ]]; then - $gitcmd reset --hard HEAD^ - fi -) - - -files=$(cat "$basedir/Spigot-Server-Patches/"* | grep "+++ b/src/main/java/net/minecraft/" | sort | uniq | sed 's/\+\+\+ b\/src\/main\/java\/net\/minecraft\///g') - -nonnms=$(grep -R "new file mode" -B 1 "$basedir/Spigot-Server-Patches/" | grep -v "new file mode" | grep -oE --color=none "net\/minecraft\/.*.java" | sed 's/.*\/net\/minecraft\///g') -function containsElement { - local e - for e in "${@:2}"; do - [[ "$e" == "$1" ]] && return 0; - done - return 1 -} -set +e -for f in $files; do - containsElement "$f" ${nonnms[@]} - if [ "$?" == "1" ]; then - if [ ! -f "$workdir/Spigot/Spigot-Server/src/main/java/net/minecraft/$f" ]; then - f="$(echo "$f" | sed 's/.java//g')" - if [ ! -f "$decompiledir/$nms/$f.java" ]; then - echo "$(color 1 31) ERROR!!! Missing NMS$(color 1 34) $f $(colorend)"; - error=true - else - import $f - fi - fi - fi -done -if [ -n "$error" ]; then - exit 1 -fi - -######################################################## -######################################################## -######################################################## -# NMS IMPORTS -# Temporarily add new NMS dev imports here before you run paper patch -# but after you have paper rb'd your changes, remove the line from this file before committing. -# we do not need any lines added to this file for NMS - -# import FileName - - -######################################################## -######################################################## -######################################################## -# LIBRARY IMPORTS -# These must always be mapped manually, no automatic stuff -# -# # group # lib # prefix # many files - -# dont forget \ at end of each line but last -importLibrary com.mojang authlib com/mojang/authlib yggdrasil/YggdrasilGameProfileRepository.java -importLibrary com.mojang datafixerupper com/mojang/datafixers DataFixerBuilder.java -importLibrary com.mojang datafixerupper com/mojang/datafixers/util Either.java -importLibrary com.mojang datafixerupper com/mojang/serialization/codecs KeyDispatchCodec.java -importLibrary com.mojang datafixerupper com/mojang/serialization Dynamic.java - -######################################################## -######################################################## -######################################################## -set -e -cd "$workdir/Spigot/Spigot-Server/" -rm -rf nms-patches applyPatches.sh makePatches.sh >/dev/null 2>&1 -$gitcmd add --force . -A >/dev/null 2>&1 -echo -e "mc-dev Imports\n\n$MODLOG" | $gitcmd commit . -F - -) diff --git a/scripts/init.sh b/scripts/init.sh deleted file mode 100755 index 8b1929c836..0000000000 --- a/scripts/init.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -spigotdecompiledir="$workdir/Minecraft/$minecraftversion/spigot" -nms="$spigotdecompiledir" -cb="src/main/java" -gitcmd="git -c commit.gpgsign=false" - -# https://stackoverflow.com/a/38595160 -# https://stackoverflow.com/a/800644 -if sed --version >/dev/null 2>&1; then - strip_cr() { - sed -i -- "s/\r//" "$@" - } -else - strip_cr () { - sed -i "" "s/$(printf '\r')//" "$@" - } -fi - -patch=$(which patch 2>/dev/null) -if [ "x$patch" == "x" ]; then - patch="$basedir/hctap.exe" -fi - -# apply patches directly to the file tree -# used to fix issues from upstream source repos -cd "$basedir" -prepatchesdir="$basedir/scripts/pre-source-patches" -for file in $(ls "$prepatchesdir") -do - if [ $file == "README.md" ]; then - continue - fi - - echo "--==-- Applying PRE-SOURCE patch: $file --==--" - $patch -p0 < "$prepatchesdir/$file" -done - -echo "Applying CraftBukkit patches to NMS..." -cd "$workdir/CraftBukkit" -$gitcmd checkout -B patched HEAD >/dev/null 2>&1 -rm -rf "$cb/net" -# create baseline NMS import so we can see diff of what CB changed -while IFS= read -r -d '' file -do - patchFile="$file" - file="$(echo "$file" | cut -d "/" -f2- | cut -d. -f1).java" - mkdir -p "$(dirname $cb/"$file")" - cp "$nms/$file" "$cb/$file" -done < <(find nms-patches -type f -print0) -$gitcmd add --force src -$gitcmd commit -m "Minecraft $ $(date)" --author="Vanilla " - -# apply patches -while IFS= read -r -d '' file -do - patchFile="$file" - file="$(echo "$file" | cut -d "/" -f2- | cut -d. -f1).java" - - echo "Patching $file < $patchFile" - set +e - strip_cr "$nms/$file" > /dev/null - set -e - - "$patch" -d src/main/java -p 1 < "$patchFile" -done < <(find nms-patches -type f -print0) - -$gitcmd add --force src -$gitcmd commit -m "CraftBukkit $ $(date)" --author="CraftBukkit " -$gitcmd checkout -f HEAD~2 -) diff --git a/scripts/makemcdevsrc.sh b/scripts/makemcdevsrc.sh deleted file mode 100755 index bd86947f8d..0000000000 --- a/scripts/makemcdevsrc.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" - -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -decompiledir="$workdir/Minecraft/$minecraftversion" -nms="$decompiledir/spigot/net/minecraft" -papernms="$basedir/Paper-Server/src/main/java/net/minecraft" -mcdevsrc="${decompiledir}/src/net/minecraft" -rm -rf "${mcdevsrc}" -mkdir -p "${mcdevsrc}" -cd "${nms}" - -for file in $(find . -name '*.java') -do - if [ ! -f "${papernms}/${file}" ]; then - destdir="${mcdevsrc}"/$(dirname "${file}") - mkdir -p "${destdir}" - cp "${file}" "${destdir}" - fi -done - -cd "$basedir" -echo "Built $decompiledir/src to be included in your project for src access"; -) diff --git a/scripts/paperclip.sh b/scripts/paperclip.sh deleted file mode 100755 index 2722ca3dda..0000000000 --- a/scripts/paperclip.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -mcver=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -paperjar="$basedir/Paper-Server/target/paper-$mcver.jar" -vanillajar="$workdir/Minecraft/$mcver/$mcver.jar" - -( - cd "$workdir/Paperclip" - mvn clean package "-Dmcver=$mcver" "-Dpaperjar=$paperjar" "-Dvanillajar=$vanillajar" -) -cp "$workdir/Paperclip/assembly/target/paperclip-${mcver}.jar" "$basedir/paperclip.jar" - -echo "" -echo "" -echo "" -echo "Build success!" -echo "Copied final jar to $(cd "$basedir" && pwd -P)/paperclip.jar" -) || exit 1 diff --git a/scripts/pre-source-patches/README.md b/scripts/pre-source-patches/README.md deleted file mode 100644 index f91d42efd0..0000000000 --- a/scripts/pre-source-patches/README.md +++ /dev/null @@ -1,16 +0,0 @@ -Files in this directory are applied directly to the tree before any other -patches. - -These patches are always applied directly from the root of the repository. -"$basedir" - -This allows us to fix malformed patch files and other changes from upstream. -This is not intended to replace any other system and should not be used in -place of the existing specific patch directories. - -Documentation is intentionally sparse to avoid being misused. - -`diff -ruN originalfile changedfile` - -See the man pages on diff and patch. - diff --git a/scripts/rebuildPatches.sh b/scripts/rebuildPatches.sh deleted file mode 100755 index a910d6f23d..0000000000 --- a/scripts/rebuildPatches.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env bash - -( -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -source "$basedir/scripts/functions.sh" -gitcmd="git -c commit.gpgsign=false -c core.safecrlf=false" - -echo "Rebuilding patch files from current fork state..." -nofilter="0" -if [ "$2" == "nofilter" ] || [ "$2" == "noclean" ]; then - nofilter="1" -fi -function cleanupPatches { - cd "$1" - for patch in *.patch; do - echo "$patch" - diffs=$($gitcmd diff --staged "$patch" | grep --color=none -E "^(\+|\-)" | grep --color=none -Ev "(\-\-\- a|\+\+\+ b|^.index)") - - if [ "x$diffs" == "x" ] ; then - $gitcmd reset HEAD "$patch" >/dev/null - $gitcmd checkout -- "$patch" >/dev/null - fi - done -} - -function savePatches { - what=$1 - what_name=$(basename "$what") - target=$2 - echo "Formatting patches for $what..." - - cd "$basedir/${what_name}-Patches/" - if [ -d "$basedir/$target/.git/rebase-apply" ]; then - # in middle of a rebase, be smarter - echo "REBASE DETECTED - PARTIAL SAVE" - last=$(cat "$basedir/$target/.git/rebase-apply/last") - next=$(cat "$basedir/$target/.git/rebase-apply/next") - orderedfiles=$(find . -name "*.patch" | sort) - for i in $(seq -f "%04g" 1 1 $last) - do - if [ $i -lt $next ]; then - rm $(echo "$orderedfiles{@}" | sed -n "${i}p") - fi - done - else - rm -rf *.patch - fi - - cd "$basedir/$target" - - $gitcmd format-patch --zero-commit --full-index --no-signature --no-stat -N -o "$basedir/${what_name}-Patches/" upstream/upstream >/dev/null - cd "$basedir" - $gitcmd add --force -A "$basedir/${what_name}-Patches" - if [ "$nofilter" == "0" ]; then - cleanupPatches "$basedir/${what_name}-Patches" - fi - echo " Patches saved for $what to $what_name-Patches/" -} - -savePatches "$workdir/Spigot/Spigot-API" "Paper-API" -if [ -f "$basedir/Paper-API/.git/patch-apply-failed" ]; then - echo "$(color 1 31)[[[ WARNING ]]] $(color 1 33)- Not saving Paper-Server as it appears Paper-API did not apply clean.$(colorend)" - echo "$(color 1 33)If this is a mistake, delete $(color 1 34)Paper-API/.git/patch-apply-failed$(color 1 33) and run rebuild again.$(colorend)" - echo "$(color 1 33)Otherwise, rerun ./paper patch to have a clean Paper-API apply so the latest Paper-Server can build.$(colorend)" -else - savePatches "$workdir/Spigot/Spigot-Server" "Paper-Server" -fi -) || exit 1 diff --git a/scripts/remap.sh b/scripts/remap.sh deleted file mode 100755 index 7458070127..0000000000 --- a/scripts/remap.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env bash - -( -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion="$(cat "${workdir}/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4)" -minecraftserverurl=$(cat "${workdir}/BuildData/info.json" | grep serverUrl | cut -d '"' -f 4) -minecrafthash=$(cat "${workdir}/BuildData/info.json" | grep minecraftHash | cut -d '"' -f 4) -accesstransforms="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep accessTransforms | cut -d '"' -f 4) -classmappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep classMappings | cut -d '"' -f 4) -membermappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep memberMappings | cut -d '"' -f 4) -packagemappings="$workdir/BuildData/mappings/"$(cat "${workdir}/BuildData/info.json" | grep packageMappings | cut -d '"' -f 4) -decompiledir="$workdir/Minecraft/$minecraftversion" -jarpath="$decompiledir/$minecraftversion" -mkdir -p "$decompiledir" - -echo "Downloading unmapped vanilla jar..." -if [ ! -f "$jarpath.jar" ]; then - curl -s -o "$jarpath.jar" "$minecraftserverurl" - if [ "$?" != "0" ]; then - echo "Failed to download the vanilla server jar. Check connectivity or try again later." - exit 1 - fi -fi - -# OS X & FreeBSD don't have md5sum, just md5 -r -command -v md5sum >/dev/null 2>&1 || { - command -v md5 >/dev/null 2>&1 && { - shopt -s expand_aliases - alias md5sum='md5 -r' - echo "md5sum command not found, using an alias instead" - } || { - echo >&2 "No md5sum or md5 command found" - exit 1 - } -} - -checksum=$(md5sum "$jarpath.jar" | cut -d ' ' -f 1) -if [ "$checksum" != "$minecrafthash" ]; then - echo "The MD5 checksum of the downloaded server jar does not match the BuildData hash." - exit 1 -fi - -# These specialsource commands are from https://hub.spigotmc.org/stash/projects/SPIGOT/repos/builddata/browse/info.json -echo "Applying class mappings..." -if [ ! -f "$jarpath-cl.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource-2.jar" map --only . --only net/minecraft --only com/mojang/math --auto-lvt BASIC --auto-member SYNTHETIC -i "$jarpath.jar" -m "$classmappings" -o "$jarpath-cl.jar" 1>/dev/null - if [ "$?" != "0" ]; then - echo "Failed to apply class mappings." - exit 1 - fi -fi - -echo "Applying member mappings..." -if [ ! -f "$jarpath-m.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource-2.jar" map --only . --only net/minecraft --only com/mojang/math --auto-member LOGGER --auto-member TOKENS -i "$jarpath-cl.jar" -m "$membermappings" -o "$jarpath-m.jar" 1>/dev/null - if [ "$?" != "0" ]; then - echo "Failed to apply member mappings." - exit 1 - fi -fi - -echo "Creating remapped jar..." -if [ ! -f "$jarpath-mapped.jar" ]; then - java -jar "$workdir/BuildData/bin/SpecialSource.jar" --only . --only net/minecraft --only com/mojang/math -i "$jarpath-m.jar" --access-transformer "$accesstransforms" -m "$packagemappings" -o "$jarpath-mapped.jar" 1>/dev/null - if [ "$?" != "0" ]; then - echo "Failed to create remapped jar." - exit 1 - fi -fi - -echo "Installing remapped jar..." -cd "$workdir/CraftBukkit" # Need to be in a directory with a valid POM at the time of install. -mvn install:install-file -q -Dfile="$jarpath-mapped.jar" -Dpackaging=jar -DgroupId=io.papermc -DartifactId=minecraft-server -Dversion="$minecraftversion-SNAPSHOT" -if [ "$?" != "0" ]; then - echo "Failed to install remapped jar." - exit 1 -fi -) diff --git a/scripts/requireDeps.sh b/scripts/requireDeps.sh deleted file mode 100755 index 8437accfaa..0000000000 --- a/scripts/requireDeps.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -set -ue - -# Check if an application is on the PATH. -# If it is not, return with non-zero. -_is_dep_available() { - command -v "$1" >/dev/null || (echo "\`$1\` ${2:-command was not found in the path and is a required dependency}"; return 1) -} - -if [ -z "${1:-}" ]; then - # No specific dependency was found; let's just check for all required ones. - _is_dep_available git - _is_dep_available patch - _is_dep_available mvn - _is_dep_available curl - - _is_dep_available javac "was not found; you can download the JDK from https://adoptopenjdk.net/ or via your package manager" - _is_dep_available jar "was not found; you can download the JDK from https://adoptopenjdk.net/ or via your package manager" -else - # Require all dependencies provided. - for dep in $@; do - _is_dep_available "$dep" - done -fi - -# vim: set ff=unix autoindent ts=4 sw=4 tw=0 et : diff --git a/scripts/testServer.sh b/scripts/testServer.sh deleted file mode 100755 index 3fabfcd0bf..0000000000 --- a/scripts/testServer.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env bash - -set -e -PS1="$" -basedir="$(cd "$1" && pwd -P)" -workdir="$basedir/work" -minecraftversion=$(cat "$workdir/BuildData/info.json" | grep minecraftVersion | cut -d '"' -f 4) -gitcmd="git -c commit.gpgsign=false" - -# -# FUNCTIONS -# -source "$basedir"/scripts/functions.sh - -updateTest() { - paperstash - $gitcmd reset --hard origin/master - paperunstash -} - -papertestdir="${PAPER_TEST_DIR:-$workdir/test-server}" - -mkdir -p "$papertestdir" -cd "$papertestdir" - -# -# SKELETON CHECK -# - -if [ ! -d .git ]; then - $gitcmd init - $gitcmd remote add origin ${PAPER_TEST_SKELETON:-https://github.com/PaperMC/PaperTestServer} - $gitcmd fetch origin - updateTest -elif [ "$2" == "update" ] || [ "$3" == "update" ]; then - updateTest -fi - -if [ ! -f server.properties ] || [ ! -d plugins ]; then - echo " " - echo " Checking out Test Server Skeleton" - updateTest -fi - - -# -# EULA CHECK -# - -if [ -z "$(grep true eula.txt 2>/dev/null)" ]; then - echo - echo "$(color 32) It appears you have not agreed to Mojangs EULA yet! Press $(color 1 33)y$(colorend) $(color 32)to confirm agreement to" - read -p " Mojangs EULA found at:$(color 1 32) https://account.mojang.com/documents/minecraft_eula $(colorend) " -n 1 -r - echo "" - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "$(color 1 31)Aborted$(colorend)" - exit; - fi - echo "eula=true" > eula.txt -fi - -# -# JAR CHECK -# - -folder="$basedir/Paper-Server" -jar="$folder/target/paper-${minecraftversion}.jar" -if [ ! -z "$PAPER_JAR" ]; then - jar="$PAPER_JAR" -fi -if [ ! -d "$folder" ]; then -( - echo "Building Patched Repo" - cd "$basedir" - ./paper patch -) -fi - -if [ "$2" == "build" ] || [ "$3" == "build" ]; then -( - echo "Building Paper" - cd "$basedir" - mvn package -) -fi -# -# JVM FLAGS -# - -if [ -f "$jar" ]; then - cp "$jar" paper.jar -fi -baseargs="-server -Xms${PAPER_MIN_TEST_MEMORY:-512M} -Xmx${PAPER_TEST_MEMORY:-2G} -Dfile.encoding=UTF-8 -XX:MaxGCPauseMillis=150 -XX:+UseG1GC " -baseargs="$baseargs -DIReallyKnowWhatIAmDoingISwear=1 " -baseargs="$baseargs -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=60 " -baseargs="$baseargs -XX:InitiatingHeapOccupancyPercent=10 -XX:G1MixedGCLiveThresholdPercent=80 " -baseargs="$baseargs -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5100" - - -cmd="java ${PAPER_TEST_BASE_JVM_ARGS:-$baseargs} ${PAPER_TEST_EXTRA_JVM_ARGS} -jar paper.jar ${PAPER_TEST_APP_ARGS:-} nogui" -screen_command="screen -DURS papertest $cmd" -tmux_command="tmux new-session -A -s Paper -n 'Paper Test' -c '$(pwd)' '$cmd'" - -# -# MULTIPLEXER CHOICE -# - -multiplex=${PAPER_TEST_MULTIPLEXER} - -if [ ! -z "$PAPER_NO_MULTIPLEX" ]; then - cmd="$cmd" -elif [ "$multiplex" == "screen" ]; then - if command -v "screen" >/dev/null 2>&1 ; then - cmd="$screen_command" - else - echo "screen not found" - exit 1 - fi -elif [ "$multiplex" == "tmux" ] ; then - if command -v "tmux" >/dev/null 2>&1 ; then - cmd="$tmux_command" - else - echo "tmux not found" - exit 1 - fi -else - if command -v "screen" >/dev/null 2>&1 ; then - cmd="$screen_command" - elif command -v "tmux" >/dev/null 2>&1 ; then - cmd="$tmux_command" - else - echo "screen or tmux not found - it is strongly recommended to install either" - echo "No terminal multiplexer will be used" - fi -fi - -# -# START / LOG -# - -if [ ! -z "$PAPER_TEST_COMMAND_WRAPPER" ]; then - $PAPER_TEST_COMMAND_WRAPPER $cmd -else - echo "Running command: $cmd" - echo "In directory: $(pwd)" - #sleep 1 - /usr/bin/env bash -c "$cmd" -fi diff --git a/scripts/upstreamMerge.sh b/scripts/upstreamMerge.sh index f011f708fc..319a71695d 100755 --- a/scripts/upstreamMerge.sh +++ b/scripts/upstreamMerge.sh @@ -30,11 +30,12 @@ update Spigot if [[ "$2" = "all" || "$2" = "a" ]] ; then update BuildData - update Paperclip fi if [ "$updated" == "1" ]; then echo "Rebuilding patches without filtering to improve apply ability" cd "$basedir" - scripts/rebuildPatches.sh "$basedir" nofilter 1>/dev/null|| exit 1 + ./gradlew cleanCache || exit 1 # todo: Figure out why this is necessary + ./gradlew applyPatches -Dpaperweight.debug=true || exit 1 + ./gradlew rebuildPatches || exit 1 fi ) diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000000..4127fc6b8c --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven("https://papermc.io/repo/repository/maven-public/") + } +} + +rootProject.name = "Paper" + +include("Paper-API", "Paper-Server", "Paper-MojangAPI") diff --git a/work/BuildData b/work/BuildData index f0a5ed1aef..3cec511b16 160000 --- a/work/BuildData +++ b/work/BuildData @@ -1 +1 @@ -Subproject commit f0a5ed1aeff8156ba4afa504e190c838dd1af50c +Subproject commit 3cec511b16ffa31cb414997a14be313716882e12 diff --git a/work/Bukkit b/work/Bukkit index 7e29f76544..2dbec58427 160000 --- a/work/Bukkit +++ b/work/Bukkit @@ -1 +1 @@ -Subproject commit 7e29f7654411f0a17ebbcc2c3f6a7dfe93bff39e +Subproject commit 2dbec584278268fc46bfb5520fd18bde18d33308 diff --git a/work/CraftBukkit b/work/CraftBukkit index 296df56673..68d403188a 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit 296df56673771692593156995684ab8041925d9d +Subproject commit 68d403188aacb73c8c9d64c16e9d72e6514b0bac diff --git a/work/Paperclip b/work/Paperclip deleted file mode 160000 index 6776c66987..0000000000 --- a/work/Paperclip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6776c66987a021a1c0db55b2e21c883660acc19f diff --git a/work/Spigot b/work/Spigot index 9fb885e86d..101ebb63b2 160000 --- a/work/Spigot +++ b/work/Spigot @@ -1 +1 @@ -Subproject commit 9fb885e86def1d9d86e25233c9b5a4de45b7a09d +Subproject commit 101ebb63b2531abf0ac868af41d57322d05931fa