From 3390082ea72e70d288bd72958fa532485b87698a Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 13 Jun 2021 22:32:56 -0700 Subject: [PATCH] progress --- .../Add-villager-reputation-API.patch | 0 .../Potential-bed-API.patch | 0 ...rioritise-own-classes-where-possible.patch | 4 +- ...-a-useful-PluginClassLoader-toString.patch | 0 .../Spawn-Reason-API.patch | 0 ...ze-NibbleArray-to-use-pooled-buffers.patch | 394 ------------------ ...te-operations-for-updating-light-dat.patch | 320 -------------- ...ound-for-Client-Lag-Spikes-MC-162253.patch | 137 ------ ...n-for-console-having-all-permissions.patch | 13 - .../Add-villager-reputation-API.patch | 21 +- ...der-respects-game-and-entity-rules-f.patch | 0 .../Ensure-safe-gateway-teleport.patch | 25 +- ...on-Full-Status-Chunk-NBT-Memory-Leak.patch | 12 +- .../Fix-PotionEffect-ignores-icon-flag.patch | 4 +- ...-brigadier-child-sorting-performance.patch | 7 +- .../Potential-bed-API.patch | 2 +- ...and-End-Portal-Frames-from-being-des.patch | 12 +- ...bleInt-allocations-from-light-engine.patch | 30 +- ...llocation-of-Vec3D-by-entity-tracker.patch | 16 +- ...Wait-for-Async-Tasks-during-shutdown.patch | 0 20 files changed, 58 insertions(+), 939 deletions(-) rename patches/{api-unmapped => api}/Add-villager-reputation-API.patch (100%) rename patches/{api-unmapped => api}/Potential-bed-API.patch (100%) rename patches/{api-unmapped => api}/Prioritise-own-classes-where-possible.patch (94%) rename patches/{api-unmapped => api}/Provide-a-useful-PluginClassLoader-toString.patch (100%) rename patches/{api-unmapped => api}/Spawn-Reason-API.patch (100%) delete mode 100644 patches/server-remapped/Optimize-NibbleArray-to-use-pooled-buffers.patch delete mode 100644 patches/server-remapped/Stop-copy-on-write-operations-for-updating-light-dat.patch delete mode 100644 patches/server-remapped/Workaround-for-Client-Lag-Spikes-MC-162253.patch rename patches/{server-remapped => server}/Add-option-for-console-having-all-permissions.patch (80%) rename patches/{server-remapped => server}/Add-villager-reputation-API.patch (94%) rename patches/{server-remapped => server}/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch (100%) rename patches/{server-remapped => server}/Ensure-safe-gateway-teleport.patch (51%) rename patches/{server-remapped => server}/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch (82%) rename patches/{server-remapped => server}/Fix-PotionEffect-ignores-icon-flag.patch (61%) rename patches/{server-remapped => server}/Optimize-brigadier-child-sorting-performance.patch (80%) rename patches/{server-remapped => server}/Potential-bed-API.patch (97%) rename patches/{server-remapped => server}/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch (90%) rename patches/{server-remapped => server}/Reduce-MutableInt-allocations-from-light-engine.patch (69%) rename patches/{server-remapped => server}/Reduce-allocation-of-Vec3D-by-entity-tracker.patch (85%) rename patches/{server-remapped => server}/Wait-for-Async-Tasks-during-shutdown.patch (100%) diff --git a/patches/api-unmapped/Add-villager-reputation-API.patch b/patches/api/Add-villager-reputation-API.patch similarity index 100% rename from patches/api-unmapped/Add-villager-reputation-API.patch rename to patches/api/Add-villager-reputation-API.patch diff --git a/patches/api-unmapped/Potential-bed-API.patch b/patches/api/Potential-bed-API.patch similarity index 100% rename from patches/api-unmapped/Potential-bed-API.patch rename to patches/api/Potential-bed-API.patch diff --git a/patches/api-unmapped/Prioritise-own-classes-where-possible.patch b/patches/api/Prioritise-own-classes-where-possible.patch similarity index 94% rename from patches/api-unmapped/Prioritise-own-classes-where-possible.patch rename to patches/api/Prioritise-own-classes-where-possible.patch index 3826df3296..9f75bf62cc 100644 --- a/patches/api-unmapped/Prioritise-own-classes-where-possible.patch +++ b/patches/api/Prioritise-own-classes-where-possible.patch @@ -82,5 +82,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - Class result = loader.getClassByName(name, resolve, description); + Class result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self - // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. - if (result != null && result.getClassLoader() instanceof PluginClassLoader) { + if (result != null) { + // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. diff --git a/patches/api-unmapped/Provide-a-useful-PluginClassLoader-toString.patch b/patches/api/Provide-a-useful-PluginClassLoader-toString.patch similarity index 100% rename from patches/api-unmapped/Provide-a-useful-PluginClassLoader-toString.patch rename to patches/api/Provide-a-useful-PluginClassLoader-toString.patch diff --git a/patches/api-unmapped/Spawn-Reason-API.patch b/patches/api/Spawn-Reason-API.patch similarity index 100% rename from patches/api-unmapped/Spawn-Reason-API.patch rename to patches/api/Spawn-Reason-API.patch diff --git a/patches/server-remapped/Optimize-NibbleArray-to-use-pooled-buffers.patch b/patches/server-remapped/Optimize-NibbleArray-to-use-pooled-buffers.patch deleted file mode 100644 index 18f8f5966c..0000000000 --- a/patches/server-remapped/Optimize-NibbleArray-to-use-pooled-buffers.patch +++ /dev/null @@ -1,394 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 6 May 2020 23:30:30 -0400 -Subject: [PATCH] Optimize NibbleArray to use pooled buffers - -Massively reduces memory allocation of 2048 byte buffers by using -an object pool for these. - -Uses lots of advanced new capabilities of the Paper codebase :) - -diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundLightUpdatePacket.java -@@ -0,0 +0,0 @@ - package net.minecraft.network.protocol.game; - - import com.google.common.collect.Lists; -+import io.netty.channel.ChannelFuture; // Paper -+ - import java.io.IOException; - import java.util.Iterator; - import java.util.List; - import net.minecraft.core.SectionPos; - import net.minecraft.network.FriendlyByteBuf; - import net.minecraft.network.protocol.Packet; -+import net.minecraft.server.MCUtil; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.level.ChunkPos; - import net.minecraft.world.level.LightLayer; - import net.minecraft.world.level.chunk.DataLayer; -@@ -0,0 +0,0 @@ public class ClientboundLightUpdatePacket implements Packet blockUpdates; - private boolean trustEdges; - -+ // Paper start -+ java.lang.Runnable cleaner1; -+ java.lang.Runnable cleaner2; -+ java.util.concurrent.atomic.AtomicInteger remainingSends = new java.util.concurrent.atomic.AtomicInteger(0); -+ -+ @Override -+ public void onPacketDispatch(ServerPlayer player) { -+ remainingSends.incrementAndGet(); -+ } -+ -+ @Override -+ public void onPacketDispatchFinish(ServerPlayer player, ChannelFuture future) { -+ if (remainingSends.decrementAndGet() <= 0) { -+ // incase of any race conditions, schedule this delayed -+ MCUtil.scheduleTask(5, () -> { -+ if (remainingSends.get() == 0) { -+ cleaner1.run(); -+ cleaner2.run(); -+ } -+ }, "Light Packet Release"); -+ } -+ } -+ -+ @Override -+ public boolean hasFinishListener() { -+ return true; -+ } -+ -+ // Paper end - public ClientboundLightUpdatePacket() {} - - public ClientboundLightUpdatePacket(ChunkPos chunkcoordintpair, LevelLightEngine lightengine, boolean flag) { - this.x = chunkcoordintpair.x; - this.z = chunkcoordintpair.z; - this.trustEdges = flag; -- this.skyUpdates = Lists.newArrayList(); -- this.blockUpdates = Lists.newArrayList(); -+ this.skyUpdates = Lists.newArrayList();cleaner1 = MCUtil.registerListCleaner(this, this.skyUpdates, DataLayer::releaseBytes); // Paper -+ this.blockUpdates = Lists.newArrayList();cleaner2 = MCUtil.registerListCleaner(this, this.blockUpdates, DataLayer::releaseBytes); // Paper - - for (int i = 0; i < 18; ++i) { - DataLayer nibblearray = lightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, -1 + i)); -@@ -0,0 +0,0 @@ public class ClientboundLightUpdatePacket implements Packet BYTE_2048 = new PooledObjects<>(() -> new byte[2048], maxPoolSize); -+ public static void releaseBytes(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE && bytes.length == 2048) { -+ System.arraycopy(EMPTY_NIBBLE, 0, bytes, 0, 2048); -+ BYTE_2048.release(bytes); -+ } -+ } -+ -+ public DataLayer markPoolSafe(byte[] bytes) { -+ if (bytes != EMPTY_NIBBLE) this.data = bytes; -+ return markPoolSafe(); -+ } -+ public DataLayer markPoolSafe() { -+ poolSafe = true; -+ return this; -+ } -+ public byte[] getIfSet() { -+ return this.data != null ? this.data : EMPTY_NIBBLE; -+ } -+ public byte[] getCloneIfSet() { -+ if (data == null) { -+ return EMPTY_NIBBLE; -+ } -+ byte[] ret = BYTE_2048.acquire(); -+ System.arraycopy(getIfSet(), 0, ret, 0, 2048); -+ return ret; -+ } -+ -+ public DataLayer cloneAndSet(byte[] bytes) { -+ if (bytes != null && bytes != EMPTY_NIBBLE) { -+ this.data = BYTE_2048.acquire(); -+ System.arraycopy(bytes, 0, this.data, 0, 2048); -+ } -+ return this; -+ } -+ boolean poolSafe = false; -+ public java.lang.Runnable cleaner; -+ private void registerCleaner() { -+ if (!poolSafe) { -+ cleaner = MCUtil.registerCleaner(this, this.data, DataLayer::releaseBytes); -+ } else { -+ cleaner = MCUtil.once(() -> DataLayer.releaseBytes(this.data)); -+ } -+ } -+ // Paper end -+ @Nullable protected byte[] data; -+ - - public DataLayer() {} - - public DataLayer(byte[] abyte) { -+ // Paper start -+ this(abyte, false); -+ } -+ public DataLayer(byte[] abyte, boolean isSafe) { - this.data = abyte; -+ if (!isSafe) this.data = getCloneIfSet(); // Paper - clone for safety -+ registerCleaner(); -+ // Paper end - if (abyte.length != 2048) { - throw (IllegalArgumentException) Util.pauseInIde((Throwable) (new IllegalArgumentException("ChunkNibbleArrays should be 2048 bytes not: " + abyte.length))); - } -@@ -0,0 +0,0 @@ public class DataLayer { - - public void set(int index, int value) { // PAIL: private -> public - if (this.data == null) { -- this.data = new byte[2048]; -+ this.data = BYTE_2048.acquire(); // Paper -+ registerCleaner();// Paper - } - - int k = this.getPosition(index); -@@ -0,0 +0,0 @@ public class DataLayer { - public byte[] getData() { - if (this.data == null) { - this.data = new byte[2048]; -+ } else { // Paper start -+ // Accessor may need this object past garbage collection so need to clone it and return pooled value -+ // If we know its safe for pre GC access, use asBytesPoolSafe(). If you just need read, use getIfSet() -+ Runnable cleaner = this.cleaner; -+ if (cleaner != null) { -+ this.data = this.data.clone(); -+ cleaner.run(); // release the previously pooled value -+ this.cleaner = null; -+ } -+ } -+ // Paper end -+ -+ return this.data; -+ } -+ -+ @Nonnull -+ public byte[] asBytesPoolSafe() { -+ if (this.data == null) { -+ this.data = BYTE_2048.acquire(); // Paper -+ registerCleaner(); // Paper - } - -+ //noinspection ConstantConditions - return this.data; - } -+ // Paper end - - public DataLayer copy() { return this.copy(); } // Paper - OBFHELPER - public DataLayer copy() { -- return this.data == null ? new DataLayer() : new DataLayer((byte[]) this.data.clone()); -+ return this.data == null ? new DataLayer() : new DataLayer(this.data); // Paper - clone in ctor - } - - public String toString() { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -0,0 +0,0 @@ public class ChunkSerializer { - } - - if (nibblearray != null && !nibblearray.isEmpty()) { -- nbttagcompound2.putByteArray("BlockLight", nibblearray.getData()); -+ nbttagcompound2.putByteArray("BlockLight", nibblearray.asBytesPoolSafe().clone()); // Paper - } - - if (nibblearray1 != null && !nibblearray1.isEmpty()) { -- nbttagcompound2.putByteArray("SkyLight", nibblearray1.getData()); -+ nbttagcompound2.putByteArray("SkyLight", nibblearray1.asBytesPoolSafe().clone()); // Paper - } - - nbttaglist.add(nbttagcompound2); -diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -@@ -0,0 +0,0 @@ package net.minecraft.world.level.lighting; - - import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - import javax.annotation.Nullable; -+import net.minecraft.server.MCUtil; - import net.minecraft.world.level.chunk.DataLayer; - - public abstract class DataLayerStorageMap> { -@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { - - public void copyDataLayer(long pos) { - if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -- this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data -+ DataLayer updating = this.data.getUpdating(pos); // Paper - pool nibbles -+ this.data.queueUpdate(pos, new DataLayer().markPoolSafe(updating.getCloneIfSet())); // Paper - avoid copying light data - pool safe clone -+ if (updating.cleaner != null) MCUtil.scheduleTask(2, updating.cleaner, "Light Engine Release"); // Paper - delay clean incase anything holding ref was still using it - this.clearCache(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java -+++ b/src/main/java/net/minecraft/world/level/lighting/FlatDataLayer.java -@@ -0,0 +0,0 @@ public class FlatDataLayer extends DataLayer { - - public FlatDataLayer(DataLayer nibblearray, int i) { - super(128); -- System.arraycopy(nibblearray.getData(), i * 128, this.data, 0, 128); -+ System.arraycopy(nibblearray.getIfSet(), i * 128, this.data, 0, 128); // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class FlatDataLayer extends DataLayer { - - @Override - public byte[] getData() { -- byte[] abyte = new byte[2048]; -+ byte[] abyte = BYTE_2048.acquire(); // Paper - - for (int i = 0; i < 16; ++i) { - System.arraycopy(this.data, 0, abyte, i * 128, 128); -diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> - protected DataLayer createDataLayer(long sectionPos) { - DataLayer nibblearray = (DataLayer) this.queuedSections.get(sectionPos); - -- return nibblearray != null ? nibblearray : new DataLayer(); -+ return nibblearray != null ? nibblearray : new DataLayer().markPoolSafe(); // Paper - } - - protected void clearQueuedSectionBlocks(LayerLightEngine storage, long sectionPos) { -@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> - - protected void queueSectionData(long sectionPos, @Nullable DataLayer array, boolean flag) { - if (array != null) { -- this.queuedSections.put(sectionPos, array); -+ DataLayer remove = this.queuedSections.put(sectionPos, array); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - if (!flag) { - this.untrustedSections.add(sectionPos); - } - } else { -- this.queuedSections.remove(sectionPos); -+ DataLayer remove = this.queuedSections.remove(sectionPos); if (remove != null && remove.cleaner != null) remove.cleaner.run(); // Paper - clean up when removed - } - - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage -Date: Mon, 27 Apr 2020 04:05:38 -0700 -Subject: [PATCH] Stop copy-on-write operations for updating light data - -Causes huge memory allocations + gc issues - -diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.LightChunkGetter; - public class BlockLightSectionStorage extends LayerLightSectionStorage { - - protected BlockLightSectionStorage(LightChunkGetter chunkProvider) { -- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap())); -+ super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data - } - - @Override -@@ -0,0 +0,0 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage { - -- public BlockDataLayerStorageMap(Long2ObjectOpenHashMap arrays) { -- super(arrays); -+ public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data -+ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data - } - - @Override - public BlockLightSectionStorage.BlockDataLayerStorageMap copy() { -- return new BlockLightSectionStorage.BlockDataLayerStorageMap(this.map.clone()); -+ return new BlockDataLayerStorageMap(this.data, true); // Paper - avoid copying light data - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java -@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { - private final long[] lastSectionKeys = new long[2]; - private final DataLayer[] lastSections = new DataLayer[2]; - private boolean cacheEnabled; -- protected final Long2ObjectOpenHashMap map; -- -- protected DataLayerStorageMap(Long2ObjectOpenHashMap arrays) { -- this.map = arrays; -+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data; // Paper - avoid copying light data -+ protected final boolean isVisible; // Paper - avoid copying light data -+ java.util.function.Function lookup; // Paper - faster branchless lookup -+ -+ // Paper start - avoid copying light data -+ protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, boolean isVisible) { -+ if (isVisible) { -+ data.performUpdatesLockMap(); -+ } -+ this.data = data; -+ this.isVisible = isVisible; -+ if (isVisible) { -+ lookup = data::getVisibleAsync; -+ } else { -+ lookup = data::getUpdating; -+ } -+ // Paper end - avoid copying light data - this.clearCache(); - this.cacheEnabled = true; - } -@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { - public abstract M copy(); - - public void copyDataLayer(long pos) { -- this.map.put(pos, ((DataLayer) this.map.get(pos)).copy()); -+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -+ this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data - this.clearCache(); - } - - public boolean hasLayer(long chunkPos) { -- return this.map.containsKey(chunkPos); -+ return lookup.apply(chunkPos) != null; // Paper - avoid copying light data - } - - @Nullable -- public DataLayer getLayer(long chunkPos) { -+ public final DataLayer getLayer(long chunkPos) { // Paper - final - if (this.cacheEnabled) { - for (int j = 0; j < 2; ++j) { - if (chunkPos == this.lastSectionKeys[j]) { -@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { - } - } - -- DataLayer nibblearray = (DataLayer) this.map.get(chunkPos); -+ DataLayer nibblearray = lookup.apply(chunkPos); // Paper - avoid copying light data - - if (nibblearray == null) { - return null; -@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { - - @Nullable - public DataLayer removeLayer(long chunkPos) { -- return (DataLayer) this.map.remove(chunkPos); -+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -+ return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data - } - - public void setLayer(long pos, DataLayer data) { -- this.map.put(pos, data); -+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data -+ this.data.queueUpdate(pos, data); // Paper - avoid copying light data - } - - public void clearCache() { -@@ -0,0 +0,0 @@ public abstract class DataLayerStorageMap> { - this.lastSectionKeys[i] = Long.MAX_VALUE; - this.lastSections[i] = null; - } -- - } - - public void disableCache() { -diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java -@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> - protected final LongSet dataSectionSet = new LongOpenHashSet(); - protected final LongSet toMarkNoData = new LongOpenHashSet(); - protected final LongSet toMarkData = new LongOpenHashSet(); -- protected volatile M visibleSectionData; -- protected final M updatingSectionData; -+ protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change -+ protected final M updatingSectionData; // Paper - diff on change, should be "updating" - protected final LongSet changedSections = new LongOpenHashSet(); - protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet(); - protected final Long2ObjectMap queuedSections = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap()); -@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> - this.layer = lightType; - this.chunkSource = chunkProvider; - this.updatingSectionData = lightData; -- this.visibleSectionData = lightData.copy(); -- this.visibleSectionData.disableCache(); -+ this.e_visible = lightData.copy(); // Paper - avoid copying light data -+ this.e_visible.disableCache(); // Paper - avoid copying light data - } - - protected boolean storingLightForSection(long sectionPos) { -@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> - - @Nullable - protected DataLayer getDataLayer(long sectionPos, boolean cached) { -- return this.getDataLayer(cached ? this.updatingSectionData : this.visibleSectionData, sectionPos); -+ // Paper start - avoid copying light data -+ if (cached) { -+ return this.getDataLayer(this.updatingSectionData, sectionPos); -+ } else { -+ synchronized (this.visibleUpdateLock) { -+ return this.getDataLayer(this.e_visible, sectionPos); -+ } -+ } -+ // Paper end - avoid copying light data - } - - @Nullable -@@ -0,0 +0,0 @@ public abstract class LayerLightSectionStorage> - - protected void swapSectionMap() { - if (!this.changedSections.isEmpty()) { -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data - M m0 = this.updatingSectionData.copy(); - - m0.disableCache(); -- this.visibleSectionData = m0; -+ this.e_visible = m0; // Paper - avoid copying light data -+ } // Paper - avoid copying light data - this.changedSections.clear(); - } - -diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java -@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data - } - - @Override - protected int getLightValue(long blockPos) { - long j = SectionPos.blockToSection(blockPos); - int k = SectionPos.y(j); -- SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.visibleSectionData; -- int l = lightenginestoragesky_a.topSections.get(SectionPos.getZeroNode(j)); -+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data -+ SkyLightSectionStorage.SkyDataLayerStorageMap lightenginestoragesky_a = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire -+ int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPos.getZeroNode(j)); // Paper - avoid copying light data - - if (l != lightenginestoragesky_a.currentLowestY && k < l) { - DataLayer nibblearray = this.getDataLayer(lightenginestoragesky_a, j); // Paper - decompile fix -@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage j) { - ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY = j; -- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.defaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); -+ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueDefaultReturnValue(((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY); // Paper - avoid copying light data - } - - long k = SectionPos.getZeroNode(sectionPos); -- int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.get(k); -+ int l = ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.getUpdating(k); // Paper - avoid copying light data - - if (l < j + 1) { -- ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).topSections.put(k, j + 1); -+ ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data - if (this.columnsWithSkySources.contains(k)) { - this.queueAddSource(sectionPos); - if (l > ((SkyLightSectionStorage.SkyDataLayerStorageMap) this.updatingSectionData).currentLowestY) { -@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage= k; - } -@@ -0,0 +0,0 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage { - - private int currentLowestY; -- private final Long2IntOpenHashMap topSections; -- -- public SkyDataLayerStorageMap(Long2ObjectOpenHashMap arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) { -- super(arrays); -- this.topSections = columnToTopSection; -- columnToTopSection.defaultReturnValue(minSectionY); -- this.currentLowestY = minSectionY; -+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data -+ -+ // Paper start - avoid copying light data -+ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) { -+ super(data, isVisible); -+ this.otherData = otherData; -+ otherData.queueDefaultReturnValue(i); -+ // Paper end - avoid copying light data -+ this.currentLowestY = i; - } - - @Override - public SkyLightSectionStorage.SkyDataLayerStorageMap copy() { -- return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.map.clone(), this.topSections.clone(), this.currentLowestY); -+ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data -+ return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.data, this.otherData, this.currentLowestY, true); // Paper - avoid copying light data - } - } - } diff --git a/patches/server-remapped/Workaround-for-Client-Lag-Spikes-MC-162253.patch b/patches/server-remapped/Workaround-for-Client-Lag-Spikes-MC-162253.patch deleted file mode 100644 index 2c73a3952a..0000000000 --- a/patches/server-remapped/Workaround-for-Client-Lag-Spikes-MC-162253.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MeFisto94 -Date: Tue, 12 May 2020 23:02:43 +0200 -Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253) - -When crossing certain chunk boundaries, the client needlessly -calculates light maps for chunk neighbours. In some specific map -configurations, these calculations cause a 500ms+ freeze on the Client. - -This patch basically serves as a workaround by sending light maps -to the client, so that it doesn't attempt to calculate them. -This mitigates the frametime impact to a minimum (but it's still there). - -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.chunk.ChunkStatus; - import net.minecraft.world.level.chunk.ImposterProtoChunk; - import net.minecraft.world.level.chunk.LevelChunk; -+import net.minecraft.world.level.chunk.LevelChunkSection; - import net.minecraft.world.level.chunk.LightChunkGetter; - import net.minecraft.world.level.chunk.ProtoChunk; - import net.minecraft.world.level.chunk.UpgradeData; -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - // Paper start - private static int getLightMask(final LevelChunk chunk) { -- final ChunkSection[] chunkSections = chunk.getSections(); -+ final LevelChunkSection[] chunkSections = chunk.getSections(); - int mask = 0; - - for (int i = 0; i < chunkSections.length; ++i) { -@@ -0,0 +0,0 @@ Lightmasks have 18 bits, from the -1 (void) section until the 17th (air) section - Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. - - */ -- mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; -+ mask |= (LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; - } - - return mask; -@@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially - public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { - if (packets[0] == null) { -+ // Paper start - add 8 for light fix workaround -+ if (packets.length != 10) { // in case Plugins call sendChunk, resize -+ packets = new Packet[10]; -+ } -+ // Paper end - packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass - packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, true); -+ -+ // Paper start - Fix MC-162253 -+ final int lightMask = getLightMask(chunk); -+ int i = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++i; -+ -+ if (!chunk.isNeighbourLoaded(x, z)) { -+ continue; -+ } -+ -+ final LevelChunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z); -+ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor); -+ -+ if (updateLightMask == 0) { -+ continue; -+ } -+ -+ packets[i] = new ClientboundLightUpdatePacket(new ChunkPos(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, updateLightMask, 0, true); -+ } -+ } -+ } -+ -+ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(player); -+ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(player); -+ -+ int j = 1; -+ for (int x = -1; x <= 1; x++) { -+ for (int z = -1; z <= 1; z++) { -+ if (x == 0 && z == 0) { -+ continue; -+ } -+ -+ ++j; -+ -+ Packet packet = packets[j]; -+ if (packet == null) { -+ continue; -+ } -+ -+ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x)); -+ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z)); -+ -+ if (Math.max(distX, distZ) > viewDistance) { -+ continue; -+ } -+ player.connection.send(packet); -+ } - } -+ // Paper end - Fix MC-162253 - - player.trackChunk(chunk.getPos(), packets[0], packets[1]); - DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos()); -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { - - // broadcast - Object[] backingSet = inRange.getBackingSet(); -- Packet[] chunkPackets = new Packet[2]; -+ Packet[] chunkPackets = new Packet[10]; - for (int index = 0, len = backingSet.length; index < len; ++index) { - Object temp = backingSet[index]; - if (!(temp instanceof ServerPlayer)) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -0,0 +0,0 @@ public class LevelChunkSection { - return this.nonEmptyBlockCount == 0; - } - -+ public static boolean isEmpty(@Nullable LevelChunkSection chunksection) { return isEmpty(chunksection) ; } // Paper - OBFHELPER - public static boolean isEmpty(@Nullable LevelChunkSection section) { - return section == LevelChunk.EMPTY_SECTION || section.isEmpty(); - } diff --git a/patches/server-remapped/Add-option-for-console-having-all-permissions.patch b/patches/server/Add-option-for-console-having-all-permissions.patch similarity index 80% rename from patches/server-remapped/Add-option-for-console-having-all-permissions.patch rename to patches/server/Add-option-for-console-having-all-permissions.patch index 8a3d3c7786..04bfb9f787 100644 --- a/patches/server-remapped/Add-option-for-console-having-all-permissions.patch +++ b/patches/server/Add-option-for-console-having-all-permissions.patch @@ -18,19 +18,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } -diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/player/Player.java -+++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -0,0 +0,0 @@ public abstract class Player extends LivingEntity { - } - } - -- protected void removeEntitiesOnShoulder() { -+ public void removeEntitiesOnShoulder() { // Paper - protected -> public - if (this.timeEntitySatOnShoulder + 20L < this.level.getGameTime()) { - // CraftBukkit start - if (this.spawnEntityFromShoulder(this.getShoulderEntityLeft())) { diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java diff --git a/patches/server-remapped/Add-villager-reputation-API.patch b/patches/server/Add-villager-reputation-API.patch similarity index 94% rename from patches/server-remapped/Add-villager-reputation-API.patch rename to patches/server/Add-villager-reputation-API.patch index d5652a809e..43ba8e9449 100644 --- a/patches/server-remapped/Add-villager-reputation-API.patch +++ b/patches/server/Add-villager-reputation-API.patch @@ -13,8 +13,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package com.destroystokyo.paper.entity.villager; +// Must have own package due to package-level constructor. + -+import Reputation; -+ +public final class ReputationConstructor { + // Abuse the package-level constructor. + public static Reputation construct(int[] values) { @@ -25,29 +23,24 @@ diff --git a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer. index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java +++ b/src/main/java/net/minecraft/world/entity/ai/gossip/GossipContainer.java -@@ -0,0 +0,0 @@ import net.minecraft.core.SerializableUUID; +@@ -0,0 +0,0 @@ import net.minecraft.util.VisibleForDebug; public class GossipContainer { - + public static final int DISCARD_THRESHOLD = 2; - private final Map gossips = Maps.newHashMap(); + private final Map gossips = Maps.newHashMap(); public Map getReputations() { return this.gossips; } // Paper - add getter for reputations - public GossipContainer() {} - + @VisibleForDebug + public Map> getGossipEntries() { @@ -0,0 +0,0 @@ public class GossipContainer { - return k > type.max ? Math.max(type.max, left) : k; + return i > type.max ? Math.max(type.max, left) : i; } - static class EntityGossips { + public static class EntityGossips { // Paper - make public + final Object2IntMap entries = new Object2IntOpenHashMap<>(); - private final Object2IntMap entries; - -- private EntityGossips() { -+ public EntityGossips() { // Paper - make public - update CraftVillager setReputation on change - this.entries = new Object2IntOpenHashMap(); - } - + public int weightedValue(Predicate gossipTypeFilter) { @@ -0,0 +0,0 @@ public class GossipContainer { public void remove(GossipType gossipType) { this.entries.removeInt(gossipType); diff --git a/patches/server-remapped/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch b/patches/server/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch similarity index 100% rename from patches/server-remapped/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch rename to patches/server/Ensure-EntityRaider-respects-game-and-entity-rules-f.patch diff --git a/patches/server-remapped/Ensure-safe-gateway-teleport.patch b/patches/server/Ensure-safe-gateway-teleport.patch similarity index 51% rename from patches/server-remapped/Ensure-safe-gateway-teleport.patch rename to patches/server/Ensure-safe-gateway-teleport.patch index 77beeb98f4..ed45257899 100644 --- a/patches/server-remapped/Ensure-safe-gateway-teleport.patch +++ b/patches/server/Ensure-safe-gateway-teleport.patch @@ -8,20 +8,19 @@ diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayB index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -0,0 +0,0 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity implements - } else if (!this.level.isClientSide) { - List list = this.level.getEntitiesOfClass(Entity.class, new AABB(this.getBlockPos()), TheEndGatewayBlockEntity::canEntityTeleport); +@@ -0,0 +0,0 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + List list = world.getEntitiesOfClass(Entity.class, new AABB(pos), TheEndGatewayBlockEntity::canEntityTeleport); -- if (!list.isEmpty()) { -- this.teleportEntity((Entity) list.get(this.level.random.nextInt(list.size()))); -+ // Paper start -+ for (Entity entity : list) { -+ if (entity.canChangeDimensions()) { -+ this.teleportEntity(entity); -+ break; + if (!list.isEmpty()) { +- TheEndGatewayBlockEntity.teleportEntity(world, pos, state, (Entity) list.get(world.random.nextInt(list.size())), blockEntity); ++ // Paper start ++ for (Entity entity : list) { ++ if (entity.canChangeDimensions()) { ++ TheEndGatewayBlockEntity.teleportEntity(world, pos, state, entity, blockEntity); ++ break; ++ } + } ++ // Paper end } -+ // Paper end - if (this.age % 2400L == 0L) { - this.triggerCooldown(); + if (blockEntity.age % 2400L == 0L) { diff --git a/patches/server-remapped/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch b/patches/server/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch similarity index 82% rename from patches/server-remapped/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch rename to patches/server/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch index 50f3a230b2..e4009f1419 100644 --- a/patches/server-remapped/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch +++ b/patches/server/Fix-Non-Full-Status-Chunk-NBT-Memory-Leak.patch @@ -26,13 +26,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.ServerPlayer; + import net.minecraft.server.level.ThreadedLevelLightEngine; @@ -0,0 +0,0 @@ public class ChunkSerializer { object2 = protochunkticklist1; } -- object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, (chunk) -> { -- postLoadChunk(nbttagcompound1, chunk); +- object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, k, achunksection, (chunk) -> { +- ChunkSerializer.postLoadChunk(world, nbttagcompound1, chunk); - // CraftBukkit start - load chunk persistent data from nbt - net.minecraft.nbt.Tag persistentBase = nbttagcompound1.get("ChunkBukkitValues"); - if (persistentBase instanceof CompoundTag) { @@ -40,11 +40,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - } - // CraftBukkit end - }); -+ object = new LevelChunk(worldserver.getLevel(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. ++ object = new LevelChunk(world.getLevel(), pos, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, k, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys. + createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here + );// Paper end } else { - ProtoChunk protochunk = new ProtoChunk(chunkcoordintpair, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, worldserver); // Paper - Anti-Xray - Add parameter + ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level @@ -0,0 +0,0 @@ public class ChunkSerializer { return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading @@ -84,7 +84,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + private static java.util.function.Consumer createLoadEntitiesConsumer(CompoundTag nbt) { + return (chunk) -> { -+ postLoadChunk(nbt, chunk); ++ postLoadChunk(chunk.level, nbt, chunk); + // CraftBukkit start - load chunk persistent data from nbt + Tag persistentBase = nbt.get("ChunkBukkitValues"); + if (persistentBase instanceof CompoundTag) { diff --git a/patches/server-remapped/Fix-PotionEffect-ignores-icon-flag.patch b/patches/server/Fix-PotionEffect-ignores-icon-flag.patch similarity index 61% rename from patches/server-remapped/Fix-PotionEffect-ignores-icon-flag.patch rename to patches/server/Fix-PotionEffect-ignores-icon-flag.patch index c07434deb7..175faa193d 100644 --- a/patches/server-remapped/Fix-PotionEffect-ignores-icon-flag.patch +++ b/patches/server/Fix-PotionEffect-ignores-icon-flag.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean addPotionEffect(PotionEffect effect, boolean force) { -- getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); -+ getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon +- this.getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles()), EntityPotionEffectEvent.Cause.PLUGIN); ++ this.getHandle().addEffect(new MobEffectInstance(MobEffect.byId(effect.getType().getId()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()), EntityPotionEffectEvent.Cause.PLUGIN); // Paper - Don't ignore icon return true; } diff --git a/patches/server-remapped/Optimize-brigadier-child-sorting-performance.patch b/patches/server/Optimize-brigadier-child-sorting-performance.patch similarity index 80% rename from patches/server-remapped/Optimize-brigadier-child-sorting-performance.patch rename to patches/server/Optimize-brigadier-child-sorting-performance.patch index 3f1501ff9f..50600fdade 100644 --- a/patches/server-remapped/Optimize-brigadier-child-sorting-performance.patch +++ b/patches/server/Optimize-brigadier-child-sorting-performance.patch @@ -18,12 +18,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private Map> arguments = Maps.newLinkedHashMap(); private final Predicate requirement; @@ -0,0 +0,0 @@ public abstract class CommandNode implements Comparable> { - arguments.put(node.getName(), (ArgumentCommandNode) node); } } -- -- children = children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); -+ //Paper - Remove manual sorting, it is no longer needed + +- this.children = this.children.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); ++ // Paper - Remove manual sorting, it is no longer needed } public void findAmbiguities(final AmbiguityConsumer consumer) { diff --git a/patches/server-remapped/Potential-bed-API.patch b/patches/server/Potential-bed-API.patch similarity index 97% rename from patches/server-remapped/Potential-bed-API.patch rename to patches/server/Potential-bed-API.patch index 8cf03e3733..de10d553a1 100644 --- a/patches/server-remapped/Potential-bed-API.patch +++ b/patches/server/Potential-bed-API.patch @@ -20,7 +20,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.Entity; @@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { - return getHandle().sleepCounter; + return this.getHandle().sleepCounter; } + // Paper start - Potential bed api diff --git a/patches/server-remapped/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch similarity index 90% rename from patches/server-remapped/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch rename to patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch index 21f2e95edc..bf74192c3f 100644 --- a/patches/server-remapped/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -44,8 +44,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 BlockState iblockdata = this.level.getBlockState(blockposition); + if (!iblockdata.isDestroyable()) continue; // Paper FluidState fluid = iblockdata.getFluidState(); // Paper - Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); + if (!this.level.isInWorldBounds(blockposition)) { @@ -0,0 +0,0 @@ public class Explosion { BlockState iblockdata = this.level.getBlockState(blockposition); Block block = iblockdata.getBlock(); @@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + BlockState type = getBlockState(pos); + if (!type.isDestroyable()) return false; + // Paper end - CraftBlockState blockstate = capturedBlockStates.get(pos); + CraftBlockState blockstate = this.capturedBlockStates.get(pos); if (blockstate == null) { blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags); diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java @@ -115,8 +115,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 BlockState iblockdata1 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT); world.setBlock(pos, iblockdata1, 20); -- world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); -+ world.setBlockEntity(pos, MovingPistonBlock.newMovingBlockEntity((BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above +- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata1, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); ++ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata1, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - diff on change world.blockUpdated(pos, iblockdata1.getBlock()); iblockdata1.updateNeighbourShapes(world, pos, 2); if (this.isSticky) { @@ -144,8 +144,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Deprecated public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { -- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()); -+ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || context.getItemInHand().getItem() != this.asItem()) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().abilities.instabuild)); // Paper +- return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())); ++ return this.material.isReplaceable() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper } @Deprecated diff --git a/patches/server-remapped/Reduce-MutableInt-allocations-from-light-engine.patch b/patches/server/Reduce-MutableInt-allocations-from-light-engine.patch similarity index 69% rename from patches/server-remapped/Reduce-MutableInt-allocations-from-light-engine.patch rename to patches/server/Reduce-MutableInt-allocations-from-light-engine.patch index f837b63f46..c0103698e2 100644 --- a/patches/server-remapped/Reduce-MutableInt-allocations-from-light-engine.patch +++ b/patches/server/Reduce-MutableInt-allocations-from-light-engine.patch @@ -10,32 +10,32 @@ diff --git a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.j index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java +++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightEngine.java -@@ -0,0 +0,0 @@ public final class BlockLightEngine extends LayerLightEngine { private static final Direction[] DIRECTIONS = Direction.values(); private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); -+ private final MutableInt mutableint = new MutableInt(); // Paper ++ private final MutableInt mutableInt = new MutableInt(); // Paper public BlockLightEngine(LightChunkGetter chunkProvider) { super(chunkProvider, LightLayer.BLOCK, new BlockLightSectionStorage(chunkProvider)); @@ -0,0 +0,0 @@ public final class BlockLightEngine extends LayerLightEngine= 15) { + BlockState blockState = this.getStateAndOpacity(targetId, mutableInt); + if (mutableInt.getValue() >= 15) { + return 15; diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java +++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightEngine.java -@@ -0,0 +0,0 @@ public final class SkyLightEngine extends LayerLightEngine { private static final Direction[] DIRECTIONS = Direction.values(); private static final Direction[] HORIZONTALS = new Direction[]{Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST}; -+ private final MutableInt mutableint = new MutableInt(); // Paper ++ private final MutableInt mutableInt = new MutableInt(); // Paper public SkyLightEngine(LightChunkGetter chunkProvider) { super(chunkProvider, LightLayer.SKY, new SkyLightSectionStorage(chunkProvider)); @@ -43,8 +43,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (level >= 15) { return level; } else { -- MutableInt mutableint = new MutableInt(); +- MutableInt mutableInt = new MutableInt(); + //MutableInt mutableint = new MutableInt(); // Paper - share mutableint, single threaded - BlockState iblockdata = this.getStateAndOpacity(targetId, mutableint); - - if (mutableint.getValue() >= 15) { + BlockState blockState = this.getStateAndOpacity(targetId, mutableInt); + if (mutableInt.getValue() >= 15) { + return 15; diff --git a/patches/server-remapped/Reduce-allocation-of-Vec3D-by-entity-tracker.patch b/patches/server/Reduce-allocation-of-Vec3D-by-entity-tracker.patch similarity index 85% rename from patches/server-remapped/Reduce-allocation-of-Vec3D-by-entity-tracker.patch rename to patches/server/Reduce-allocation-of-Vec3D-by-entity-tracker.patch index 49d82d8667..e8d8a15032 100644 --- a/patches/server-remapped/Reduce-allocation-of-Vec3D-by-entity-tracker.patch +++ b/patches/server/Reduce-allocation-of-Vec3D-by-entity-tracker.patch @@ -8,14 +8,6 @@ diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/j index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.levelgen.structure.StructureStart; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; - import net.minecraft.world.level.storage.DimensionDataStorage; - import net.minecraft.world.level.storage.LevelStorageSource; --import net.minecraft.world.phys.Vec3; - import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper - import org.apache.commons.lang3.mutable.MutableBoolean; - import org.apache.logging.log4j.LogManager; @@ -0,0 +0,0 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially public void updatePlayer(ServerPlayer player) { org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot @@ -31,16 +23,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - boolean flag = vec3d.x >= (double) (-i) && vec3d.x <= (double) i && vec3d.z >= (double) (-i) && vec3d.z <= (double) i && this.entity.broadcastToPlayer(player); + boolean flag = vec3d_dx >= (double) (-i) && vec3d_dx <= (double) i && vec3d_dz >= (double) (-i) && vec3d_dz <= (double) i && this.entity.broadcastToPlayer(player); // Paper - remove allocation of Vec3D here - if (flag) { - boolean flag1 = this.entity.forcedLoading; + // CraftBukkit start - respect vanish API + if (this.entity instanceof ServerPlayer) { diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java @@ -0,0 +0,0 @@ public class ServerEntity { ++this.teleportDelay; - i = Mth.floor(this.entity.yRot * 256.0F / 360.0F); - j = Mth.floor(this.entity.xRot * 256.0F / 360.0F); + i = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); + j = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); - Vec3 vec3d = this.entity.position().subtract(ClientboundMoveEntityPacket.packetToEntity(this.xp, this.yp, this.zp)); - boolean flag1 = vec3d.lengthSqr() >= 7.62939453125E-6D; + // Paper start - reduce allocation of Vec3D here diff --git a/patches/server-remapped/Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/Wait-for-Async-Tasks-during-shutdown.patch similarity index 100% rename from patches/server-remapped/Wait-for-Async-Tasks-during-shutdown.patch rename to patches/server/Wait-for-Async-Tasks-during-shutdown.patch