diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9399b666c..fa85615bb 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -11,13 +11,14 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.commits[0].message, '[ci-skip]')"
steps:
- - uses: actions/checkout@v3
- - uses: gradle/wrapper-validation-action@v1
- - uses: actions/setup-java@v3.6.0
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
with:
distribution: temurin
- java-version: 17
+ java-version: 21
cache: 'gradle'
+ - uses: gradle/wrapper-validation-action@v2
+ - uses: gradle/actions/setup-gradle@v3
- name: Configure Git
run: git config --global user.email "no-reply@github.com" && git config --global user.name "Github Actions"
- name: Apply Patches
diff --git a/.gitignore b/.gitignore
index dcb2438fd..1fd301e1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,4 +56,6 @@ build-data/
Purpur-API
Purpur-MojangAPI
Purpur-Server
+paper-api-generator
*.jar
+test-plugin.settings.gradle.kts
diff --git a/.idea/runConfigurations/Run_Purpur_Paperclip_Jar.xml b/.idea/runConfigurations/Run_Purpur_Paperclip_Jar.xml
index 00aa84396..05a5aa732 100644
--- a/.idea/runConfigurations/Run_Purpur_Paperclip_Jar.xml
+++ b/.idea/runConfigurations/Run_Purpur_Paperclip_Jar.xml
@@ -1,11 +1,11 @@
-
+
-
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Upstream_Paper__createReobfPaperclipJar_.xml b/.idea/runConfigurations/Upstream_Paper__createMojmapPaperclipJar_.xml
similarity index 82%
rename from .idea/runConfigurations/Upstream_Paper__createReobfPaperclipJar_.xml
rename to .idea/runConfigurations/Upstream_Paper__createMojmapPaperclipJar_.xml
index 8911b6115..4145189fc 100644
--- a/.idea/runConfigurations/Upstream_Paper__createReobfPaperclipJar_.xml
+++ b/.idea/runConfigurations/Upstream_Paper__createMojmapPaperclipJar_.xml
@@ -1,5 +1,5 @@
-
+
@@ -10,7 +10,7 @@
@@ -23,4 +23,4 @@
-
+
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 118d9bc9f..6538e3a35 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,11 +4,11 @@ Purpur is happy you're willing to contribute to our projects. We are usually
very lenient with all submitted PRs, but there are still some guidelines you
can follow to make the approval process go more smoothly.
-## Use a Personal Fork and not Organization
+## Use a Personal Fork and not an Organization
Purpur will routinely modify your PR, whether it's a quick rebase or to take care
of any minor nitpicks we might have. Often, it's better for us to solve these
-problems for you than make you go back and forth trying to fix it yourself.
+problems for you than make you go back and forth trying to fix them yourself.
Unfortunately, if you use an organization for your PR, it prevents Purpur from
modifying it. This requires us to manually merge your PR, resulting in us
@@ -27,12 +27,12 @@ which can be obtained in (most) package managers such as `apt` (Debian / Ubuntu;
you will most likely use this for WSL), `homebrew` (macOS / Linux), and more:
- `git` (package `git` everywhere);
-- A Java 16 or later JDK (packages vary, use Google/DuckDuckGo/etc.).
+- A Java 21 or later JDK (packages vary, use Google/DuckDuckGo/etc.).
- [Adoptium](https://adoptium.net/) has builds for most operating systems.
- - Purpur requires JDK 16 to build, however makes use of Gradle's
+ - Purpur requires JDK 21 to build, however, makes use of Gradle's
[Toolchains](https://docs.gradle.org/current/userguide/toolchains.html)
- feature to allow building with only JRE 8 or later installed. (Gradle will
- automatically provision JDK 16 for compilation if it cannot find an existing
+ feature to allow building with only JRE 11 or later installed. (Gradle will
+ automatically provision JDK 21 for compilation if it cannot find an existing
install).
If you're on Windows, check
@@ -42,16 +42,16 @@ If you're compiling with Docker, you can use Adoptium's
[`eclipse-temurin`](https://hub.docker.com/_/eclipse-temurin/) images like so:
```console
-# docker run -it -v "$(pwd)":/data --rm eclipse-temurin:16.0.2_7-jdk bash
+# docker run -it -v "$(pwd)":/data --rm eclipse-temurin:21.0.3_9-jdk bash
Pulling image...
root@abcdefg1234:/# javac -version
-javac 16.0.2
+javac 21.0.3
```
## Understanding Patches
-Purpur is mostly patches and extensions to Paper/Spigot. These patches/extensions are
+Paper is mostly patches and extensions to Spigot. These patches/extensions are
split into different directories which target certain parts of the code. These
directories are:
@@ -66,7 +66,7 @@ Assuming you have already forked the repository:
1. Clone your fork to your local machine;
2. Type `./gradlew applyPatches` in a terminal to apply the changes from upstream.
- On Windows, leave out the `./` at the beginning for all `gradlew` commands;
+ On Windows, replace the `./` with `.\` at the beginning for all `gradlew` commands;
3. cd into `Purpur-Server` for server changes, and `Purpur-API` for API changes.
+
+
diff --git a/patches/server/0299-Stored-Bee-API.patch b/patches/server/0284-Stored-Bee-API.patch
similarity index 71%
rename from patches/server/0299-Stored-Bee-API.patch
rename to patches/server/0284-Stored-Bee-API.patch
index b82401931..525c836e8 100644
--- a/patches/server/0299-Stored-Bee-API.patch
+++ b/patches/server/0284-Stored-Bee-API.patch
@@ -5,18 +5,18 @@ Subject: [PATCH] Stored Bee API
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 7b82842b97ce795745cf6ee6399f618c55acbbf3..d6316aec8860ed3e579c1adb0b4578517ce0b885 100644
+index d8efb00c325448d566c59418fe22268c6eb4cfce..f7a6ab35c95ffda73f17843916ddb624ad290b42 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
-@@ -130,6 +130,22 @@ public class BeehiveBlockEntity extends BlockEntity {
+@@ -146,11 +146,33 @@ public class BeehiveBlockEntity extends BlockEntity {
return list;
}
+ // Purpur start
-+ public List releaseBee(BlockState iblockdata, BeeData data, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, boolean force) {
++ public List releaseBee(BlockState iblockdata, BeehiveBlockEntity.BeeData data, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, boolean force) {
+ List list = Lists.newArrayList();
+
-+ BeehiveBlockEntity.releaseBee(this.level, this.worldPosition, iblockdata, data, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force);
++ BeehiveBlockEntity.releaseOccupant(this.level, this.worldPosition, iblockdata, data.occupant, list, tileentitybeehive_releasestatus, this.savedFlowerPos, force);
+
+ if (!list.isEmpty()) {
+ stored.remove(data);
@@ -28,10 +28,8 @@ index 7b82842b97ce795745cf6ee6399f618c55acbbf3..d6316aec8860ed3e579c1adb0b457851
+ }
+ // Purpur end
+
- public void addOccupant(Entity entity, boolean hasNectar) {
- this.addOccupantWithPresetTicks(entity, hasNectar, 0);
- }
-@@ -139,6 +155,12 @@ public class BeehiveBlockEntity extends BlockEntity {
+ @VisibleForDebug
+ public int getOccupantCount() {
return this.stored.size();
}
@@ -44,20 +42,20 @@ index 7b82842b97ce795745cf6ee6399f618c55acbbf3..d6316aec8860ed3e579c1adb0b457851
// Paper start - Add EntityBlockStorage clearEntities
public void clearBees() {
this.stored.clear();
-@@ -425,9 +447,9 @@ public class BeehiveBlockEntity extends BlockEntity {
- private BeeReleaseStatus() {}
+@@ -471,9 +493,9 @@ public class BeehiveBlockEntity extends BlockEntity {
+ }
}
- private static class BeeData {
+ public static class BeeData { // Purpur - change from private to public
-- final CompoundTag entityData;
-+ public final CompoundTag entityData; // Purpur - make public
- int ticksInHive;
- int exitTickCounter; // Paper - separate counter for checking if bee should exit to reduce exit attempts
- final int minOccupationTicks;
+- private final BeehiveBlockEntity.Occupant occupant;
++ public final BeehiveBlockEntity.Occupant occupant; // Purpur - make public
+ private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
+ private int ticksInHive;
+
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
-index 2b906fccdb0a5ecddaf487ee931d05b511f84351..7011f0c22b4ede8423ed702d5adb9674aa8a315c 100644
+index 1a2a05160ba51d9c75f1ae6ae61d944d81428722..3beb26ad2ef0fded49a8da8c5dec64f9508c1995 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java
@@ -16,8 +16,15 @@ import org.bukkit.entity.Bee;
@@ -75,7 +73,7 @@ index 2b906fccdb0a5ecddaf487ee931d05b511f84351..7011f0c22b4ede8423ed702d5adb9674
+ // Purpur end
}
- protected CraftBeehive(CraftBeehive state) {
+ protected CraftBeehive(CraftBeehive state, Location location) {
@@ -75,15 +82,54 @@ public class CraftBeehive extends CraftBlockEntityState impl
bees.add((Bee) bee.getBukkitEntity());
}
@@ -120,19 +118,20 @@ index 2b906fccdb0a5ecddaf487ee931d05b511f84351..7011f0c22b4ede8423ed702d5adb9674
public void addEntity(Bee entity) {
Preconditions.checkArgument(entity != null, "Entity must not be null");
-+ int length = getSnapshot().getStored().size(); // Purpur
- getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false);
+- this.getSnapshot().addOccupant(((CraftBee) entity).getHandle());
++ int length = this.getSnapshot().getStored().size(); // Purpur
++ getSnapshot().addOccupant(((CraftBee) entity).getHandle());
+
+ // Purpur start - check if new bee was added, and if yes, add to stored bees
-+ List s = getSnapshot().getStored();
-+ if(length < s.size()) {
-+ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(s.get(s.size() - 1), this));
++ List storedBeeData = this.getSnapshot().getStored();
++ if(length < storedBeeData.size()) {
++ storage.add(new org.purpurmc.purpur.entity.PurpurStoredBee(storedBeeData.getLast(), this));
+ }
+ // Purpur end
}
@Override
-@@ -95,6 +141,7 @@ public class CraftBeehive extends CraftBlockEntityState impl
+@@ -100,6 +146,7 @@ public class CraftBeehive extends CraftBlockEntityState impl
@Override
public void clearEntities() {
getSnapshot().clearBees();
@@ -142,15 +141,18 @@ index 2b906fccdb0a5ecddaf487ee931d05b511f84351..7011f0c22b4ede8423ed702d5adb9674
}
diff --git a/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java
new file mode 100644
-index 0000000000000000000000000000000000000000..8efca1d91188ac4db911a8eb0fa9ea2cc3c48e28
+index 0000000000000000000000000000000000000000..7608bf0981fa0d37031e51e57e4086cb5ec4c88b
--- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/entity/PurpurStoredBee.java
-@@ -0,0 +1,102 @@
+@@ -0,0 +1,106 @@
+package org.purpurmc.purpur.entity;
+
+import io.papermc.paper.adventure.PaperAdventure;
+import net.kyori.adventure.text.Component;
++import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.Tag;
++import net.minecraft.server.MinecraftServer;
++import net.minecraft.world.item.component.CustomData;
+import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
+import org.bukkit.block.EntityBlockStorage;
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
@@ -176,12 +178,13 @@ index 0000000000000000000000000000000000000000..8efca1d91188ac4db911a8eb0fa9ea2c
+ this.handle = data;
+ this.blockStorage = blockStorage;
+
-+ this.customName = handle.entityData.contains("CustomName", Tag.TAG_STRING)
-+ ? PaperAdventure.asAdventure(net.minecraft.network.chat.Component.Serializer.fromJson(handle.entityData.getString("CustomName")))
++ CompoundTag customData = handle.occupant.entityData().copyTag();
++ this.customName = customData.contains("CustomName")
++ ? PaperAdventure.asAdventure(net.minecraft.network.chat.Component.Serializer.fromJson(customData.getString("CustomName"), MinecraftServer.getDefaultRegistryAccess()))
+ : null;
+
-+ if(handle.entityData.contains("BukkitValues", Tag.TAG_COMPOUND)) {
-+ this.persistentDataContainer.putAll(handle.entityData.getCompound("BukkitValues"));
++ if(customData.contains("BukkitValues", Tag.TAG_COMPOUND)) {
++ this.persistentDataContainer.putAll(customData.getCompound("BukkitValues"));
+ }
+ }
+
@@ -240,11 +243,11 @@ index 0000000000000000000000000000000000000000..8efca1d91188ac4db911a8eb0fa9ea2c
+
+ @Override
+ public void update() {
-+ handle.entityData.put("BukkitValues", this.persistentDataContainer.toTagCompound());
++ handle.occupant.entityData().copyTag().put("BukkitValues", this.persistentDataContainer.toTagCompound());
+ if(customName == null) {
-+ handle.entityData.remove("CustomName");
++ handle.occupant.entityData().copyTag().remove("CustomName");
+ } else {
-+ handle.entityData.putString("CustomName", net.minecraft.network.chat.Component.Serializer.toJson(PaperAdventure.asVanilla(customName)));
++ handle.occupant.entityData().copyTag().putString("CustomName", net.minecraft.network.chat.Component.Serializer.toJson(PaperAdventure.asVanilla(customName), MinecraftServer.getDefaultRegistryAccess()));
+ }
+ }
+}
diff --git a/patches/server/0300-Shears-can-defuse-TNT.patch b/patches/server/0285-Shears-can-defuse-TNT.patch
similarity index 88%
rename from patches/server/0300-Shears-can-defuse-TNT.patch
rename to patches/server/0285-Shears-can-defuse-TNT.patch
index 2fd4164b0..5fb2d5add 100644
--- a/patches/server/0300-Shears-can-defuse-TNT.patch
+++ b/patches/server/0285-Shears-can-defuse-TNT.patch
@@ -8,13 +8,13 @@ Shears can now defuse TNT. Each world can have a configured chance for the TNT t
By default the option is disabled to avoid breaking any possible vanilla mechanics.
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 4ce3e69970dd9eb251d0538a2d233ca30e9e5e47..afc65b8bb7e7f7f70a25f2d869412ed325b658da 100644
+index f1f352ec0e51f5db59254841a06c176c5a876fc9..dff0e7b08b973a1b29f916e63d3e4778d6c56cdc 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
-@@ -175,4 +175,29 @@ public class PrimedTnt extends Entity implements TraceableEntity {
+@@ -193,4 +193,29 @@ public class PrimedTnt extends Entity implements TraceableEntity {
return !level().paperConfig().fixes.preventTntFromMovingInWater && super.isPushedByFluid();
}
- // Paper end
+ // Paper end - Option to prevent TNT from moving in water
+ // Purpur start - Shears can defuse TNT
+ @Override
+ public net.minecraft.world.InteractionResult interact(net.minecraft.world.entity.player.Player player, net.minecraft.world.InteractionHand hand) {
@@ -28,7 +28,7 @@ index 4ce3e69970dd9eb251d0538a2d233ca30e9e5e47..afc65b8bb7e7f7f70a25f2d869412ed3
+ new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.TNT));
+ tntItem.setPickUpDelay(10);
+
-+ inHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand));
++ inHand.hurtAndBreak(1, player, LivingEntity.getSlotForHand(hand));
+ level().addFreshEntity(tntItem, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CUSTOM);
+
+ this.playSound(net.minecraft.sounds.SoundEvents.SHEEP_SHEAR);
@@ -42,10 +42,10 @@ index 4ce3e69970dd9eb251d0538a2d233ca30e9e5e47..afc65b8bb7e7f7f70a25f2d869412ed3
+ // Purpur end - Shears can defuse TNT
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-index e7a794ce230c481e39436506facdb77726f96199..ec7c1b39a87f253c52de4d0f3b01e8329aaa723a 100644
+index 03819b5d991d91c2e7f5e2eae50e1a7e4197336b..bd1ae536d975b5a3c54063834fd05255f15d8dad 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-@@ -3219,4 +3219,11 @@ public class PurpurWorldConfig {
+@@ -3282,4 +3282,11 @@ public class PurpurWorldConfig {
cauldronDripstoneWaterFillChance = (float) getDouble("blocks.cauldron.fill-chances.dripstone-water", cauldronDripstoneWaterFillChance);
cauldronDripstoneLavaFillChance = (float) getDouble("blocks.cauldron.fill-chances.dripstone-lava", cauldronDripstoneLavaFillChance);
}
diff --git a/patches/server/0301-Explorer-Map-API.patch b/patches/server/0286-Explorer-Map-API.patch
similarity index 63%
rename from patches/server/0301-Explorer-Map-API.patch
rename to patches/server/0286-Explorer-Map-API.patch
index f4039b193..b5f2c63e7 100644
--- a/patches/server/0301-Explorer-Map-API.patch
+++ b/patches/server/0286-Explorer-Map-API.patch
@@ -5,22 +5,22 @@ Subject: [PATCH] Explorer Map API
diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java
-index c368b437597edf7e165326727ae778a69c3fcc83..fed5bfb02ab7d6c1d1d9bf993fda5b3f411b9352 100644
+index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..608390ed36710a419de1542b80340dd3fcc7299c 100644
--- a/src/main/java/net/minecraft/world/item/MapItem.java
+++ b/src/main/java/net/minecraft/world/item/MapItem.java
-@@ -243,6 +243,7 @@ public class MapItem extends ComplexItem {
- MapItemSavedData worldmap = MapItem.getSavedData(map, world);
-
- if (worldmap != null) {
-+ worldmap.isExplorerMap = true; // Purpur
- if (world.dimension() == worldmap.dimension) {
- int i = 1 << worldmap.scale;
- int j = worldmap.centerX;
+@@ -195,6 +195,7 @@ public class MapItem extends ComplexItem {
+ public static void renderBiomePreviewMap(ServerLevel world, ItemStack map) {
+ MapItemSavedData mapItemSavedData = getSavedData(map, world);
+ if (mapItemSavedData != null) {
++ mapItemSavedData.isExplorerMap = true; // Purpur
+ if (world.dimension() == mapItemSavedData.dimension) {
+ int i = 1 << mapItemSavedData.scale;
+ int j = mapItemSavedData.centerX;
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 e4c4948e076cd64686dfd16ae0568fafc1437140..804c342783baccdc12e8ca49a362770e31596f6a 100644
+index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..e26f6215ca42885cb0635a3183a8df93a924ba7f 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
-@@ -67,6 +67,7 @@ public class MapItemSavedData extends SavedData {
+@@ -79,6 +79,7 @@ public class MapItemSavedData extends SavedData {
private final Map frameMarkers = Maps.newHashMap();
private int trackedDecorationCount;
private org.bukkit.craftbukkit.map.RenderData vanillaRender = new org.bukkit.craftbukkit.map.RenderData(); // Paper
@@ -29,10 +29,10 @@ index e4c4948e076cd64686dfd16ae0568fafc1437140..804c342783baccdc12e8ca49a362770e
// CraftBukkit start
public final CraftMapView mapView;
diff --git a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
-index 2d2bf5c37709b8e747fbfa2db5ce86f258e86224..f6413ab181208d729afb532dca5e96e4c938e83c 100644
+index 0cbbd915631904fe8c6effefb92895422b33eff6..aef19cfbecb4ddfc8dc71c4f3b2a011364c12dc2 100644
--- a/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
+++ b/src/main/java/org/bukkit/craftbukkit/map/CraftMapRenderer.java
-@@ -46,4 +46,10 @@ public class CraftMapRenderer extends MapRenderer {
+@@ -47,4 +47,10 @@ public class CraftMapRenderer extends MapRenderer {
}
}
diff --git a/patches/server/0302-Option-Ocelot-Spawn-Under-Sea-Level.patch b/patches/server/0287-Option-Ocelot-Spawn-Under-Sea-Level.patch
similarity index 84%
rename from patches/server/0302-Option-Ocelot-Spawn-Under-Sea-Level.patch
rename to patches/server/0287-Option-Ocelot-Spawn-Under-Sea-Level.patch
index f0ebe5b25..5d79d6bf5 100644
--- a/patches/server/0302-Option-Ocelot-Spawn-Under-Sea-Level.patch
+++ b/patches/server/0287-Option-Ocelot-Spawn-Under-Sea-Level.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] Option Ocelot Spawn Under Sea Level
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 af275fc579d66bb098c08e88e4186846a1174c02..3c5f25300d1c7800144a459cc8bf598352a62a35 100644
+index 5668aca08732e317c7bccacf1cfaae7d8666bce6..07dc8a43f4e8c54a94696b84896d32f66a207ad3 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Ocelot.java
-@@ -295,7 +295,7 @@ public class Ocelot extends Animal {
+@@ -293,7 +293,7 @@ public class Ocelot extends Animal {
if (world.isUnobstructed(this) && !world.containsAnyLiquid(this.getBoundingBox())) {
BlockPos blockposition = this.blockPosition();
@@ -18,10 +18,10 @@ index af275fc579d66bb098c08e88e4186846a1174c02..3c5f25300d1c7800144a459cc8bf5983
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-index ec7c1b39a87f253c52de4d0f3b01e8329aaa723a..39236dc4d7c70edff091bb1df54b2158e6dd5e2c 100644
+index bd1ae536d975b5a3c54063834fd05255f15d8dad..0f4a926937d07f76144cd1146b48bfdadaf887b5 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-@@ -2036,6 +2036,7 @@ public class PurpurWorldConfig {
+@@ -2097,6 +2097,7 @@ public class PurpurWorldConfig {
public int ocelotBreedingTicks = 6000;
public boolean ocelotTakeDamageFromWater = false;
public boolean ocelotAlwaysDropExp = false;
@@ -29,7 +29,7 @@ index ec7c1b39a87f253c52de4d0f3b01e8329aaa723a..39236dc4d7c70edff091bb1df54b2158
private void ocelotSettings() {
ocelotRidable = getBoolean("mobs.ocelot.ridable", ocelotRidable);
ocelotRidableInWater = getBoolean("mobs.ocelot.ridable-in-water", ocelotRidableInWater);
-@@ -2049,6 +2050,7 @@ public class PurpurWorldConfig {
+@@ -2110,6 +2111,7 @@ public class PurpurWorldConfig {
ocelotBreedingTicks = getInt("mobs.ocelot.breeding-delay-ticks", ocelotBreedingTicks);
ocelotTakeDamageFromWater = getBoolean("mobs.ocelot.takes-damage-from-water", ocelotTakeDamageFromWater);
ocelotAlwaysDropExp = getBoolean("mobs.ocelot.always-drop-exp", ocelotAlwaysDropExp);
diff --git a/patches/server/0303-add-an-option-for-piglins-to-ignore-gold-trimmed-arm.patch b/patches/server/0288-add-an-option-for-piglins-to-ignore-gold-trimmed-arm.patch
similarity index 58%
rename from patches/server/0303-add-an-option-for-piglins-to-ignore-gold-trimmed-arm.patch
rename to patches/server/0288-add-an-option-for-piglins-to-ignore-gold-trimmed-arm.patch
index 462263f28..8f0bc4e20 100644
--- a/patches/server/0303-add-an-option-for-piglins-to-ignore-gold-trimmed-arm.patch
+++ b/patches/server/0288-add-an-option-for-piglins-to-ignore-gold-trimmed-arm.patch
@@ -5,39 +5,23 @@ Subject: [PATCH] add an option for piglins to ignore gold-trimmed armor
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
-index 5c13e376dd079134da465044f1057bcce66973a3..8f10ced20d7cdb7020f032c9e37d9bbb38f360d6 100644
+index e25af9af8f87e6762716749c367658bf6bda9e34..b7d5c0b0e3741fcf04c4bac21a82fc41e2eeed5d 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
-@@ -597,20 +597,33 @@ public class PiglinAi {
- Iterator iterator = iterable.iterator();
-
- Item item;
-+ ItemStack itemstack; // Purpur
-
- do {
- if (!iterator.hasNext()) {
- return false;
- }
-
-- ItemStack itemstack = (ItemStack) iterator.next();
-+ itemstack = (ItemStack) iterator.next(); // Purpur
+@@ -606,11 +606,18 @@ public class PiglinAi {
+ ItemStack itemstack = (ItemStack) iterator.next();
item = itemstack.getItem();
-- } while (!(item instanceof ArmorItem) || ((ArmorItem) item).getMaterial() != ArmorMaterials.GOLD);
-+ } while (!(item instanceof ArmorItem) || ((ArmorItem) item).getMaterial() != ArmorMaterials.GOLD && (!entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim || !isWearingGoldTrim(entity, itemstack))); // Purpur
+- } while (!(item instanceof ArmorItem) || !((ArmorItem) item).getMaterial().is(ArmorMaterials.GOLD));
++ } while (!(item instanceof ArmorItem) || !((ArmorItem) item).getMaterial().is(ArmorMaterials.GOLD) && (!entity.level().purpurConfig.piglinIgnoresArmorWithGoldTrim || !isWearingGoldTrim(item))); // Purpur
return true;
}
+ // Purpur start
-+ private static boolean isWearingGoldTrim(LivingEntity entity, ItemStack itemstack) {
-+ Optional optionalArmorTrim = net.minecraft.world.item.armortrim.ArmorTrim.getTrim(entity.level().registryAccess(), itemstack, true);
-+
-+ if (optionalArmorTrim.isEmpty()) return false;
-+
-+ net.minecraft.world.item.armortrim.ArmorTrim armorTrim = optionalArmorTrim.get();
-+
-+ return armorTrim.material().is(net.minecraft.world.item.armortrim.TrimMaterials.GOLD);
++ private static boolean isWearingGoldTrim(Item itemstack) {
++ net.minecraft.world.item.armortrim.ArmorTrim armorTrim = itemstack.components().get(net.minecraft.core.component.DataComponents.TRIM);
++ return armorTrim != null && armorTrim.material().is(net.minecraft.world.item.armortrim.TrimMaterials.GOLD);
+ }
+ // Purpur end
+
@@ -45,10 +29,10 @@ index 5c13e376dd079134da465044f1057bcce66973a3..8f10ced20d7cdb7020f032c9e37d9bbb
piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET);
piglin.getNavigation().stop();
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-index 39236dc4d7c70edff091bb1df54b2158e6dd5e2c..cd7f347e46f4fa08e291bfdbbb01ea4f3271a877 100644
+index 0f4a926937d07f76144cd1146b48bfdadaf887b5..27eadd84aed6d109e278b0ee450fc2c302f61aba 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-@@ -2205,6 +2205,7 @@ public class PurpurWorldConfig {
+@@ -2266,6 +2266,7 @@ public class PurpurWorldConfig {
public int piglinPortalSpawnModifier = 2000;
public boolean piglinAlwaysDropExp = false;
public double piglinHeadVisibilityPercent = 0.5D;
@@ -56,7 +40,7 @@ index 39236dc4d7c70edff091bb1df54b2158e6dd5e2c..cd7f347e46f4fa08e291bfdbbb01ea4f
private void piglinSettings() {
piglinRidable = getBoolean("mobs.piglin.ridable", piglinRidable);
piglinRidableInWater = getBoolean("mobs.piglin.ridable-in-water", piglinRidableInWater);
-@@ -2220,6 +2221,7 @@ public class PurpurWorldConfig {
+@@ -2281,6 +2282,7 @@ public class PurpurWorldConfig {
piglinPortalSpawnModifier = getInt("mobs.piglin.portal-spawn-modifier", piglinPortalSpawnModifier);
piglinAlwaysDropExp = getBoolean("mobs.piglin.always-drop-exp", piglinAlwaysDropExp);
piglinHeadVisibilityPercent = getDouble("mobs.piglin.head-visibility-percent", piglinHeadVisibilityPercent);
diff --git a/patches/server/0289-Add-option-for-always-showing-item-in-player-death-m.patch b/patches/server/0289-Add-option-for-always-showing-item-in-player-death-m.patch
new file mode 100644
index 000000000..84ea3ef77
--- /dev/null
+++ b/patches/server/0289-Add-option-for-always-showing-item-in-player-death-m.patch
@@ -0,0 +1,46 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: MelnCat
+Date: Tue, 22 Aug 2023 22:18:26 -0700
+Subject: [PATCH] Add option for always showing item in player death messages
+
+
+diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
+index 357a79d72a2de02a019595e457fe432bf409e516..4fb025a63628eb60509d90b680922a0220104bcb 100644
+--- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
++++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
+@@ -54,7 +54,7 @@ public class CombatTracker {
+
+ private Component getMessageForAssistedFall(Entity attacker, Component attackerDisplayName, String itemDeathTranslationKey, String deathTranslationKey) {
+ ItemStack itemStack = attacker instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem() : ItemStack.EMPTY;
+- return !itemStack.isEmpty() && itemStack.has(DataComponents.CUSTOM_NAME)
++ return !itemStack.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemStack.has(DataComponents.CUSTOM_NAME)) // Purpur
+ ? Component.translatable(itemDeathTranslationKey, this.mob.getDisplayName(), attackerDisplayName, itemStack.getDisplayName())
+ : Component.translatable(deathTranslationKey, this.mob.getDisplayName(), attackerDisplayName);
+ }
+diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+index 812091bf6efc067b21b9723b8241360d4b4c79e7..25e614be19b2b29b36af136b823f27f85e1650fa 100644
+--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
++++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+@@ -197,7 +197,7 @@ public class DamageSource {
+
+ ItemStack itemstack1 = itemstack;
+
+- return !itemstack1.isEmpty() && itemstack1.has(DataComponents.CUSTOM_NAME) ? Component.translatable(s + ".item", killed.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, killed.getDisplayName(), ichatbasecomponent);
++ return !itemstack1.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemstack1.has(DataComponents.CUSTOM_NAME)) ? Component.translatable(s + ".item", killed.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, killed.getDisplayName(), ichatbasecomponent);
+ }
+ }
+
+diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+index e7bce4121f7bc2fe0acd8860a73c58dfed73330b..6e0e871153e0ec85fd40ddf0581b6ed2932b9f99 100644
+--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+@@ -576,4 +576,9 @@ public class PurpurConfig {
+ block.fallDistanceMultiplier = fallDistanceMultiplier.floatValue();
+ });
+ }
++
++ public static boolean playerDeathsAlwaysShowItem = false;
++ private static void playerDeathsAlwaysShowItem() {
++ playerDeathsAlwaysShowItem = getBoolean("settings.player-deaths-always-show-item", playerDeathsAlwaysShowItem);
++ }
+ }
diff --git a/patches/server/0305-place-end-crystal-on-any-block.patch b/patches/server/0290-place-end-crystal-on-any-block.patch
similarity index 85%
rename from patches/server/0305-place-end-crystal-on-any-block.patch
rename to patches/server/0290-place-end-crystal-on-any-block.patch
index 617d26409..8bf62f530 100644
--- a/patches/server/0305-place-end-crystal-on-any-block.patch
+++ b/patches/server/0290-place-end-crystal-on-any-block.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] place end crystal on any block
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
-index 3688e9f8c6c6d1239095e3a87060ccca90386d0c..34254eec36d34ae343733fa1abbaaba60be41a3b 100644
+index dd1bdb4bb87a3a59c229ba76b36841d199717624..54607cea2622f259aedfe425b60e2317e4167bf9 100644
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
-@@ -26,7 +26,7 @@ public class EndCrystalItem extends Item {
+@@ -27,7 +27,7 @@ public class EndCrystalItem extends Item {
BlockPos blockposition = context.getClickedPos();
BlockState iblockdata = world.getBlockState(blockposition);
@@ -18,10 +18,10 @@ index 3688e9f8c6c6d1239095e3a87060ccca90386d0c..34254eec36d34ae343733fa1abbaaba6
} else {
BlockPos blockposition1 = blockposition.above(); final BlockPos aboveBlockPosition = blockposition1; // Paper - OBFHELPER
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-index cd7f347e46f4fa08e291bfdbbb01ea4f3271a877..d4d9f748d259df8b6f4566efa21c15c470de5ba2 100644
+index 27eadd84aed6d109e278b0ee450fc2c302f61aba..81c4b22a4fb7cbc2601966b646bb20294b46313e 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-@@ -899,6 +899,7 @@ public class PurpurWorldConfig {
+@@ -978,6 +978,7 @@ public class PurpurWorldConfig {
public boolean basedEndCrystalExplosionFire = false;
public net.minecraft.world.level.Level.ExplosionInteraction basedEndCrystalExplosionEffect = net.minecraft.world.level.Level.ExplosionInteraction.BLOCK;
public int endCrystalCramming = 0;
@@ -29,7 +29,7 @@ index cd7f347e46f4fa08e291bfdbbb01ea4f3271a877..d4d9f748d259df8b6f4566efa21c15c4
private void endCrystalSettings() {
if (PurpurConfig.version < 31) {
if ("DESTROY".equals(getString("blocks.end-crystal.baseless.explosion-effect", baselessEndCrystalExplosionEffect.name()))) {
-@@ -927,6 +928,7 @@ public class PurpurWorldConfig {
+@@ -1006,6 +1007,7 @@ public class PurpurWorldConfig {
basedEndCrystalExplosionEffect = net.minecraft.world.level.Level.ExplosionInteraction.BLOCK;
}
endCrystalCramming = getInt("blocks.end-crystal.cramming-amount", endCrystalCramming);
diff --git a/patches/server/0307-Add-option-to-disable-the-copper-oxidation-proximity.patch b/patches/server/0291-Add-option-to-disable-the-copper-oxidation-proximity.patch
similarity index 81%
rename from patches/server/0307-Add-option-to-disable-the-copper-oxidation-proximity.patch
rename to patches/server/0291-Add-option-to-disable-the-copper-oxidation-proximity.patch
index 0ed6de5c5..8d565ec61 100644
--- a/patches/server/0307-Add-option-to-disable-the-copper-oxidation-proximity.patch
+++ b/patches/server/0291-Add-option-to-disable-the-copper-oxidation-proximity.patch
@@ -5,23 +5,23 @@ Subject: [PATCH] Add option to disable the copper oxidation proximity penalty
diff --git a/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java b/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
-index 8512b977b44a0a4d3a2521e27a60d65f7ac967be..dd270f67388c8663e0418875c88cb1e2a55d0635 100644
+index daae7fd6e0148cfba8e359d990748a0c83a3376e..0e06b1bcd906e92c083dc74d56d6d0a2a36f62a7 100644
--- a/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ChangeOverTimeBlock.java
-@@ -65,7 +65,7 @@ public interface ChangeOverTimeBlock> {
+@@ -67,7 +67,7 @@ public interface ChangeOverTimeBlock> {
}
float f = (float) (k + 1) / (float) (k + j + 1);
- float f1 = f * f * this.getChanceModifier();
+ float f1 = world.purpurConfig.disableOxidationProximityPenalty ? this.getChanceModifier() : f * f * this.getChanceModifier(); // Purpur
- if (random.nextFloat() < f1) {
- this.getNext(state).ifPresent((iblockdata2) -> {
+ return random.nextFloat() < f1 ? this.getNext(state) : Optional.empty();
+ }
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-index d4d9f748d259df8b6f4566efa21c15c470de5ba2..64e172e6cbfb8134c2b36bce8279e1ef44085257 100644
+index 81c4b22a4fb7cbc2601966b646bb20294b46313e..43d91390274c8cc8863e0aceb20837415b915166 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
-@@ -145,6 +145,7 @@ public class PurpurWorldConfig {
+@@ -146,6 +146,7 @@ public class PurpurWorldConfig {
public boolean rainStopsAfterSleep = true;
public boolean thunderStopsAfterSleep = true;
public int mobLastHurtByPlayerTime = 100;
@@ -29,7 +29,7 @@ index d4d9f748d259df8b6f4566efa21c15c470de5ba2..64e172e6cbfb8134c2b36bce8279e1ef
private void miscGameplayMechanicsSettings() {
useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
mendingMultiplier = getDouble("gameplay-mechanics.mending-multiplier", mendingMultiplier);
-@@ -173,6 +174,7 @@ public class PurpurWorldConfig {
+@@ -181,6 +182,7 @@ public class PurpurWorldConfig {
rainStopsAfterSleep = getBoolean("gameplay-mechanics.rain-stops-after-sleep", rainStopsAfterSleep);
thunderStopsAfterSleep = getBoolean("gameplay-mechanics.thunder-stops-after-sleep", thunderStopsAfterSleep);
mobLastHurtByPlayerTime = getInt("gameplay-mechanics.mob-last-hurt-by-player-time", mobLastHurtByPlayerTime);
diff --git a/patches/server/0292-register-minecraft-debug-commands.patch b/patches/server/0292-register-minecraft-debug-commands.patch
new file mode 100644
index 000000000..db1601242
--- /dev/null
+++ b/patches/server/0292-register-minecraft-debug-commands.patch
@@ -0,0 +1,47 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: granny
+Date: Sun, 18 Feb 2024 16:28:32 -0800
+Subject: [PATCH] register minecraft debug commands
+
+
+diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
+index 13dfb3e506d50c0b191baf5d05bbfc28c20be0ae..f9d0e8ee9414b3897f268ba78a1469ddf868f51a 100644
+--- a/src/main/java/net/minecraft/commands/Commands.java
++++ b/src/main/java/net/minecraft/commands/Commands.java
+@@ -222,8 +222,8 @@ public class Commands {
+ JfrCommand.register(this.dispatcher);
+ }
+
+- if (SharedConstants.IS_RUNNING_IN_IDE) {
+- TestCommand.register(this.dispatcher);
++ if (org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands || SharedConstants.IS_RUNNING_IN_IDE) { // Purpur
++ if (!org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands) TestCommand.register(this.dispatcher); // Purpur
+ ResetChunksCommand.register(this.dispatcher);
+ RaidCommand.register(this.dispatcher, commandRegistryAccess);
+ DebugPathCommand.register(this.dispatcher);
+diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
+index 8925440dbc35dbc4a7d59f13511d7afeda803260..411f1f8c6be072cfc5ba88cbec38dbc4300a41d1 100644
+--- a/src/main/java/net/minecraft/server/Main.java
++++ b/src/main/java/net/minecraft/server/Main.java
+@@ -122,6 +122,7 @@ public class Main {
+ // Purpur start - load config files early
+ org.bukkit.configuration.file.YamlConfiguration purpurConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionset.valueOf("purpur-settings"));
+ org.purpurmc.purpur.PurpurConfig.clampEnchantLevels = purpurConfiguration.getBoolean("settings.enchantment.clamp-levels");
++ org.purpurmc.purpur.PurpurConfig.registerMinecraftDebugCommands = purpurConfiguration.getBoolean("settings.register-minecraft-debug-commands");
+ // Purpur end - load config files early
+
+ io.papermc.paper.plugin.PluginInitializerManager.load(optionset); // Paper
+diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+index 6e0e871153e0ec85fd40ddf0581b6ed2932b9f99..f49108ed94f7787347c5e0a721646083d6dffafc 100644
+--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
+@@ -581,4 +581,9 @@ public class PurpurConfig {
+ private static void playerDeathsAlwaysShowItem() {
+ playerDeathsAlwaysShowItem = getBoolean("settings.player-deaths-always-show-item", playerDeathsAlwaysShowItem);
+ }
++
++ public static boolean registerMinecraftDebugCommands = false;
++ private static void registerMinecraftDebugCommands() {
++ registerMinecraftDebugCommands = getBoolean("settings.register-minecraft-debug-commands", registerMinecraftDebugCommands);
++ }
+ }
diff --git a/patches/server/0293-Configurable-villager-search-radius.patch b/patches/server/0293-Configurable-villager-search-radius.patch
new file mode 100644
index 000000000..819b508a2
--- /dev/null
+++ b/patches/server/0293-Configurable-villager-search-radius.patch
@@ -0,0 +1,54 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Pantera
+Date: Fri, 26 Jan 2024 15:57:24 +0900
+Subject: [PATCH] Configurable-villager-search-radius
+
+
+diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+index e1b6fe9ecda25f86431baf414f1bfd3a26a8b2bd..6499e3fe49e453db11e51eaf717ca8b3b682056b 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+@@ -73,7 +73,7 @@ public class AcquirePoi {
+ };
+ // Paper start - optimise POI access
+ java.util.List, BlockPos>> poiposes = new java.util.ArrayList<>();
+- io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, poiPredicate, predicate2, entity.blockPosition(), 48, 48*48, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes);
++ io.papermc.paper.util.PoiAccess.findNearestPoiPositions(poiManager, poiPredicate, predicate2, entity.blockPosition(), world.purpurConfig.villagerAcquirePoiSearchRadius, world.purpurConfig.villagerAcquirePoiSearchRadius*world.purpurConfig.villagerAcquirePoiSearchRadius, PoiManager.Occupancy.HAS_SPACE, false, 5, poiposes); // Purpur
+ Set, BlockPos>> set = new java.util.HashSet<>(poiposes);
+ // Paper end - optimise POI access
+ Path path = findPathToPois(entity, set);
+diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
+index 92731b6b593289e9f583c9b705b219e81fcd8e73..9104d7010bda6f9f73b478c11490ef9c53f76da2 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
+@@ -56,7 +56,7 @@ public class NearestBedSensor extends Sensor {
+ // Paper start - optimise POI access
+ java.util.List, BlockPos>> poiposes = new java.util.ArrayList<>();
+ // don't ask me why it's unbounded. ask mojang.
+- io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), 48, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes);
++ io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), world.purpurConfig.villagerNearestBedSensorSearchRadius, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); // Purpur
+ Path path = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes));
+ // Paper end - optimise POI access
+ if (path != null && path.canReach()) {
+diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+index 43d91390274c8cc8863e0aceb20837415b915166..710511db0e882d9795c2a1ff31570fbb05fbb0f1 100644
+--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
++++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+@@ -2896,6 +2896,8 @@ public class PurpurWorldConfig {
+ public boolean villagerDisplayTradeItem = true;
+ public int villagerSpawnIronGolemRadius = 0;
+ public int villagerSpawnIronGolemLimit = 0;
++ public int villagerAcquirePoiSearchRadius = 48;
++ public int villagerNearestBedSensorSearchRadius = 48;
+ private void villagerSettings() {
+ villagerRidable = getBoolean("mobs.villager.ridable", villagerRidable);
+ villagerRidableInWater = getBoolean("mobs.villager.ridable-in-water", villagerRidableInWater);
+@@ -2932,6 +2934,8 @@ public class PurpurWorldConfig {
+ villagerDisplayTradeItem = getBoolean("mobs.villager.display-trade-item", villagerDisplayTradeItem);
+ villagerSpawnIronGolemRadius = getInt("mobs.villager.spawn-iron-golem.radius", villagerSpawnIronGolemRadius);
+ villagerSpawnIronGolemLimit = getInt("mobs.villager.spawn-iron-golem.limit", villagerSpawnIronGolemLimit);
++ villagerAcquirePoiSearchRadius = getInt("mobs.villager.search-radius.acquire-poi", villagerAcquirePoiSearchRadius);
++ villagerNearestBedSensorSearchRadius = getInt("mobs.villager.search-radius.nearest-bed-sensor", villagerNearestBedSensorSearchRadius);
+ }
+
+ public boolean vindicatorRidable = false;
diff --git a/patches/server/0294-option-to-make-ravagers-afraid-of-rabbits.patch b/patches/server/0294-option-to-make-ravagers-afraid-of-rabbits.patch
new file mode 100644
index 000000000..765dd9d66
--- /dev/null
+++ b/patches/server/0294-option-to-make-ravagers-afraid-of-rabbits.patch
@@ -0,0 +1,39 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: granny
+Date: Tue, 7 May 2024 04:59:57 -0700
+Subject: [PATCH] option to make ravagers afraid of rabbits
+
+https://github.com/PurpurMC/Purpur/discussions/713
+
+diff --git a/src/main/java/net/minecraft/world/entity/monster/Ravager.java b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
+index 9551bd7c9bed37cf17910e7f71b82ed20fb2d759..dbfcca8adb7afa7a3101f22c2bc48aff6abae4a2 100644
+--- a/src/main/java/net/minecraft/world/entity/monster/Ravager.java
++++ b/src/main/java/net/minecraft/world/entity/monster/Ravager.java
+@@ -111,6 +111,7 @@ public class Ravager extends Raider {
+ super.registerGoals();
+ this.goalSelector.addGoal(0, new FloatGoal(this));
+ this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur
++ if (level().purpurConfig.ravagerAvoidRabbits) this.goalSelector.addGoal(3, new net.minecraft.world.entity.ai.goal.AvoidEntityGoal<>(this, net.minecraft.world.entity.animal.Rabbit.class, 6.0F, 1.0D, 1.2D)); // Purpur
+ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, true));
+ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4D));
+ this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
+diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+index 710511db0e882d9795c2a1ff31570fbb05fbb0f1..d8de8710d9b8cf2ae5c434b2b0b27e76ffbbe4bf 100644
+--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
++++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+@@ -2412,6 +2412,7 @@ public class PurpurWorldConfig {
+ public boolean ravagerTakeDamageFromWater = false;
+ public List ravagerGriefableBlocks = new ArrayList<>();
+ public boolean ravagerAlwaysDropExp = false;
++ public boolean ravagerAvoidRabbits = false;
+ private void ravagerSettings() {
+ ravagerRidable = getBoolean("mobs.ravager.ridable", ravagerRidable);
+ ravagerRidableInWater = getBoolean("mobs.ravager.ridable-in-water", ravagerRidableInWater);
+@@ -2442,6 +2443,7 @@ public class PurpurWorldConfig {
+ }
+ });
+ ravagerAlwaysDropExp = getBoolean("mobs.ravager.always-drop-exp", ravagerAlwaysDropExp);
++ ravagerAvoidRabbits = getBoolean("mobs.ravager.avoid-rabbits", ravagerAvoidRabbits);
+ }
+
+ public boolean salmonRidable = false;
diff --git a/patches/server/0295-config-for-startup-commands.patch b/patches/server/0295-config-for-startup-commands.patch
new file mode 100644
index 000000000..77e6c93cd
--- /dev/null
+++ b/patches/server/0295-config-for-startup-commands.patch
@@ -0,0 +1,48 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: granny
+Date: Sun, 5 May 2024 02:27:52 -0700
+Subject: [PATCH] config for startup commands
+
+
+diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
+index dfeae138e830e95ab823b6349a91160b02622208..21327a92b75a460c7beb3aa408502f37a7db31fa 100644
+--- a/src/main/java/net/minecraft/server/MinecraftServer.java
++++ b/src/main/java/net/minecraft/server/MinecraftServer.java
+@@ -1188,6 +1188,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop startupCommands = new ArrayList<>();
++ private static void startupCommands() {
++ startupCommands.clear();
++ getList("settings.startup-commands", new ArrayList()).forEach(line -> {
++ String command = line.toString();
++ if (command.startsWith("/")) {
++ command = command.substring(1);
++ }
++ startupCommands.add(command);
++ });
++ }
+ }
diff --git a/patches/server/0304-Add-option-for-always-showing-item-in-player-death-m.patch b/patches/server/0304-Add-option-for-always-showing-item-in-player-death-m.patch
deleted file mode 100644
index da162e380..000000000
--- a/patches/server/0304-Add-option-for-always-showing-item-in-player-death-m.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MelnCat
-Date: Tue, 22 Aug 2023 22:18:26 -0700
-Subject: [PATCH] Add option for always showing item in player death messages
-
-
-diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
-index 8c2c515f1b5f56bf1d6cf0c35d4f0fa7b593d1a0..6e8d9be28c5908fb12c44c0ecb0e02180601371a 100644
---- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
-+++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java
-@@ -59,7 +59,7 @@ public class CombatTracker {
- }
-
- ItemStack itemStack = var10000;
-- return !itemStack.isEmpty() && itemStack.hasCustomHoverName() ? Component.translatable(itemDeathTranslationKey, this.mob.getDisplayName(), attackerDisplayName, itemStack.getDisplayName()) : Component.translatable(deathTranslationKey, this.mob.getDisplayName(), attackerDisplayName);
-+ return !itemStack.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemStack.hasCustomHoverName()) ? Component.translatable(itemDeathTranslationKey, this.mob.getDisplayName(), attackerDisplayName, itemStack.getDisplayName()) : Component.translatable(deathTranslationKey, this.mob.getDisplayName(), attackerDisplayName);
- }
-
- private Component getFallMessage(CombatEntry damageRecord, @Nullable Entity attacker) {
-diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
-index fc1fb63ee0e28b8d1f065bfad716b465cde5a69f..c8860f20956a2819da001e93938249452bf7cb49 100644
---- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
-+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
-@@ -126,7 +126,7 @@ public class DamageSource {
-
- ItemStack itemstack1 = itemstack;
-
-- return !itemstack1.isEmpty() && itemstack1.hasCustomHoverName() ? Component.translatable(s + ".item", killed.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, killed.getDisplayName(), ichatbasecomponent);
-+ return !itemstack1.isEmpty() && (org.purpurmc.purpur.PurpurConfig.playerDeathsAlwaysShowItem || itemstack1.hasCustomHoverName()) ? Component.translatable(s + ".item", killed.getDisplayName(), ichatbasecomponent, itemstack1.getDisplayName()) : Component.translatable(s, killed.getDisplayName(), ichatbasecomponent);
- }
- }
-
-diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
-index f10679ef2cbd73397b64eb69516c8a46e4d35a4e..3633574e112f217b412217dd243a631dc4e9c40c 100644
---- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java
-+++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java
-@@ -647,4 +647,9 @@ public class PurpurConfig {
- block.fallDistanceMultiplier = fallDistanceMultiplier.floatValue();
- });
- }
-+
-+ public static boolean playerDeathsAlwaysShowItem = false;
-+ private static void playerDeathsAlwaysShowItem() {
-+ playerDeathsAlwaysShowItem = getBoolean("settings.player-deaths-always-show-item", playerDeathsAlwaysShowItem);
-+ }
- }
diff --git a/patches/api/0001-Pufferfish-API-Changes.patch b/patches/unapplied-api/0001-Pufferfish-API-Changes.patch
similarity index 96%
rename from patches/api/0001-Pufferfish-API-Changes.patch
rename to patches/unapplied-api/0001-Pufferfish-API-Changes.patch
index 7b92d9cbd..1fbc75a41 100644
--- a/patches/api/0001-Pufferfish-API-Changes.patch
+++ b/patches/unapplied-api/0001-Pufferfish-API-Changes.patch
@@ -20,18 +20,18 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
diff --git a/build.gradle.kts b/build.gradle.kts
-index fb47a794893d5fef026a35a7c573becf74420aa0..0330a20576c372c29ca4d98a2bc5b01e28303ac3 100644
+index 04853c43b99951bf0d4c96ef73724625bdaf018f..9164120d299d062c62529a7ef74eac0ded367993 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
-@@ -46,6 +46,7 @@ dependencies {
+@@ -51,6 +51,7 @@ dependencies {
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
api("org.apache.logging.log4j:log4j-api:$log4jVersion")
api("org.slf4j:slf4j-api:$slf4jVersion")
+ api("io.sentry:sentry:5.4.0") // Pufferfish
- implementation("org.ow2.asm:asm:9.4")
- implementation("org.ow2.asm:asm-commons:9.4")
-@@ -89,6 +90,13 @@ val generateApiVersioningFile by tasks.registering {
+ implementation("org.ow2.asm:asm:9.7")
+ implementation("org.ow2.asm:asm-commons:9.7")
+@@ -109,6 +110,13 @@ val generateApiVersioningFile by tasks.registering {
}
}
@@ -389,7 +389,7 @@ index 0000000000000000000000000000000000000000..ae2464920c9412ac90b819a540ee58be
+
+}
diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java
-index 3a9aaca2e76411a9c27f9f5e0f22d060d5a66d06..9584e245144b561b4f6745b2f26a4f69a6f92891 100644
+index c80faa079eca1564847070f0338fc98024639829..e632d51d3487eb4807243b6705999ad124466bf5 100644
--- a/src/main/java/org/bukkit/map/MapPalette.java
+++ b/src/main/java/org/bukkit/map/MapPalette.java
@@ -1,6 +1,7 @@
@@ -480,10 +480,10 @@ index eaefbb00e9993d54906cc8cf35cf753c0d6c7707..301e82369603f3dd6e6c1bd380da4bac
if (cloader instanceof PluginClassLoader) {
diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
-index 13da387d3b59bc67c0d73e3fbd3a4034b1281527..7572a0bf6614b02be3cbccc7b86e52ee1b8df621 100644
+index 7e4f7cb2afbc145e532285c793573ad107bc3033..12449e18180d604e9cbbc744da74a8b222a18e1f 100644
--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
-@@ -48,6 +48,8 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
+@@ -50,6 +50,8 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
private io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup classLoaderGroup; // Paper
public io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext; // Paper
@@ -492,7 +492,7 @@ index 13da387d3b59bc67c0d73e3fbd3a4034b1281527..7572a0bf6614b02be3cbccc7b86e52ee
static {
ClassLoader.registerAsParallelCapable();
}
-@@ -183,6 +185,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
+@@ -197,6 +199,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
throw new ClassNotFoundException(name);
}
@@ -500,7 +500,7 @@ index 13da387d3b59bc67c0d73e3fbd3a4034b1281527..7572a0bf6614b02be3cbccc7b86e52ee
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) {
-@@ -190,7 +193,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
+@@ -204,7 +207,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
}
Class> result = classes.get(name);
@@ -509,7 +509,7 @@ index 13da387d3b59bc67c0d73e3fbd3a4034b1281527..7572a0bf6614b02be3cbccc7b86e52ee
String path = name.replace('.', '/').concat(".class");
JarEntry entry = jar.getJarEntry(path);
-@@ -237,6 +240,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
+@@ -251,6 +254,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
this.setClass(name, result); // Paper
}
@@ -517,7 +517,7 @@ index 13da387d3b59bc67c0d73e3fbd3a4034b1281527..7572a0bf6614b02be3cbccc7b86e52ee
return result;
}
-@@ -251,6 +255,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
+@@ -265,6 +269,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
// Paper end
super.close();
} finally {
diff --git a/patches/api/0002-Fix-pufferfish-issues.patch b/patches/unapplied-api/0002-Fix-pufferfish-issues.patch
similarity index 51%
rename from patches/api/0002-Fix-pufferfish-issues.patch
rename to patches/unapplied-api/0002-Fix-pufferfish-issues.patch
index 08bd8a159..b6b893fd9 100644
--- a/patches/api/0002-Fix-pufferfish-issues.patch
+++ b/patches/unapplied-api/0002-Fix-pufferfish-issues.patch
@@ -4,8 +4,21 @@ Date: Tue, 4 Jan 2022 23:05:41 -0600
Subject: [PATCH] Fix pufferfish issues
+diff --git a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
+index ab5fea0b03224bf249352ce340e94704ff713345..3441cdad70da1bd523c5933b1a914688718c2657 100644
+--- a/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
++++ b/src/main/java/gg/pufferfish/pufferfish/simd/SIMDChecker.java
+@@ -15,7 +15,7 @@ public class SIMDChecker {
+ @Deprecated
+ public static boolean canEnable(Logger logger) {
+ try {
+- if (SIMDDetection.getJavaVersion() != 17 && SIMDDetection.getJavaVersion() != 18 && SIMDDetection.getJavaVersion() != 19) {
++ if (SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21) {
+ return false;
+ } else {
+ SIMDDetection.testRun = true;
diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java
-index 06e96e5c98f1a7a68c8b4b5e527314c1aa774e38..49bba9a7a02b9cf3a552583315eff2b7dbe060c0 100644
+index 88f1ca89fa640a686231b8eec87e70419b2d73ef..d6b91c49a267c89d7df2ddee7ccfe64675d117be 100644
--- a/src/test/java/org/bukkit/AnnotationTest.java
+++ b/src/test/java/org/bukkit/AnnotationTest.java
@@ -47,6 +47,10 @@ public class AnnotationTest {
diff --git a/patches/server/0001-Pufferfish-Server-Changes.patch b/patches/unapplied-server/0001-Pufferfish-Server-Changes.patch
similarity index 86%
rename from patches/server/0001-Pufferfish-Server-Changes.patch
rename to patches/unapplied-server/0001-Pufferfish-Server-Changes.patch
index 61f291acb..40944d98b 100644
--- a/patches/server/0001-Pufferfish-Server-Changes.patch
+++ b/patches/unapplied-server/0001-Pufferfish-Server-Changes.patch
@@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
diff --git a/build.gradle.kts b/build.gradle.kts
-index a79461457ea19339f47572c70705d655ebc55276..57739f9dd7d045d1a585a9fc1be290a1a007db6a 100644
+index bcfe59b6efb628ee1e7f9d60667360d4d885fb6a..4517548e2c892c2e94f91e7449660f9e36b8f14e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -13,8 +13,12 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) {
@@ -38,9 +38,9 @@ index a79461457ea19339f47572c70705d655ebc55276..57739f9dd7d045d1a585a9fc1be290a1
// Paper start
implementation("org.jline:jline-terminal-jansi:3.21.0")
implementation("net.minecrell:terminalconsoleappender:1.3.0")
-@@ -52,12 +56,27 @@ dependencies {
- runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3")
- runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3")
+@@ -50,6 +54,13 @@ dependencies {
+ runtimeOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18")
+ runtimeOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18")
+ // Pufferfish start
+ implementation("org.yaml:snakeyaml:1.32")
@@ -52,9 +52,10 @@ index a79461457ea19339f47572c70705d655ebc55276..57739f9dd7d045d1a585a9fc1be290a1
testImplementation("io.github.classgraph:classgraph:4.8.47") // Paper - mob goal test
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
testImplementation("org.hamcrest:hamcrest:2.2")
+@@ -59,6 +70,14 @@ dependencies {
}
- val craftbukkitPackageVersion = "1_20_R2" // Paper
+ val craftbukkitPackageVersion = "1_20_R3" // Paper
+
+// Pufferfish Start
+tasks.withType {
@@ -66,7 +67,7 @@ index a79461457ea19339f47572c70705d655ebc55276..57739f9dd7d045d1a585a9fc1be290a1
tasks.jar {
archiveClassifier.set("dev")
-@@ -70,7 +89,7 @@ tasks.jar {
+@@ -71,7 +90,7 @@ tasks.jar {
attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main",
"Implementation-Title" to "CraftBukkit",
@@ -75,20 +76,11 @@ index a79461457ea19339f47572c70705d655ebc55276..57739f9dd7d045d1a585a9fc1be290a1
"Implementation-Vendor" to date, // Paper
"Specification-Title" to "Bukkit",
"Specification-Version" to project.version,
-@@ -210,7 +229,5 @@ val runtimeClasspathForRunDev = sourceSets.main.flatMap { src ->
- }
- tasks.registerRunTask("runDev") {
- description = "Spin up a non-relocated Mojang-mapped test server"
-- classpath(tasks.filterProjectDir.flatMap { it.outputJar })
-- classpath(runtimeClasspathForRunDev)
-- jvmArgs("-DPaper.isRunDev=true")
-+ classpath(sourceSets.main.map { it.runtimeClasspath })
- }
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
-index a2f71a6d1a9e98133dff6cd0f625da9435a8af14..ff940e43ca35094bbcae6c7d471d3c4aeb7c1727 100644
+index 7620c72a4c243cbeea245203ce03a97cbfa7d922..b35a9f4c5f8960864c402ede8a51fb5ab9c4fcc0 100644
--- a/src/main/java/co/aikar/timings/TimingsExport.java
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
-@@ -242,7 +242,8 @@ public class TimingsExport extends Thread {
+@@ -240,7 +240,8 @@ public class TimingsExport extends Thread {
parent.put("config", createObject(
pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)),
pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)),
@@ -624,10 +616,10 @@ index 0000000000000000000000000000000000000000..020368da69b9a492155f6de6297f7473
+}
diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
new file mode 100644
-index 0000000000000000000000000000000000000000..cc66657cb4f978aa2df3ca1be6c683759952cc7a
+index 0000000000000000000000000000000000000000..6464682e2f93659e73aca491031c8051ab000033
--- /dev/null
+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
-@@ -0,0 +1,294 @@
+@@ -0,0 +1,302 @@
+package gg.pufferfish.pufferfish;
+
+import gg.pufferfish.pufferfish.simd.SIMDDetection;
@@ -810,6 +802,14 @@ index 0000000000000000000000000000000000000000..cc66657cb4f978aa2df3ca1be6c68375
+ "disabling this option.",
+ "This can be overridden per-player with the permission pufferfish.usebooks");
+ }
++
++ public static boolean tpsCatchup;
++ private static void tpsCatchup() {
++ tpsCatchup = getBoolean("tps-catchup", true,
++ "If this setting is true, the server will run faster after a lag spike in",
++ "an attempt to maintain 20 TPS. This option (defaults to true per",
++ "spigot/paper) can cause mobs to move fast after a lag spike.");
++ }
+
+ public static boolean enableSuffocationOptimization;
+ private static void suffocationOptimization() {
@@ -1463,10 +1463,10 @@ index 0000000000000000000000000000000000000000..facd55463d44cb7e3d2ca6892982f549
+ }
+}
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
-index d02546b18cb689724887b4e85e8d32a18828a4ad..91eaff58bb422ba188e6cfaa9c20b45bec211edd 100644
+index e028353e0261310afc42ca0454b723d9f1ffc131..2222625a515d9ae6c3e9c92fc4d4a5bf974af5f8 100644
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
-@@ -213,7 +213,7 @@ public final class MCUtil {
+@@ -215,7 +215,7 @@ public final class MCUtil {
}
public static long getCoordinateKey(final Entity entity) {
@@ -1475,29 +1475,54 @@ index d02546b18cb689724887b4e85e8d32a18828a4ad..91eaff58bb422ba188e6cfaa9c20b45b
}
public static long getCoordinateKey(final ChunkPos pair) {
+diff --git a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
+index 0af9ed92824ccf30814eceb6a2c2e5c12661c991..67eeb39aede6908d2756e49821ca350ebe916902 100644
+--- a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
++++ b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java
+@@ -37,7 +37,7 @@ public class SignedMessageChain {
+ throw new SignedMessageChain.DecodeException(Component.translatable("chat.disabled.chain_broken"), false); // Paper - diff on change (if disconnects, need a new kick event cause)
+ } else if (playerPublicKey.data().hasExpired()) {
+ throw new SignedMessageChain.DecodeException(Component.translatable("chat.disabled.expiredProfileKey"), false, org.bukkit.event.player.PlayerKickEvent.Cause.EXPIRED_PROFILE_PUBLIC_KEY); // Paper - kick event causes
+- } else if (body.timeStamp().isBefore(this.lastTimeStamp)) {
++ } else if (!gg.pufferfish.pufferfish.PufferfishConfig.disableOutOfOrderChat && body.timeStamp().isBefore(this.lastTimeStamp)) { // Pufferfish
+ throw new SignedMessageChain.DecodeException(Component.translatable("multiplayer.disconnect.out_of_order_chat"), true, org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event causes
+ } else {
+ this.lastTimeStamp = body.timeStamp();
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 97745f0bab8d82d397c6c2a5775aed92bca0a034..371049c1236c6443384c0ce184e99d5b9f8e57c2 100644
+index 2dc07e5ef249636e85ad9c78e3729e9e066a8fe8..b9e0a32f5829ca15f949effcafcbe2a975f6f690 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
-@@ -308,6 +308,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) {
AtomicReference atomicreference = new AtomicReference();
-@@ -1697,7 +1699,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Spigot - Spigot > // CraftBukkit - cb > vanilla!
-+ return "Pufferfish"; // Pufferfish - Pufferfish > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla!
+- return "Paper"; // Paper
++ return "Pufferfish"; // Pufferfish > // Paper
}
public SystemReport fillSystemReport(SystemReport details) {
-@@ -2272,6 +2274,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop needsChangeBroadcasting = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>();
@@ -1539,7 +1564,7 @@ index 0c2617574e21037d94ac56ad08b490f9bca5c5af..7eaee0d0dcbb420abb5c49ba0a465d90
// Paper end - optimise chunk tick iteration
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) {
-@@ -1330,8 +1330,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1448,8 +1448,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return ChunkMap.this.level.getServer().getScaledTrackingDistance(initialDistance);
}
@@ -1568,7 +1593,7 @@ index 0c2617574e21037d94ac56ad08b490f9bca5c5af..7eaee0d0dcbb420abb5c49ba0a465d90
Iterator iterator = this.entity.getIndirectPassengers().iterator();
while (iterator.hasNext()) {
-@@ -1343,6 +1363,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -1461,6 +1481,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
i = j;
}
}
@@ -1579,91 +1604,71 @@ index 0c2617574e21037d94ac56ad08b490f9bca5c5af..7eaee0d0dcbb420abb5c49ba0a465d90
return this.scaledRange(i);
}
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-index 17b6925b46f8386dcfc561483693de516465ec12..5d9a1855cdab1a25ad22ad096c68e55143efa821 100644
+index 366c0c9b45a819f7f94ebe3e49b8ab7f9edf9ce7..1cf8c819c0d7776c3b33d6594ca81abe3c2a719d 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -75,6 +75,9 @@ public class ServerChunkCache extends ChunkSource {
- final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f);
-
+@@ -77,6 +77,9 @@ public class ServerChunkCache extends ChunkSource {
private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4];
-+
+ // Paper end
+
+ public boolean firstRunSpawnCounts = true; // Pufferfish
+ public final java.util.concurrent.atomic.AtomicBoolean _pufferfish_spawnCountsReady = new java.util.concurrent.atomic.AtomicBoolean(false); // Pufferfish - optimize countmobs
-
- private static int getChunkCacheKey(int x, int z) {
- return x & 3 | ((z & 3) << 2);
-@@ -521,6 +524,7 @@ public class ServerChunkCache extends ChunkSource {
- ProfilerFiller gameprofilerfiller = this.level.getProfiler();
-
- gameprofilerfiller.push("pollingChunks");
-+ this.level.resetIceAndSnowTick(); // Pufferfish - reset ice & snow tick random
- int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
- boolean flag1 = level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
-
-@@ -530,28 +534,35 @@ public class ServerChunkCache extends ChunkSource {
- // Paper start - per player mob spawning
- NaturalSpawner.SpawnState spawnercreature_d; // moved down
- if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
-- // re-set mob counts
-- for (ServerPlayer player : this.level.players) {
-- // Paper start - per player mob spawning backoff
-- for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
-- player.mobCounts[ii] = 0;
--
-- int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
-- if (newBackoff < 0) {
-- newBackoff = 0;
-+ // Pufferfish start - moved down when async processing
-+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) {
-+ // re-set mob counts
-+ for (ServerPlayer player : this.level.players) {
-+ // Paper start - per player mob spawning backoff
-+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
-+ player.mobCounts[ii] = 0;
+
-+ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
-+ if (newBackoff < 0) {
-+ newBackoff = 0;
-+ }
-+ player.mobBackoffCounts[ii] = newBackoff;
+ public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory) {
+ this.level = world;
+ this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(world);
+@@ -513,6 +516,7 @@ public class ServerChunkCache extends ChunkSource {
+
+ // Paper - optimise chunk tick iteration
+
++ this.level.resetIceAndSnowTick(); // Pufferfish - reset ice & snow tick random
+ if (this.level.getServer().tickRateManager().runsNormally()) {
+ gameprofilerfiller.popPush("naturalSpawnCount");
+ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
+@@ -521,6 +525,7 @@ public class ServerChunkCache extends ChunkSource {
+ int naturalSpawnChunkCount = k;
+ NaturalSpawner.SpawnState spawnercreature_d; // moved down
+ if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
++ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning) { // Pufferfish - moved down when async processing
+ // re-set mob counts
+ for (ServerPlayer player : this.level.players) {
+ // Paper start - per player mob spawning backoff
+@@ -535,14 +540,18 @@ public class ServerChunkCache extends ChunkSource {
}
-- player.mobBackoffCounts[ii] = newBackoff;
-+ // Paper end - per player mob spawning backoff
+ // Paper end - per player mob spawning backoff
}
-- // Paper end - per player mob spawning backoff
-+ lastSpawnState = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
+- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
++ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); // Pufferfish - async mob spawning
++ } // Pufferfish - (endif) moved down when async processing
+ } else {
+- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
++ // Pufferfish start - async mob spawning
++ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
++ _pufferfish_spawnCountsReady.set(true);
++ // Pufferfish end
}
-- spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
-+ // Pufferfish end
- } else {
-- spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
-+ // Pufferfish start
-+ lastSpawnState = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
-+ _pufferfish_spawnCountsReady.set(true);
-+ // Pufferfish end
- }
- // Paper end
- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
+ // Paper end - Optional per player mob spawns
+ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
-- this.lastSpawnState = spawnercreature_d;
-+ //this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously
- gameprofilerfiller.popPush("filteringLoadedChunks");
- // Paper - optimise chunk tick iteration
- // Paper - optimise chunk tick iteration
-@@ -644,8 +655,8 @@ public class ServerChunkCache extends ChunkSource {
- // Paper end - optimise chunk tick iteration
- if (tick && chunk1.chunkStatus.isOrAfter(net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING)) { // Paper - optimise chunk tick iteration
- chunk1.incrementInhabitedTime(j);
-- if (spawn && flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration
-- NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
-+ if (spawn && flag2 && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning || _pufferfish_spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration // Pufferfish
-+ NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish
- }
+- this.lastSpawnState = spawnercreature_d;
++ // this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously
+ gameprofilerfiller.popPush("spawnAndTick");
+ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
- if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration
-@@ -691,6 +702,40 @@ public class ServerChunkCache extends ChunkSource {
+@@ -632,8 +641,8 @@ public class ServerChunkCache extends ChunkSource {
+ if (tick && chunk1.chunkStatus.isOrAfter(net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING)) {
+ // Paper end - optimise chunk tick iteration
+ chunk1.incrementInhabitedTime(j);
+- if (spawn && flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration
+- NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
++ if (spawn && flag && (!gg.pufferfish.pufferfish.PufferfishConfig.enableAsyncMobSpawning || _pufferfish_spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration // Pufferfish
++ NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish
+ }
+
+ if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration
+@@ -680,6 +689,40 @@ public class ServerChunkCache extends ChunkSource {
+ gameprofilerfiller.pop();
gameprofilerfiller.pop();
- this.chunkMap.tick();
}
+
+ // Pufferfish start - optimize mob spawning
@@ -1703,10 +1708,10 @@ index 17b6925b46f8386dcfc561483693de516465ec12..5d9a1855cdab1a25ad22ad096c68e551
private void getFullChunk(long pos, Consumer chunkConsumer) {
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
-index 35674f92a67f93382103c2766df4b678ba5c862f..d46e61640b241d32df05240dedd2c23f138725e6 100644
+index 529ab44baaf573b97cf7e89560c548642733188f..db55ad9aaabfa1ea998754f3ac352d1698936696 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
-@@ -177,7 +177,8 @@ public class ServerEntity {
+@@ -183,7 +183,8 @@ public class ServerEntity {
long i1 = this.positionCodec.encodeZ(vec3d);
boolean flag6 = k < -32768L || k > 32767L || l < -32768L || l > 32767L || i1 < -32768L || i1 > 32767L;
@@ -1716,7 +1721,7 @@ index 35674f92a67f93382103c2766df4b678ba5c862f..d46e61640b241d32df05240dedd2c23f
if ((!flag2 || !flag3) && !(this.entity instanceof AbstractArrow)) {
if (flag2) {
packet1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) k), (short) ((int) l), (short) ((int) i1), this.entity.onGround());
-@@ -191,6 +192,7 @@ public class ServerEntity {
+@@ -197,6 +198,7 @@ public class ServerEntity {
flag4 = true;
flag5 = true;
}
@@ -1725,18 +1730,18 @@ index 35674f92a67f93382103c2766df4b678ba5c862f..d46e61640b241d32df05240dedd2c23f
this.wasOnGround = this.entity.onGround();
this.teleportDelay = 0;
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index 17610196db7a1c6feb2cf74a02479a8691aa323f..c1b03e4c37ea85ddf283479682d0eb2eca57ee3c 100644
+index 502bdc726b7890b00ee36871d905dea44e8719e3..fbffe3dab1b7812b50df5d6bddf4fbdb2e583339 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -878,6 +878,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -894,6 +894,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
org.spigotmc.ActivationRange.activateEntities(this); // Spigot
- timings.entityTick.startTiming(); // Spigot
+ this.timings.entityTick.startTiming(); // Spigot
this.entityTickList.forEach((entity) -> {
+ entity.activatedPriorityReset = false; // Pufferfish - DAB
if (!entity.isRemoved()) {
if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed
entity.discard();
-@@ -897,7 +898,20 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -913,7 +914,20 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
gameprofilerfiller.push("tick");
@@ -1751,14 +1756,14 @@ index 17610196db7a1c6feb2cf74a02479a8691aa323f..c1b03e4c37ea85ddf283479682d0eb2e
+ final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
+ MinecraftServer.LOGGER.error(msg, throwable);
+ getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable)));
-+ entity.discard();
++ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
+ // Paper end
+ }
+ // Pufferfish end
gameprofilerfiller.pop();
}
}
-@@ -962,9 +976,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -978,9 +992,11 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
// Paper start - optimise random block ticking
private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos();
@@ -1771,35 +1776,27 @@ index 17610196db7a1c6feb2cf74a02479a8691aa323f..c1b03e4c37ea85ddf283479682d0eb2e
public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
ChunkPos chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
-@@ -975,7 +991,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -991,7 +1007,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
gameprofilerfiller.push("thunder");
final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
-- if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - disable thunder
-+ if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && /*this.random.nextInt(this.spigotConfig.thunderChance) == 0 &&*/ chunk.shouldDoLightning(this.random)) { // Spigot // Paper - disable thunder // Pufferfish - replace random with shouldDoLightning
+- if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder
++ if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && /*this.random.nextInt(this.spigotConfig.thunderChance) == 0 &&*/ chunk.shouldDoLightning(this.random)) { // Spigot // Paper - Option to disable thunder // Pufferfish - replace random with shouldDoLightning
blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-index 34fcdeb0f4039f1fc6c4c8c593cc615560af1ba2..ef6d8f787cba0db53270adedd923f9a47d435852 100644
+index fe2ef36ab5dc4b933abf24dbfd0e811c53239cf0..e725c1c0496383007ffb94c46fc18340666b5e29 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
-@@ -1118,6 +1118,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
+@@ -1135,6 +1135,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
@Override
public void handleEditBook(ServerboundEditBookPacket packet) {
+ if (!gg.pufferfish.pufferfish.PufferfishConfig.enableBooks && !this.player.getBukkitEntity().hasPermission("pufferfish.usebooks")) return; // Pufferfish
- // Paper start
+ // Paper start - Book size limits
if (!this.cserver.isPrimaryThread()) {
List pageList = packet.getPages();
-@@ -2273,6 +2274,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
- }
-
- private boolean updateChatOrder(Instant timestamp) {
-+ if (gg.pufferfish.pufferfish.PufferfishConfig.disableOutOfOrderChat) return true;
- Instant instant1;
-
- do {
diff --git a/src/main/java/net/minecraft/world/CompoundContainer.java b/src/main/java/net/minecraft/world/CompoundContainer.java
index 241fec02e6869c638d3a160819b32173a081467b..6a8f9e8f5bf108674c47018def28906e2d0a729c 100644
--- a/src/main/java/net/minecraft/world/CompoundContainer.java
@@ -1913,10 +1910,10 @@ index d6cbe98e67fdbf8db46338a88ab1356dd63b50a3..20dd3a63b2f955b05a75eb240e33ae4c
int LARGE_MAX_STACK_SIZE = 64;
int DEFAULT_DISTANCE_LIMIT = 8;
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
-index f20ae9153b7098980ce6c0e75fcbbb4da652661b..505ed0f8f933428192f5fc806ff52d84acea7f99 100644
+index 637478fd8a284e6833cf8f5fa17ccf9d73d1dd3f..1aa45e64e49ea011c2ba5e943b4e72c4f3a47176 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
-@@ -305,7 +305,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -309,7 +309,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
public double yo;
public double zo;
private Vec3 position;
@@ -1925,20 +1922,17 @@ index f20ae9153b7098980ce6c0e75fcbbb4da652661b..505ed0f8f933428192f5fc806ff52d84
private ChunkPos chunkPosition;
private Vec3 deltaMovement;
private float yRot;
-@@ -433,6 +433,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
- return this.originWorld;
- }
- // Paper end
-+ // Pufferfish start
-+ public boolean activatedPriorityReset = false; // DAB
-+ public int activatedPriority = gg.pufferfish.pufferfish.PufferfishConfig.maximumActivationPrio; // golf score
-+ public final BlockPos.MutableBlockPos cachedBlockPos = new BlockPos.MutableBlockPos(); // used where needed
-+ // Pufferfish end
-+
- public float getBukkitYaw() {
- return this.yRot;
- }
-@@ -765,6 +771,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -424,6 +424,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
+ private UUID originWorld;
+ public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
+ public boolean fixedPose = false; // Paper - Expand Pose API
++ public boolean activatedPriorityReset = false; // Pufferfish - DAB
++ public int activatedPriority = gg.pufferfish.pufferfish.PufferfishConfig.maximumActivationPrio; // Pufferfish - DAB (golf score)
++ public final BlockPos.MutableBlockPos cachedBlockPos = new BlockPos.MutableBlockPos(); // Pufferfish - reduce entity allocations
+
+ public void setOrigin(@javax.annotation.Nonnull Location location) {
+ this.origin = location.toVector();
+@@ -820,6 +823,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public void tick() {
@@ -1951,7 +1945,7 @@ index f20ae9153b7098980ce6c0e75fcbbb4da652661b..505ed0f8f933428192f5fc806ff52d84
this.baseTick();
}
-@@ -4324,16 +4336,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4421,16 +4430,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
}
public boolean updateFluidHeightAndDoFluidPushing(TagKey tag, double speed) {
@@ -1977,7 +1971,7 @@ index f20ae9153b7098980ce6c0e75fcbbb4da652661b..505ed0f8f933428192f5fc806ff52d84
double d1 = 0.0D;
boolean flag = this.isPushedByFluid();
boolean flag1 = false;
-@@ -4341,14 +4355,61 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4438,14 +4449,61 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
int k1 = 0;
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
@@ -2045,7 +2039,7 @@ index f20ae9153b7098980ce6c0e75fcbbb4da652661b..505ed0f8f933428192f5fc806ff52d84
if (d2 >= axisalignedbb.minY) {
flag1 = true;
-@@ -4370,9 +4431,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+@@ -4467,9 +4525,12 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
// CraftBukkit end
}
}
@@ -2059,10 +2053,10 @@ index f20ae9153b7098980ce6c0e75fcbbb4da652661b..505ed0f8f933428192f5fc806ff52d84
if (vec3d.length() > 0.0D) {
if (k1 > 0) {
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
-index 73871f456a85bda1e51f54986d0e61fb629822e8..2561e74ffdf595a9b6ae13dcd738662c772db442 100644
+index 09e8445a3f8c6b3ebc852a75a9a25b41a51ba659..dc11683ee4d8a6b7a1c42bcae36dc6e8105cd994 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
-@@ -301,6 +301,8 @@ public class EntityType implements FeatureElement, EntityTypeT
+@@ -305,6 +305,8 @@ public class EntityType implements FeatureElement, EntityTypeT
private final boolean canSpawnFarFromPlayer;
private final int clientTrackingRange;
private final int updateInterval;
@@ -2072,10 +2066,10 @@ index 73871f456a85bda1e51f54986d0e61fb629822e8..2561e74ffdf595a9b6ae13dcd738662c
private String descriptionId;
@Nullable
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-index b95f88d5e5b4785ee063695fd81935636a0588d1..2cdc2bd62f0cb62f75365b6b3e6d80d9a2132451 100644
+index e9bb7feb591032904516d1b9374f486d8a7d066c..366121188c5abb550ed0a5f99d25c001628685bb 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
-@@ -142,7 +142,6 @@ import org.bukkit.event.entity.EntityTeleportEvent;
+@@ -143,7 +143,6 @@ import org.bukkit.event.entity.EntityTeleportEvent;
import org.bukkit.event.player.PlayerItemConsumeEvent;
// CraftBukkit end
@@ -2092,7 +2086,7 @@ index b95f88d5e5b4785ee063695fd81935636a0588d1..2cdc2bd62f0cb62f75365b6b3e6d80d9
this.hurt(this.damageSources().inWall(), 1.0F);
} else if (flag && !this.level().getWorldBorder().isWithinBounds(this.getBoundingBox())) {
double d0 = this.level().getWorldBorder().getDistanceToBorder(this) + this.level().getWorldBorder().getDamageSafeZone();
-@@ -1401,6 +1400,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -1418,6 +1417,19 @@ public abstract class LivingEntity extends Entity implements Attackable {
return this.getHealth() <= 0.0F;
}
@@ -2112,7 +2106,7 @@ index b95f88d5e5b4785ee063695fd81935636a0588d1..2cdc2bd62f0cb62f75365b6b3e6d80d9
@Override
public boolean hurt(DamageSource source, float amount) {
if (this.isInvulnerableTo(source)) {
-@@ -1999,6 +2011,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
+@@ -2024,6 +2036,20 @@ public abstract class LivingEntity extends Entity implements Attackable {
return this.lastClimbablePos;
}
@@ -2134,10 +2128,10 @@ index b95f88d5e5b4785ee063695fd81935636a0588d1..2cdc2bd62f0cb62f75365b6b3e6d80d9
if (this.isSpectator()) {
return false;
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
-index d28c477171c1b6888a45175075017d960464b5cd..4cb836dfa7cbd2e634d4a3a567da0305aac0da4d 100644
+index d2c92df28475f0a32a0134324eb0a5609a9afb99..a6b48b4eab6e0e98205fd9cafc3cde5ad39651af 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
-@@ -220,14 +220,16 @@ public abstract class Mob extends LivingEntity implements Targeting {
+@@ -222,14 +222,16 @@ public abstract class Mob extends LivingEntity implements Targeting {
return this.lookControl;
}
@@ -2178,7 +2172,7 @@ index d28c477171c1b6888a45175075017d960464b5cd..4cb836dfa7cbd2e634d4a3a567da0305
this.level().getProfiler().pop();
}
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 7204b973c3ad9239e82355513f6d538107102e48..3087f8359b098682a345399c85395de8a15b6eed 100644
+index b99a080ab27e24d8131fda931ca70d6d271bb01c..8d6954d05d2bf6d6c1c4953db3127b011a858cec 100644
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
@@ -23,9 +23,11 @@ public class AttributeMap {
@@ -2189,29 +2183,27 @@ index 7204b973c3ad9239e82355513f6d538107102e48..3087f8359b098682a345399c85395de8
public AttributeMap(AttributeSupplier defaultAttributes) {
this.supplier = defaultAttributes;
-+ this.createInstance = attribute -> this.supplier.createInstance(this::onAttributeModified, attribute); // Pufferfish
++ this.createInstance = attributex -> this.supplier.createInstance(this::onAttributeModified, attributex); // Pufferfish
}
private void onAttributeModified(AttributeInstance instance) {
-@@ -45,11 +47,10 @@ public class AttributeMap {
- }).collect(Collectors.toList());
+@@ -42,9 +44,10 @@ public class AttributeMap {
+ return this.attributes.values().stream().filter(attribute -> attribute.getAttribute().isClientSyncable()).collect(Collectors.toList());
}
+
@Nullable
public AttributeInstance getInstance(Attribute attribute) {
-- return this.attributes.computeIfAbsent(attribute, (attributex) -> {
-- return this.supplier.createInstance(this::onAttributeModified, attributex);
-- });
+- return this.attributes.computeIfAbsent(attribute, attributex -> this.supplier.createInstance(this::onAttributeModified, attributex));
+ return this.attributes.computeIfAbsent(attribute, this.createInstance); // Pufferfish - cache lambda, as for some reason java allocates it anyways
}
@Nullable
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java
-index 646d9a121d908a2fc3e4e302484dd5cd1bfc6804..e546ecdccde352502e26a8668eaaafe048d6e282 100644
+index 758f62416ca9c02351348ac0d41deeb4624abc0e..69130969c9a434ec2361e573c9a1ec9f462dfda2 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java
-@@ -37,7 +37,11 @@ public class VillagerPanicTrigger extends Behavior {
+@@ -36,7 +36,11 @@ public class VillagerPanicTrigger extends Behavior {
@Override
protected void tick(ServerLevel world, Villager entity, long time) {
@@ -2223,12 +2215,12 @@ index 646d9a121d908a2fc3e4e302484dd5cd1bfc6804..e546ecdccde352502e26a8668eaaafe0
+ // Pufferfish end
entity.spawnGolemIfNeeded(world, time, 3);
}
-
+ }
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 b738ee2d3801fadfd09313f05ae24593e56b0ec6..1635818fc4b1788c0d397085239df6dd75b210ab 100644
+index 38af5c7280366fd6ec077f3d914ea5f3ee77451a..d78e1f6191738d426968efc24e734f04b0fc7edb 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
-@@ -53,9 +53,12 @@ public class GoalSelector {
+@@ -52,9 +52,12 @@ public class GoalSelector {
}
// Paper start
@@ -2244,27 +2236,27 @@ index b738ee2d3801fadfd09313f05ae24593e56b0ec6..1635818fc4b1788c0d397085239df6dd
public boolean hasTasks() {
for (WrappedGoal task : this.availableGoals) {
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 34f319ad09276c6f68dde449c79351de0d7d86f5..a719af0b512d9ef243d0d54f3b744b1b1a5f2772 100644
+index aee0147649d458b87d92496eda0c1723ebe570d2..89e9ea999d2fbd81a1d74382ef3fcd675fc8b94e 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
-@@ -119,6 +119,7 @@ public abstract class MoveToBlockGoal extends Goal {
- for(int m = 0; m <= l; m = m > 0 ? -m : 1 - m) {
- for(int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) {
+@@ -121,6 +121,7 @@ public abstract class MoveToBlockGoal extends Goal {
+ for (int m = 0; m <= l; m = m > 0 ? -m : 1 - m) {
+ for (int n = m < l && m > -l ? l : 0; n <= l; n = n > 0 ? -n : 1 - n) {
mutableBlockPos.setWithOffset(blockPos, m, k - 1, n);
+ if (!this.mob.level().hasChunkAt(mutableBlockPos)) continue; // Pufferfish - if this block isn't loaded, continue
if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) {
this.blockPos = mutableBlockPos;
- setTargetPosition(mutableBlockPos.immutable()); // Paper
+ this.mob.movingTarget = mutableBlockPos == BlockPos.ZERO ? null : mutableBlockPos.immutable(); // Paper
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 c157309ac78e7af084d3acb6e8b2bcd469a39d5e..ac5e5676b194a2a99e5cf53eb89c1152cac963b8 100644
+index d2f0c3b26d4beedb49d86e0242d843590d469d02..28cff997a1b263784e245f692adbff2a888a2d53 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
-@@ -75,9 +75,18 @@ public class TargetingConditions {
+@@ -76,9 +76,18 @@ public class TargetingConditions {
}
- if (this.range > 0.0D) {
-- double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D;
-- double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0D); // Paper
+ if (this.range > 0.0) {
+- double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0;
+- double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0); // Paper - Fix MC-145656
+ // Pufferfish start - check range before getting visibility
+ // d = invisibility percent, e = follow range adjusted for invisibility, f = distance
double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
@@ -2274,17 +2266,17 @@ index c157309ac78e7af084d3acb6e8b2bcd469a39d5e..ac5e5676b194a2a99e5cf53eb89c1152
+ return false;
+ }
+
-+ double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D;
-+ double e = Math.max((followRangeRaw) * d, 2.0D); // Paper
++ double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0;
++ double e = Math.max((followRangeRaw) * d, 2.0); // Paper - Fix MC-145656
+ // Pufferfish end
if (f > e * e) {
return false;
}
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 5beaa849a250ea005733250ad3edfa8382224667..2c91fe46355c9a201507de5577f693ed4f5fb974 100644
+index 44fa2d4f90389f5526746bd94a2450c03340bd0b..4fba7c2f6ec363846a772ef2a63e9b3fc1037de5 100644
--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
-@@ -237,13 +237,22 @@ public class Bat extends AmbientCreature {
+@@ -241,13 +241,22 @@ public class Bat extends AmbientCreature {
}
}
@@ -2325,10 +2317,10 @@ index 5ad5f22e5aa26445e5eb229958e7bf356bdd460e..d241ca4d0295f9fce39c11197bd435cf
this.level().getProfiler().pop();
this.level().getProfiler().push("allayActivityUpdate");
diff --git a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
-index aa850cfaa0534d57e83f37360724da2428a48a18..eb1e850f11ed1cd8d2f1f2eb1af55b7fe6352ed4 100644
+index b21e180641d17438997a80e5bcb0ec7998d24a2e..33c160994f70f71446d665e7487913437c9f9db4 100644
--- a/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
+++ b/src/main/java/net/minecraft/world/entity/animal/axolotl/Axolotl.java
-@@ -280,9 +280,11 @@ public class Axolotl extends Animal implements LerpingModel, VariantHolder {
- return true;
+@@ -183,9 +183,11 @@ public class Frog extends Animal implements VariantHolder {
+ }
}
+ private int behaviorTick = 0; // Pufferfish
@@ -2357,10 +2349,10 @@ index 5000ebc5f19dee72a86360062b822aecd60beb47..c8e3d47b3f2dc919cca8ad397095437f
this.level().getProfiler().pop();
this.level().getProfiler().push("frogActivityUpdate");
diff --git a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
-index 4aeab90e778629c355189dfe79c39c4b21f5f5ac..6ed4ac06c76b8d0d6e8db778cade15dbd1e3e5f5 100644
+index 958816ce2166248b542c96c10c398a52d769b4db..415afe3473d9f8a50b1edab8cfda6158e59836e6 100644
--- a/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
+++ b/src/main/java/net/minecraft/world/entity/animal/frog/Tadpole.java
-@@ -77,9 +77,11 @@ public class Tadpole extends AbstractFish {
+@@ -80,9 +80,11 @@ public class Tadpole extends AbstractFish {
return SoundEvents.TADPOLE_FLOP;
}
@@ -2373,7 +2365,7 @@ index 4aeab90e778629c355189dfe79c39c4b21f5f5ac..6ed4ac06c76b8d0d6e8db778cade15db
this.level().getProfiler().pop();
this.level().getProfiler().push("tadpoleActivityUpdate");
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 111a244087e24f25ba8524a46a228da10cd9498a..ff12ba2b79cb2e7e0bfd0e3b58ff6cb9e770092b 100644
+index 5d247ac38fe8a61603b3d934f3000bcda773142b..2e4177cfb02616ef6fa689f6d378976e39484cfb 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
@@ -191,9 +191,11 @@ public class Goat extends Animal {
@@ -2389,10 +2381,10 @@ index 111a244087e24f25ba8524a46a228da10cd9498a..ff12ba2b79cb2e7e0bfd0e3b58ff6cb9
this.level().getProfiler().pop();
this.level().getProfiler().push("goatActivityUpdate");
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 1e07febcf7a3dfb281728cc5e3e4f15dd776d7e0..c65ab566c6241dd6a44bd11a449ef0c4b2f6dc65 100644
+index 12440ee2dccc0a697fb403765f2e1b987ccc0283..de2471cfa96a23944f229f33ffdff88b6b7756e4 100644
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
-@@ -150,6 +150,13 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
+@@ -151,6 +151,13 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
this.bossEvent.setName(this.getDisplayName());
}
@@ -2407,7 +2399,7 @@ index 1e07febcf7a3dfb281728cc5e3e4f15dd776d7e0..c65ab566c6241dd6a44bd11a449ef0c4
protected SoundEvent getAmbientSound() {
return SoundEvents.WITHER_AMBIENT;
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 b0a97679157a18a3c623ce3b2ae315789772c254..9fc3db543a0c9df502df5fb85012c6aa590e887d 100644
+index f33c03e81b7ff643741f56eea055e6af260de618..6563e625ebae47fc68e5010d36bd4b4d327c07b7 100644
--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
+++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
@@ -333,11 +333,17 @@ public class EnderMan extends Monster implements NeutralMob {
@@ -2431,11 +2423,11 @@ index b0a97679157a18a3c623ce3b2ae315789772c254..9fc3db543a0c9df502df5fb85012c6aa
boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER);
diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
-index 4257f2282152aee09533c9a2e53018d3e49effa4..e703320717ff620a19ff76d1c10066117c9895d5 100644
+index 050ffa4a23feba29fdf4c6a175cdff4e5009027d..1299f93d4f983e6715e447add65df91ef9e9090a 100644
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/Hoglin.java
-@@ -128,9 +128,11 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
- return (Brain) super.getBrain(); // Paper - decompile fix
+@@ -155,9 +155,11 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
+ return (Brain)super.getBrain();
}
+ private int behaviorTick; // Pufferfish
@@ -2447,7 +2439,7 @@ index 4257f2282152aee09533c9a2e53018d3e49effa4..e703320717ff620a19ff76d1c1006611
this.level().getProfiler().pop();
HoglinAi.updateActivity(this);
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
-index 6407ddef8442fce4f310ac4babf3e3de0dd5fc9a..cfdc1650783d6855e0d4f33ec68aab48dbee09f0 100644
+index a9813da7f2b248f98f22e0ad2e7842915025ec12..83d83e3f84bb6bd58761671c6cd4c8683545ff4c 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
@@ -300,9 +300,11 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
@@ -2463,10 +2455,10 @@ index 6407ddef8442fce4f310ac4babf3e3de0dd5fc9a..cfdc1650783d6855e0d4f33ec68aab48
this.level().getProfiler().pop();
PiglinAi.updateActivity(this);
diff --git a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
-index b2bc3a832c310448046ccde37a04918aa6d63197..5e43912708f9074dee1bb351efa737a7e6796fc3 100644
+index 937f81a859953498abe73bea560c86e6560e1c33..0a151c679b0dc943598180942d6d4b3886211688 100644
--- a/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
+++ b/src/main/java/net/minecraft/world/entity/monster/warden/Warden.java
-@@ -272,11 +272,13 @@ public class Warden extends Monster implements VibrationSystem {
+@@ -273,11 +273,13 @@ public class Warden extends Monster implements VibrationSystem {
}
@@ -2481,10 +2473,10 @@ index b2bc3a832c310448046ccde37a04918aa6d63197..5e43912708f9074dee1bb351efa737a7
this.level().getProfiler().pop();
super.customServerAiStep();
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 f555e29c7f9ea4ddb243a018bdc93d2bf1950c3c..bbcc0356b4c0470502e893cf2dc2f16936a88bc4 100644
+index 24044795d8e0f1fb15a4f2f5401f44897092f2a3..96ca567af2d8fb2ba39f995be80b935344550124 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
-@@ -142,6 +142,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -143,6 +143,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
return holder.is(PoiTypes.MEETING);
});
@@ -2493,7 +2485,7 @@ index f555e29c7f9ea4ddb243a018bdc93d2bf1950c3c..bbcc0356b4c0470502e893cf2dc2f169
public Villager(EntityType extends Villager> entityType, Level world) {
this(entityType, world, VillagerType.PLAINS);
}
-@@ -245,6 +247,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -246,6 +248,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
}
// Spigot End
@@ -2501,7 +2493,7 @@ index f555e29c7f9ea4ddb243a018bdc93d2bf1950c3c..bbcc0356b4c0470502e893cf2dc2f169
@Override
@Deprecated // Paper
protected void customServerAiStep() {
-@@ -254,7 +257,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
+@@ -255,7 +258,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
protected void customServerAiStep(final boolean inactive) {
// Paper end
this.level().getProfiler().push("villagerBrain");
@@ -2515,7 +2507,7 @@ index f555e29c7f9ea4ddb243a018bdc93d2bf1950c3c..bbcc0356b4c0470502e893cf2dc2f169
if (this.assignProfessionWhenSpawned) {
this.assignProfessionWhenSpawned = false;
diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java
-index 96d664c28738d6090f7067761c2978dd1aa0fd0e..b1c24a02b87aca7b180a6efbce177f2300db49c1 100644
+index 96c898086f35fd83f9b1ce7e3fe53d31b2fa4c31..c6a925cbd35eb33b27b90bfa8344ac7515d28b76 100644
--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java
+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java
@@ -687,6 +687,8 @@ public class Inventory implements Container, Nameable {
@@ -2547,10 +2539,10 @@ index 96d664c28738d6090f7067761c2978dd1aa0fd0e..b1c24a02b87aca7b180a6efbce177f23
return false;
}
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 a90317100d32974e481e14476843f66997a2cf3a..cd0629581bae5f805842157af36c2d838e01bee3 100644
+index 156809090f1f83ad68e7e2477a3cfddac5757a8e..837f68825f601971f374be47952b23108bf66ba6 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
-@@ -44,6 +44,36 @@ public abstract class Projectile extends Entity implements TraceableEntity {
+@@ -45,6 +45,36 @@ public abstract class Projectile extends Entity implements TraceableEntity {
super(type, world);
}
@@ -2588,10 +2580,10 @@ index a90317100d32974e481e14476843f66997a2cf3a..cd0629581bae5f805842157af36c2d83
if (entity != null) {
this.ownerUUID = entity.getUUID();
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 272095d7a09ab41227d741172735f66fd2798ce1..47692d6db44b58bb724c87128279bd0d3e62a398 100644
+index 756d0434472921992c9d84597d7c9c824e93614c..38c573d440946ca7ee6016ef92e9c1605031e611 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
-@@ -27,7 +27,10 @@ import org.bukkit.inventory.InventoryHolder;
+@@ -28,7 +28,10 @@ import org.bukkit.inventory.InventoryHolder;
public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity {
@@ -2602,7 +2594,7 @@ index 272095d7a09ab41227d741172735f66fd2798ce1..47692d6db44b58bb724c87128279bd0d
@Nullable
public ResourceLocation lootTable;
public long lootTableSeed;
-@@ -89,12 +92,18 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
+@@ -90,12 +93,18 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
protected AbstractMinecartContainer(EntityType> type, Level world) {
super(type, world);
@@ -2623,7 +2615,7 @@ index 272095d7a09ab41227d741172735f66fd2798ce1..47692d6db44b58bb724c87128279bd0d
}
@Override
-@@ -156,6 +165,10 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
+@@ -164,6 +173,10 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
protected void readAdditionalSaveData(CompoundTag nbt) {
super.readAdditionalSaveData(nbt);
this.lootableData.loadNbt(nbt); // Paper
@@ -2635,7 +2627,7 @@ index 272095d7a09ab41227d741172735f66fd2798ce1..47692d6db44b58bb724c87128279bd0d
}
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
-index 5a19875cbc603acea95193d969d2e1dc1e0bfd78..3688e9f8c6c6d1239095e3a87060ccca90386d0c 100644
+index e1696f6b77df4c8fceaece64701d4db78b0a4c42..faa3f62d22266a3c32d6c95c3ffebd4aa3880739 100644
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
@@ -55,7 +55,7 @@ public class EndCrystalItem extends Item {
@@ -2644,11 +2636,11 @@ index 5a19875cbc603acea95193d969d2e1dc1e0bfd78..3688e9f8c6c6d1239095e3a87060ccca
- if (enderdragonbattle != null) {
+ if (enderdragonbattle != null && gg.pufferfish.pufferfish.PufferfishConfig.allowEndCrystalRespawn) { // Pufferfish
- enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - pass placed end crystal position to pre-check proximity to portal
+ enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - Perf: Do crystal-portal proximity check before entity lookup
}
}
diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
-index 38f7d1ece27ec1a3deda21fb6a6f0e788c8ed718..252fc22844682c0f67dc02a87478e01e49b6430d 100644
+index 27b0a79f7a7c47047216aae42944bac2a2151181..a097cfc528f709c80575f35483b6878314ea2717 100644
--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
+++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
@@ -26,8 +26,13 @@ public class ShapelessRecipe extends io.papermc.paper.inventory.recipe.RecipeBoo
@@ -2695,35 +2687,35 @@ index 38f7d1ece27ec1a3deda21fb6a6f0e788c8ed718..252fc22844682c0f67dc02a87478e01e
autorecipestackmanager.initialize(this); // Paper - better exact choice recipes
int i = 0;
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index ea8a0961190e9aafda4fed6fecd85097c141040a..1e2620338f0b6fd1c160a8f8d6b659e273f2f1c9 100644
+index ca89d1593bf1b46c79a882db528cbca1359dc9d4..a82de7111915b19cdc3f065910465a5e7e843aff 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -210,6 +210,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -215,6 +215,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ // Paper end
public abstract ResourceKey getTypeKey();
-
++
+ protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); public net.minecraft.util.RandomSource getThreadUnsafeRandom() { return this.randomTickRandom; } // Pufferfish - move thread unsafe random initialization // Pufferfish - getter
-+
- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
+
+ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config; Async-Anti-Xray: Pass executor
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
- this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper
-@@ -1308,13 +1310,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1317,13 +1319,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
try {
tickConsumer.accept(entity);
MinecraftServer.getServer().executeMidTickTasks(); // Paper - execute chunk tasks mid tick
- } catch (Throwable throwable) {
+ } catch (Throwable throwable) { // Pufferfish - diff on change ServerLevel.tick
if (throwable instanceof ThreadDeath) throw throwable; // Paper
- // Paper start - Prevent tile entity and entity crashes
+ // Paper start - Prevent block entity and entity crashes
final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
MinecraftServer.LOGGER.error(msg, throwable);
- getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
-- entity.discard();
-+ entity.discard(); // Pufferfish - diff on change ServerLevel.tick
- // Paper end
+ getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); // Paper - ServerExceptionEvent
+- entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
++ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Pufferfish - diff on change ServerLevel.tick
+ // Paper end - Prevent block entity and entity crashes
}
}
-@@ -1779,6 +1781,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1797,6 +1799,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
}
public ProfilerFiller getProfiler() {
@@ -2732,10 +2724,10 @@ index ea8a0961190e9aafda4fed6fecd85097c141040a..1e2620338f0b6fd1c160a8f8d6b659e2
}
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
-index 3cdddda9c0618e95288b81b975d499c8dd30c05f..9c2d62feff1816f5729060c6192269a5b2d34153 100644
+index da7489986848316fed029b71d1bc4e1248c9c9a8..661acdf4b1f33d150b0caf179e925d3162d7be35 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
-@@ -429,12 +429,12 @@ public final class NaturalSpawner {
+@@ -425,12 +425,12 @@ public final class NaturalSpawner {
}
}
@@ -2753,17 +2745,16 @@ index 3cdddda9c0618e95288b81b975d499c8dd30c05f..9c2d62feff1816f5729060c6192269a5
return new BlockPos(i, l, j);
}
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 65012a12e1430956ef55ced56773e6354ac26444..ed439b7e94646141c93a7dd3704d1cdeb5c27e16 100644
+index 64076a452a315090d299a7a58a43fd3b5c1b4e0a..0c317b0147a73a8075e0883f0c132f4db0bdfea7 100644
--- a/src/main/java/net/minecraft/world/level/biome/Biome.java
+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java
-@@ -66,14 +66,20 @@ public final class Biome {
+@@ -63,13 +63,18 @@ public final class Biome {
private final BiomeGenerationSettings generationSettings;
private final MobSpawnSettings mobSettings;
private final BiomeSpecialEffects specialEffects;
-- private final ThreadLocal temperatureCache = ThreadLocal.withInitial(() -> {
+- private final ThreadLocal temperatureCache = ThreadLocal.withInitial(() -> Util.make(() -> {
+ // Pufferfish start - use our cache
-+ private final ThreadLocal temperatureCache = ThreadLocal.withInitial(() -> {
- return Util.make(() -> {
++ private final ThreadLocal temperatureCache = ThreadLocal.withInitial(() -> Util.make(() -> {
+ /*
Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = new Long2FloatLinkedOpenHashMap(1024, 0.25F) {
protected void rehash(int i) {
@@ -2771,14 +2762,13 @@ index 65012a12e1430956ef55ced56773e6354ac26444..ed439b7e94646141c93a7dd3704d1cde
};
long2FloatLinkedOpenHashMap.defaultReturnValue(Float.NaN);
return long2FloatLinkedOpenHashMap;
-+
+ */
+ return new gg.airplane.structs.Long2FloatAgingCache(TEMPERATURE_CACHE_SIZE);
+ // Pufferfish end
- });
- });
+ }));
-@@ -118,17 +124,15 @@ public final class Biome {
+ Biome(Biome.ClimateSettings weather, BiomeSpecialEffects effects, BiomeGenerationSettings generationSettings, MobSpawnSettings spawnSettings) {
+@@ -112,17 +117,15 @@ public final class Biome {
@Deprecated
public float getTemperature(BlockPos blockPos) {
long l = blockPos.asLong();
@@ -2802,7 +2792,7 @@ index 65012a12e1430956ef55ced56773e6354ac26444..ed439b7e94646141c93a7dd3704d1cde
}
}
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 a71414397bd45ee7bcacfeef0041d80dfa25f114..d66806565770cb03a21794f99e5c4b0f3040b26a 100644
+index 9b1243d96e0694c62fc9e82e9be540bce0d2b3ad..3514022d898a24052c917ebf55dcef3e757d6836 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
@@ -31,7 +31,10 @@ import org.bukkit.entity.HumanEntity;
@@ -2880,10 +2870,10 @@ index a71414397bd45ee7bcacfeef0041d80dfa25f114..d66806565770cb03a21794f99e5c4b0f
@Override
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 1d9b23c6e458caddc2c738164e6c079cd85d3ce9..1cfacc7dfa4a761c4a4fb28f9bb02e95bace32f4 100644
+index cdb739df2a285032d25d84f4464f202a7a3fa578..6b9cd8543a5bfc2b936ba18f66ffd60f2f792e43 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
-@@ -47,7 +47,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -48,7 +48,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
public static final int MOVE_ITEM_SPEED = 8;
public static final int HOPPER_CONTAINER_SIZE = 5;
@@ -2891,10 +2881,10 @@ index 1d9b23c6e458caddc2c738164e6c079cd85d3ce9..1cfacc7dfa4a761c4a4fb28f9bb02e95
private NonNullList items;
+ private gg.airplane.structs.ItemListWithBitset optimizedItems; // Pufferfish
+ // Pufferfish end
- private int cooldownTime;
+ public int cooldownTime;
private long tickedGameTime;
-@@ -83,14 +86,37 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -84,14 +87,37 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
public HopperBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.HOPPER, pos, state);
@@ -2934,28 +2924,27 @@ index 1d9b23c6e458caddc2c738164e6c079cd85d3ce9..1cfacc7dfa4a761c4a4fb28f9bb02e95
if (!this.tryLoadLootTable(nbt)) {
ContainerHelper.loadAllItems(nbt, this.items);
}
-@@ -491,6 +517,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -492,6 +518,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
private static boolean isFullContainer(Container inventory, Direction direction) {
+ if (true) return inventory.isCompletelyFull(direction); // Pufferfish - use bitsets
- // Paper start - optimize hoppers
+ // Paper start - Perf: Optimize Hoppers
if (inventory instanceof WorldlyContainer worldlyContainer) {
for (final int slot : worldlyContainer.getSlotsForFace(direction)) {
-@@ -513,7 +540,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -514,7 +541,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
}
private static boolean isEmptyContainer(Container inv, Direction facing) {
-- return allMatch(inv, facing, IS_EMPTY_TEST);
-+ // Paper start
+- return allMatch(inv, facing, IS_EMPTY_TEST); // Paper - Perf: Optimize Hoppers
+ // Pufferfish start - use bitsets
-+ //return allMatch(inv, facing, IS_EMPTY_TEST);
++ //return allMatch(inv, facing, IS_EMPTY_TEST); // Paper - Perf: Optimize Hoppers
+ return inv.isCompletelyEmpty(facing);
+ // Pufferfish end
}
public static boolean suckInItems(Level world, Hopper hopper) {
-@@ -713,7 +744,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -714,7 +744,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
if (HopperBlockEntity.canPlaceItemInContainer(to, stack, slot, side)) {
boolean flag = false;
@@ -2964,7 +2953,7 @@ index 1d9b23c6e458caddc2c738164e6c079cd85d3ce9..1cfacc7dfa4a761c4a4fb28f9bb02e95
if (itemstack1.isEmpty()) {
// Spigot start - SPIGOT-6693, InventorySubcontainer#setItem
-@@ -908,7 +939,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
+@@ -909,7 +939,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@Override
protected void setItems(NonNullList list) {
@@ -2977,13 +2966,13 @@ index 1d9b23c6e458caddc2c738164e6c079cd85d3ce9..1cfacc7dfa4a761c4a4fb28f9bb02e95
public static void entityInside(Level world, BlockPos pos, BlockState state, Entity entity, HopperBlockEntity blockEntity) {
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 081691f9710ff1115e4308f79ed49fbc38941193..765ee7f78532a363813286ef7db2a7e48605cb06 100644
+index dfd1246b735fe64c5beae83567a013861eb00822..fa64bf5ad13c278438039b663ea3134e72108411 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
-@@ -96,12 +96,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
+@@ -94,12 +94,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
public boolean isEmpty() {
- this.unpackLootTable((Player)null);
- // Paper start
+ this.unpackLootTable(null);
+ // Paper start - Perf: Optimize Hoppers
- for (final ItemStack itemStack : this.getItems()) {
- if (!itemStack.isEmpty()) {
- return false;
@@ -2991,11 +2980,11 @@ index 081691f9710ff1115e4308f79ed49fbc38941193..765ee7f78532a363813286ef7db2a7e4
- }
- return true;
+ return this.isCompletelyEmpty(null); // Pufferfish - use super
- // Paper end
+ // Paper end - Perf: Optimize Hoppers
}
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 3e9758fa40bf93fe3d315cc66389193bd57bc393..b78476223637722efe12520d3c2e301603abd8a1 100644
+index 465458e8a7dbaf9afb32709a71c7b2620d1e1fd2..270a892373ecbb3982990d6201d79c8a66de4f60 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -86,6 +86,18 @@ public class LevelChunk extends ChunkAccess {
@@ -3027,7 +3016,7 @@ index 3e9758fa40bf93fe3d315cc66389193bd57bc393..b78476223637722efe12520d3c2e3016
// 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 f0de72afad4bb571153436399386a6a8a70582a6..45b7527341fcb6d24f35318cedb522646b5ee1c2 100644
+index 796bbef3544e06b8e7aac7e8ac5f740a2613f4bd..2422ca3ffc6ab7178cacf933b8013f85e7de4bd9 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -25,6 +25,7 @@ public class LevelChunkSection {
@@ -3054,19 +3043,19 @@ index f0de72afad4bb571153436399386a6a8a70582a6..45b7527341fcb6d24f35318cedb52264
}
this.updateBlockCallback(x, y, z, iblockdata1, state); // Paper - optimise collisions
-@@ -161,6 +164,7 @@ public class LevelChunkSection {
- if (fluid.isRandomlyTicking()) {
- this.tickingFluidCount = (short) (this.tickingFluidCount + 1);
- }
+@@ -162,6 +165,7 @@ public class LevelChunkSection {
+ if (fluid.isRandomlyTicking()) {
+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1);
+ }
+ this.fluidStateCount++; // Pufferfish
- }
+ }
- // Paper start - optimise collisions
+ // Paper start - optimise collisions
diff --git a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
-index 4cdfc433df67afcd455422e9baf56f167dd712ae..57fcf3910f45ce371ac2e237b277b1034caaac4e 100644
+index 83a39f900551e39d5af6f17a339a386ddee4feef..0c8c534fc69172387f188af5282accfed7597ac7 100644
--- a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
+++ b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java
-@@ -8,7 +8,7 @@ import javax.annotation.Nullable;
+@@ -9,7 +9,7 @@ import javax.annotation.Nullable;
import net.minecraft.world.entity.Entity;
public class EntityTickList {
@@ -3076,7 +3065,7 @@ index 4cdfc433df67afcd455422e9baf56f167dd712ae..57fcf3910f45ce371ac2e237b277b103
private void ensureActiveIsNotIterated() {
// Paper - replace with better logic, do not delay removals
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 e21f4c5aff3a8e97101f6efc1349fbecf326b5ea..c55f51e6db55f9fa66f53eef0e7a56af5f81d742 100644
+index 6d8ff6c06af5545634f255ed17dc1e489ece2548..6411aa4ff6bd4cabb25c426fa8f4a7eedb969c03 100644
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
@@ -45,6 +45,8 @@ public abstract class FlowingFluid extends Fluid {
@@ -3103,7 +3092,7 @@ index e21f4c5aff3a8e97101f6efc1349fbecf326b5ea..c55f51e6db55f9fa66f53eef0e7a56af
private final Map shapes = Maps.newIdentityHashMap();
public FlowingFluid() {}
-@@ -252,6 +262,8 @@ public abstract class FlowingFluid extends Fluid {
+@@ -251,6 +261,8 @@ public abstract class FlowingFluid extends Fluid {
return false;
}
// Paper end - optimise collisions
@@ -3112,7 +3101,7 @@ index e21f4c5aff3a8e97101f6efc1349fbecf326b5ea..c55f51e6db55f9fa66f53eef0e7a56af
Object2ByteLinkedOpenHashMap object2bytelinkedopenhashmap;
if (!state.getBlock().hasDynamicShape() && !fromState.getBlock().hasDynamicShape()) {
-@@ -259,9 +271,16 @@ public abstract class FlowingFluid extends Fluid {
+@@ -258,9 +270,16 @@ public abstract class FlowingFluid extends Fluid {
} else {
object2bytelinkedopenhashmap = null;
}
@@ -3129,7 +3118,7 @@ index e21f4c5aff3a8e97101f6efc1349fbecf326b5ea..c55f51e6db55f9fa66f53eef0e7a56af
if (object2bytelinkedopenhashmap != null) {
block_a = new Block.BlockStatePairKey(state, fromState, face);
byte b0 = object2bytelinkedopenhashmap.getAndMoveToFirst(block_a);
-@@ -272,11 +291,22 @@ public abstract class FlowingFluid extends Fluid {
+@@ -271,11 +290,22 @@ public abstract class FlowingFluid extends Fluid {
} else {
block_a = null;
}
@@ -3152,7 +3141,7 @@ index e21f4c5aff3a8e97101f6efc1349fbecf326b5ea..c55f51e6db55f9fa66f53eef0e7a56af
if (object2bytelinkedopenhashmap != null) {
if (object2bytelinkedopenhashmap.size() == 200) {
object2bytelinkedopenhashmap.removeLastByte();
-@@ -284,6 +314,11 @@ public abstract class FlowingFluid extends Fluid {
+@@ -283,6 +313,11 @@ public abstract class FlowingFluid extends Fluid {
object2bytelinkedopenhashmap.putAndMoveToFirst(block_a, (byte) (flag ? 1 : 0));
}
@@ -3165,7 +3154,7 @@ index e21f4c5aff3a8e97101f6efc1349fbecf326b5ea..c55f51e6db55f9fa66f53eef0e7a56af
return flag;
}
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java b/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java
-index e43d07ccdd36f0c9f5b8e9c74cf0d87e17eec66a..8e441f7c2b2d911a0c0111aaa231fc6adae08730 100644
+index 37a0002bbe6539648db5219bb373e0404ae48dc0..ca0571d232e102c4b177a1ea44b96f5f0f440211 100644
--- a/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java
+++ b/src/main/java/net/minecraft/world/level/storage/loot/LootParams.java
@@ -21,8 +21,10 @@ public class LootParams {
@@ -3182,10 +3171,10 @@ index e43d07ccdd36f0c9f5b8e9c74cf0d87e17eec66a..8e441f7c2b2d911a0c0111aaa231fc6a
}
diff --git a/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java b/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java
-index ebe65474a4a05ff1637d7f37ebcfe690af59def5..42142c512b12e5b269c19f1e821c50e7496a5f25 100644
+index 88a4a72bb390947dc17e5da09a99b2d1b3ac4621..284c76ddb9724b44bb2e93f590685c728e843e6d 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/EntityCollisionContext.java
-@@ -19,47 +19,66 @@ public class EntityCollisionContext implements CollisionContext {
+@@ -17,50 +17,69 @@ public class EntityCollisionContext implements CollisionContext {
return defaultValue;
}
};
@@ -3216,16 +3205,23 @@ index ebe65474a4a05ff1637d7f37ebcfe690af59def5..42142c512b12e5b269c19f1e821c50e7
this.entity = entity;
}
- /** @deprecated */
@Deprecated
protected EntityCollisionContext(Entity entity) {
-- this(entity.isDescending(), entity.getY(), entity instanceof LivingEntity ? ((LivingEntity)entity).getMainHandItem() : ItemStack.EMPTY, entity instanceof LivingEntity ? ((LivingEntity)entity)::canStandOnFluid : (fluidState) -> {
-- return false;
-- }, entity);
+- this(
+- entity.isDescending(),
+- entity.getY(),
+- entity instanceof LivingEntity ? ((LivingEntity)entity).getMainHandItem() : ItemStack.EMPTY,
+- entity instanceof LivingEntity ? ((LivingEntity)entity)::canStandOnFluid : fluidState -> false,
+- entity
+- );
+ // Pufferfish start - remove this
-+ // this(entity.isDescending(), entity.getY(), entity instanceof LivingEntity ? ((LivingEntity)entity).getMainHandItem() : ItemStack.EMPTY, entity instanceof LivingEntity ? ((LivingEntity)entity)::canStandOnFluid : (fluidState) -> {
-+ // return false;
-+ // }, entity);
++ // this(
++ // entity.isDescending(),
++ // entity.getY(),
++ // entity instanceof LivingEntity ? ((LivingEntity)entity).getMainHandItem() : ItemStack.EMPTY,
++ // entity instanceof LivingEntity ? ((LivingEntity)entity)::canStandOnFluid : fluidState -> false,
++ // entity
++ // );
+ // Pufferfish end
+ this.entity = entity;
}
@@ -3262,16 +3258,16 @@ index ebe65474a4a05ff1637d7f37ebcfe690af59def5..42142c512b12e5b269c19f1e821c50e7
@Override
public boolean isAbove(VoxelShape shape, BlockPos pos, boolean defaultValue) {
-- return this.entityBottom > (double)pos.getY() + shape.max(Direction.Axis.Y) - (double)1.0E-5F;
-+ return (this.entity == null ? -Double.MAX_VALUE : entity.getY()) > (double)pos.getY() + shape.max(Direction.Axis.Y) - (double)1.0E-5F; // Pufferfish
+- return this.entityBottom > (double)pos.getY() + shape.max(Direction.Axis.Y) - 1.0E-5F;
++ return (this.entity == null ? -Double.MAX_VALUE : entity.getY()) > (double)pos.getY() + shape.max(Direction.Axis.Y) - 1.0E-5F; // Pufferfish
}
@Nullable
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-index b7e7e6ed60f55d2ab5e4fcefb3638ad1768c3b7f..5a95dcc02241d6036ee520a6a7a05e8713c6081f 100644
+index c490a29bcf7410bc54959ee71375605964379ed5..18bfe2fb7efad66f5fae07a30593d640c597bf77 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-@@ -267,7 +267,7 @@ import javax.annotation.Nullable; // Paper
+@@ -266,7 +266,7 @@ import javax.annotation.Nullable; // Paper
import javax.annotation.Nonnull; // Paper
public final class CraftServer implements Server {
@@ -3280,7 +3276,7 @@ index b7e7e6ed60f55d2ab5e4fcefb3638ad1768c3b7f..5a95dcc02241d6036ee520a6a7a05e87
private final String serverVersion;
private final String bukkitVersion = Versioning.getBukkitVersion();
private final Logger logger = Logger.getLogger("Minecraft");
-@@ -1122,6 +1122,11 @@ public final class CraftServer implements Server {
+@@ -1137,6 +1137,11 @@ public final class CraftServer implements Server {
plugin.getPluginMeta().getDisplayName(),
"This plugin is not properly shutting down its async tasks when it is being shut down. This task may throw errors during the final shutdown logs and might not complete before process dies."
));
@@ -3291,13 +3287,13 @@ index b7e7e6ed60f55d2ab5e4fcefb3638ad1768c3b7f..5a95dcc02241d6036ee520a6a7a05e87
+ }
}
}
- // Paper end
+ // Paper end - Wait for Async Tasks during shutdown
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
-index acfe2676b840d4edc70507aa139f7db212ed90b7..ef89684b5e8ab20744ba02a71fe0465d197f627d 100644
+index 96d772eb02f79f8c478f5e6f065e387aa7665b18..c5ce412f321b8b4f31cc042893659e213b081f29 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
@@ -45,6 +45,6 @@ public class CraftShapelessRecipe extends ShapelessRecipe implements CraftRecipe
- data.set(i, toNMS(ingred.get(i), true));
+ data.set(i, this.toNMS(ingred.get(i), true));
}
- MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.ShapelessRecipe(this.getGroup(), CraftRecipe.getCategory(this.getCategory()), CraftItemStack.asNMSCopy(this.getResult()), data)));
@@ -3305,10 +3301,10 @@ index acfe2676b840d4edc70507aa139f7db212ed90b7..ef89684b5e8ab20744ba02a71fe0465d
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
-index 806fb1064a1769d1251f2a2b04372275754d2aeb..3298aac109e08da4801a6f08aa6f7acfc5e6bf16 100644
+index 3c7a771c48cc2732cc038ca11bb93ec5f8c2d667..94681c5d807019be5caf0b5d5156c0d670f45f8f 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
-@@ -462,7 +462,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
+@@ -502,7 +502,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
@Override
public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() {
@@ -3331,7 +3327,7 @@ index 774556a62eb240da42e84db4502e2ed43495be17..80553face9c70c2a3d897681e7761df8
if (stream != null) {
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
-index 2f9e5a1adf9d67ffe18d95f2822ca3d2288fb27a..14e8e7ad8d742cdc0c50d29d6dade3e338c0463e 100644
+index 3283ed99c35ffed6805567705e0518d9f84feedc..d7c7e12c0b8f77e59d94de130972f762ed227726 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -38,6 +38,10 @@ import co.aikar.timings.MinecraftTimings;
@@ -3345,9 +3341,9 @@ index 2f9e5a1adf9d67ffe18d95f2822ca3d2288fb27a..14e8e7ad8d742cdc0c50d29d6dade3e3
public class ActivationRange
{
-@@ -222,6 +226,25 @@ public class ActivationRange
+@@ -223,6 +227,25 @@ public class ActivationRange
}
- // Paper end - configurable marker ticking
+ // Paper end - Configurable marker ticking
ActivationRange.activateEntity(entity);
+
+ // Pufferfish start
@@ -3371,7 +3367,7 @@ index 2f9e5a1adf9d67ffe18d95f2822ca3d2288fb27a..14e8e7ad8d742cdc0c50d29d6dade3e3
}
// Paper end
}
-@@ -238,12 +261,12 @@ public class ActivationRange
+@@ -239,12 +262,12 @@ public class ActivationRange
if ( MinecraftServer.currentTick > entity.activatedTick )
{
if ( entity.defaultActivationState )
@@ -3386,12 +3382,12 @@ index 2f9e5a1adf9d67ffe18d95f2822ca3d2288fb27a..14e8e7ad8d742cdc0c50d29d6dade3e3
entity.activatedTick = MinecraftServer.currentTick;
}
}
-@@ -297,7 +320,7 @@ public class ActivationRange
+@@ -298,7 +321,7 @@ public class ActivationRange
if ( entity instanceof LivingEntity )
{
LivingEntity living = (LivingEntity) entity;
-- if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper
-+ if ( living.onClimableCached() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper // Pufferfish - use cached
+- if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 || living.isFreezing()) // Paper
++ if ( living.onClimableCached() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 || living.isFreezing() ) // Paper // Pufferfish - use cached
{
return 1; // Paper
}
diff --git a/patches/server/0002-Fix-pufferfish-issues.patch b/patches/unapplied-server/0003-Fix-pufferfish-issues.patch
similarity index 57%
rename from patches/server/0002-Fix-pufferfish-issues.patch
rename to patches/unapplied-server/0003-Fix-pufferfish-issues.patch
index 6ded7b179..cae584b75 100644
--- a/patches/server/0002-Fix-pufferfish-issues.patch
+++ b/patches/unapplied-server/0003-Fix-pufferfish-issues.patch
@@ -4,24 +4,29 @@ Date: Sun, 12 Jun 2022 09:18:57 -0500
Subject: [PATCH] Fix pufferfish issues
-diff --git a/build.gradle.kts b/build.gradle.kts
-index 57739f9dd7d045d1a585a9fc1be290a1a007db6a..f8b27b3992f1d59bf0e95bba0961540e88345754 100644
---- a/build.gradle.kts
-+++ b/build.gradle.kts
-@@ -229,5 +229,7 @@ val runtimeClasspathForRunDev = sourceSets.main.flatMap { src ->
- }
- tasks.registerRunTask("runDev") {
- description = "Spin up a non-relocated Mojang-mapped test server"
-- classpath(sourceSets.main.map { it.runtimeClasspath })
-+ classpath(tasks.filterProjectDir.flatMap { it.outputJar })
-+ classpath(runtimeClasspathForRunDev)
-+ jvmArgs("-DPaper.isRunDev=true")
- }
diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
-index cc66657cb4f978aa2df3ca1be6c683759952cc7a..26f08b7fb16484c39135ed172c246f76c9e089c7 100644
+index 6464682e2f93659e73aca491031c8051ab000033..5a73aa17a963ae2d57e9bd5b5e3e5b0030d06216 100644
--- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
-@@ -224,7 +224,7 @@ public class PufferfishConfig {
+@@ -86,7 +86,7 @@ public class PufferfishConfig {
+ // Attempt to detect vectorization
+ try {
+ SIMDDetection.isEnabled = SIMDDetection.canEnable(PufferfishLogger.LOGGER);
+- SIMDDetection.versionLimited = SIMDDetection.getJavaVersion() != 17 && SIMDDetection.getJavaVersion() != 18 && SIMDDetection.getJavaVersion() != 19;
++ SIMDDetection.versionLimited = SIMDDetection.getJavaVersion() < 17 || SIMDDetection.getJavaVersion() > 21;
+ } catch (NoClassDefFoundError | Exception ignored) {
+ ignored.printStackTrace();
+ }
+@@ -94,7 +94,7 @@ public class PufferfishConfig {
+ if (SIMDDetection.isEnabled) {
+ PufferfishLogger.LOGGER.info("SIMD operations detected as functional. Will replace some operations with faster versions.");
+ } else if (SIMDDetection.versionLimited) {
+- PufferfishLogger.LOGGER.warning("Will not enable SIMD! These optimizations are only safely supported on Java 17, Java 18, and Java 19.");
++ PufferfishLogger.LOGGER.warning("Will not enable SIMD! These optimizations are only safely supported on Java 17 through Java 21.");
+ } else {
+ PufferfishLogger.LOGGER.warning("SIMD operations are available for your server, but are not configured!");
+ PufferfishLogger.LOGGER.warning("To enable additional optimizations, add \"--add-modules=jdk.incubator.vector\" to your startup flags, BEFORE the \"-jar\".");
+@@ -232,7 +232,7 @@ public class PufferfishConfig {
public static int activationDistanceMod;
private static void dynamicActivationOfBrains() throws IOException {
@@ -30,7 +35,7 @@ index cc66657cb4f978aa2df3ca1be6c683759952cc7a..26f08b7fb16484c39135ed172c246f76
startDistance = getInt("dab.start-distance", "activation-range.start-distance", 12,
"This value determines how far away an entity has to be",
"from the player to start being effected by DEAR.");
-@@ -268,7 +268,7 @@ public class PufferfishConfig {
+@@ -276,7 +276,7 @@ public class PufferfishConfig {
public static boolean throttleInactiveGoalSelectorTick;
private static void inactiveGoalSelectorThrottle() {
@@ -40,10 +45,10 @@ index cc66657cb4f978aa2df3ca1be6c683759952cc7a..26f08b7fb16484c39135ed172c246f76
"This can improve performance by a few percent, but has minor gameplay implications.");
}
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
-index c1b03e4c37ea85ddf283479682d0eb2eca57ee3c..cf2fd8eba6aa4cf15cac924577507a700f7f72b5 100644
+index fbffe3dab1b7812b50df5d6bddf4fbdb2e583339..881ba370b098a4a202fbfb9c5c3d9304719d155e 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
-@@ -976,7 +976,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+@@ -992,7 +992,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
}
// Paper start - optimise random block ticking
private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos();
@@ -52,21 +57,49 @@ index c1b03e4c37ea85ddf283479682d0eb2eca57ee3c..cf2fd8eba6aa4cf15cac924577507a70
// Paper end
private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Pufferfish
+diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
+index 1aa45e64e49ea011c2ba5e943b4e72c4f3a47176..6f7b34357788faecf8368cc9a27d26585935f789 100644
+--- a/src/main/java/net/minecraft/world/entity/Entity.java
++++ b/src/main/java/net/minecraft/world/entity/Entity.java
+@@ -825,7 +825,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
+ public void tick() {
+ // Pufferfish start - entity TTL
+ if (type != EntityType.PLAYER && type.ttl >= 0 && this.tickCount >= type.ttl) {
+- discard();
++ discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Purpur
+ return;
+ }
+ // Pufferfish end - entity TTL
+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 837f68825f601971f374be47952b23108bf66ba6..2a8a8030feefae84e394460612405887e63f2ac7 100644
+--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
++++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+@@ -64,7 +64,7 @@ public abstract class Projectile extends Entity implements TraceableEntity {
+ if (!isLoaded) {
+ if (Projectile.loadedThisTick > gg.pufferfish.pufferfish.PufferfishConfig.maxProjectileLoadsPerTick) {
+ if (++this.loadedLifetime > gg.pufferfish.pufferfish.PufferfishConfig.maxProjectileLoadsPerProjectile) {
+- this.discard();
++ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); // Purpur
+ }
+ return;
+ }
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index 1e2620338f0b6fd1c160a8f8d6b659e273f2f1c9..6c0e33323922de72dcb941a10883a07c72808b5f 100644
+index a82de7111915b19cdc3f065910465a5e7e843aff..fc32b6342b7553265f2a012f91f4dd9c0386f8f2 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
-@@ -210,7 +210,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -215,8 +215,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ // Paper end
public abstract ResourceKey getTypeKey();
-
+-
- protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); public net.minecraft.util.RandomSource getThreadUnsafeRandom() { return this.randomTickRandom; } // Pufferfish - move thread unsafe random initialization // Pufferfish - getter
++
+ //protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); public net.minecraft.util.RandomSource getThreadUnsafeRandom() { return this.randomTickRandom; } // Pufferfish - move thread unsafe random initialization // Pufferfish - getter // Purpur - dont break ABI
- protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
+ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config; Async-Anti-Xray: Pass executor
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
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 b78476223637722efe12520d3c2e301603abd8a1..e2ea90469352346b43f0a86746179a6adc53d82a 100644
+index 270a892373ecbb3982990d6201d79c8a66de4f60..d087c8271dbdfe3dc6d805539a710d37ed6d7f21 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -122,7 +122,7 @@ public class LevelChunk extends ChunkAccess {
diff --git a/patches/server/0275-Make-pufferfish-config-relocatable.patch b/patches/unapplied-server/0269-Make-pufferfish-config-relocatable.patch
similarity index 85%
rename from patches/server/0275-Make-pufferfish-config-relocatable.patch
rename to patches/unapplied-server/0269-Make-pufferfish-config-relocatable.patch
index 6ae92addc..c81d41c1e 100644
--- a/patches/server/0275-Make-pufferfish-config-relocatable.patch
+++ b/patches/unapplied-server/0269-Make-pufferfish-config-relocatable.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Make pufferfish config relocatable
diff --git a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
-index 26f08b7fb16484c39135ed172c246f76c9e089c7..9ca1494497ae53e56b1f81fda51b0b8bd02a6d03 100644
+index 5a73aa17a963ae2d57e9bd5b5e3e5b0030d06216..8afc58f35deb49084a20b803e91ce4692ce6e4d6 100644
--- a/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
+++ b/src/main/java/gg/pufferfish/pufferfish/PufferfishConfig.java
@@ -28,6 +28,7 @@ public class PufferfishConfig {
@@ -26,22 +26,22 @@ index 26f08b7fb16484c39135ed172c246f76c9e089c7..9ca1494497ae53e56b1f81fda51b0b8b
if (configFile.exists()) {
try {
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
-index 207a76f91758a8643976414a8732573d488bf1df..813a3c0172f1152665b95104d155e5de40589b39 100644
+index 6a9bd431e9c2e1fc1e51d394eaccba864bbeac89..85b861e21d8798a883ecbd0a09cc25f87e801b7b 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -230,6 +230,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
- com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
- io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider
- // Paper end
+ // Purpur end
+ com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
+ io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // Paper - init PaperBrigadierProvider
+ gg.pufferfish.pufferfish.PufferfishConfig.pufferfishFile = (java.io.File) options.valueOf("pufferfish-settings"); // Purpur
gg.pufferfish.pufferfish.PufferfishConfig.load(); // Pufferfish
gg.pufferfish.pufferfish.PufferfishCommand.init(); // Pufferfish
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
-index 45f63f2fedee7bcab9cd3ebc3117cecd225b89d2..67c621fdc994b392dc961f79e1e3b97c2977adc4 100644
+index 1dd676ad37c68e3fce71306d7e05cb2c377a32b4..409c0e81571e23c9d535b541c61538424259d60a 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
-@@ -179,6 +179,12 @@ public class Main {
+@@ -180,6 +180,12 @@ public class Main {
.ofType(File.class)
.defaultsTo(new File("purpur.yml"))
.describedAs("Yml file");
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 7f07d28d5..0ff9678cd 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,7 +8,7 @@ pluginManagement {
}
plugins {
- id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0"
+ id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
if (!file(".git").exists()) {
@@ -32,8 +32,26 @@ if (!file(".git").exists()) {
}
rootProject.name = "purpur"
-for (name in listOf("Purpur-API", "Purpur-Server")) {
+for (name in listOf("Purpur-API", "Purpur-Server", "paper-api-generator")) {
val projName = name.lowercase(Locale.ENGLISH)
include(projName)
findProject(":$projName")!!.projectDir = file(name)
}
+
+optionalInclude("test-plugin")
+
+fun optionalInclude(name: String, op: (ProjectDescriptor.() -> Unit)? = null) {
+ val settingsFile = file("$name.settings.gradle.kts")
+ if (settingsFile.exists()) {
+ apply(from = settingsFile)
+ findProject(":$name")?.let { op?.invoke(it) }
+ } else {
+ settingsFile.writeText(
+ """
+ // Uncomment to enable the '$name' project
+ // include(":$name")
+
+ """.trimIndent()
+ )
+ }
+}
diff --git a/test-plugin/build.gradle.kts b/test-plugin/build.gradle.kts
new file mode 100644
index 000000000..4e1830aa8
--- /dev/null
+++ b/test-plugin/build.gradle.kts
@@ -0,0 +1,17 @@
+version = "1.0.0-SNAPSHOT"
+
+dependencies {
+ compileOnly(project(":purpur-api"))
+}
+
+tasks.processResources {
+ val apiVersion = rootProject.providers.gradleProperty("mcVersion").get()
+ val props = mapOf(
+ "version" to project.version,
+ "apiversion" to "\"$apiVersion\"",
+ )
+ inputs.properties(props)
+ filesMatching("paper-plugin.yml") {
+ expand(props)
+ }
+}
diff --git a/test-plugin/src/main/java/org/purpurmc/testplugin/TestPlugin.java b/test-plugin/src/main/java/org/purpurmc/testplugin/TestPlugin.java
new file mode 100644
index 000000000..39e2b3557
--- /dev/null
+++ b/test-plugin/src/main/java/org/purpurmc/testplugin/TestPlugin.java
@@ -0,0 +1,12 @@
+package org.purpurmc.testplugin;
+
+import org.bukkit.event.Listener;
+import org.bukkit.plugin.java.JavaPlugin;
+
+public class TestPlugin extends JavaPlugin implements Listener {
+
+ @Override
+ public void onEnable() {
+ this.getServer().getPluginManager().registerEvents(this, this);
+ }
+}
diff --git a/test-plugin/src/main/java/org/purpurmc/testplugin/TestPluginBootstrap.java b/test-plugin/src/main/java/org/purpurmc/testplugin/TestPluginBootstrap.java
new file mode 100644
index 000000000..612aa3e6f
--- /dev/null
+++ b/test-plugin/src/main/java/org/purpurmc/testplugin/TestPluginBootstrap.java
@@ -0,0 +1,4 @@
+package org.purpurmc.testplugin;
+
+public class TestPluginBootstrap {
+}
diff --git a/test-plugin/src/main/java/org/purpurmc/testplugin/TestPluginLoader.java b/test-plugin/src/main/java/org/purpurmc/testplugin/TestPluginLoader.java
new file mode 100644
index 000000000..6a00427bd
--- /dev/null
+++ b/test-plugin/src/main/java/org/purpurmc/testplugin/TestPluginLoader.java
@@ -0,0 +1,4 @@
+package org.purpurmc.testplugin;
+
+public class TestPluginLoader {
+}
diff --git a/test-plugin/src/main/resources/paper-plugin.yml b/test-plugin/src/main/resources/paper-plugin.yml
new file mode 100644
index 000000000..3418d110e
--- /dev/null
+++ b/test-plugin/src/main/resources/paper-plugin.yml
@@ -0,0 +1,12 @@
+name: Purpur-Test-Plugin
+version: ${version}
+main: org.purpurmc.testplugin.TestPlugin
+description: Purpur Test Plugin
+author: PurpurMC
+api-version: ${apiversion}
+load: STARTUP
+bootstrapper: org.purpurmc.testplugin.TestPluginBootstrap
+loader: org.purpurmc.testplugin.TestPluginLoader
+defaultPerm: FALSE
+permissions:
+dependencies: