From c42850dbcc0497afe7be7b2cca9fe421ad6e098e Mon Sep 17 00:00:00 2001 From: Nassim Jahnke <nassim@njahnke.dev> Date: Thu, 25 Apr 2024 13:02:27 +0200 Subject: [PATCH] More patches --- ...culate-regionfile-header-if-it-is-co.patch | 60 ++++++++------- ...lementation-for-blockstate-state-loo.patch | 6 +- .../Eigencraft-redstone-implementation.patch | 4 +- .../server/Execute-chunk-tasks-mid-tick.patch | 0 patches/server/Fix-DamageSource-API.patch | 2 +- .../Improve-boat-collision-performance.patch | 0 .../server/Improved-Watchdog-Support.patch | 12 +-- .../server/Optimise-general-POI-access.patch | 0 .../Optimise-random-block-ticking.patch | 6 +- .../Optimize-Bit-Operations-by-inlining.patch | 2 +- ...der-Remove-Streams-Optimized-collect.patch | 6 +- .../server/Optimize-Voxel-Shape-Merging.patch | 0 ...and-End-Portal-Frames-from-being-des.patch | 16 ++-- .../server/Remove-streams-from-hot-code.patch | 0 ...tance-map-to-optimise-entity-tracker.patch | 4 +- .../server/Write-SavedData-IO-async.patch | 77 ++++++++----------- 16 files changed, 90 insertions(+), 105 deletions(-) rename patches/{unapplied => }/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch (93%) rename patches/{unapplied => }/server/Custom-table-implementation-for-blockstate-state-loo.patch (98%) rename patches/{unapplied => }/server/Eigencraft-redstone-implementation.patch (99%) rename patches/{unapplied => }/server/Execute-chunk-tasks-mid-tick.patch (100%) rename patches/{unapplied => }/server/Improve-boat-collision-performance.patch (100%) rename patches/{unapplied => }/server/Improved-Watchdog-Support.patch (98%) rename patches/{unapplied => }/server/Optimise-general-POI-access.patch (100%) rename patches/{unapplied => }/server/Optimise-random-block-ticking.patch (99%) rename patches/{unapplied => }/server/Optimize-Bit-Operations-by-inlining.patch (99%) rename patches/{unapplied => }/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch (96%) rename patches/{unapplied => }/server/Optimize-Voxel-Shape-Merging.patch (100%) rename patches/{unapplied => }/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch (96%) rename patches/{unapplied => }/server/Remove-streams-from-hot-code.patch (100%) rename patches/{unapplied => }/server/Use-distance-map-to-optimise-entity-tracker.patch (98%) rename patches/{unapplied => }/server/Write-SavedData-IO-async.patch (74%) diff --git a/patches/unapplied/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch similarity index 93% rename from patches/unapplied/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch rename to patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch index a188298a88..4cf82ff216 100644 --- a/patches/unapplied/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch +++ b/patches/server/Attempt-to-recalculate-regionfile-header-if-it-is-co.patch @@ -47,10 +47,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java @@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { - public ChunkStorage(Path directory, DataFixer dataFixer, boolean dsync) { + public ChunkStorage(RegionStorageInfo storageKey, Path directory, DataFixer dataFixer, boolean dsync) { this.fixerUpper = dataFixer; -- this.regionFileCache = new RegionFileStorage(directory, dsync); // Paper - rewrite chunk system; async chunk IO -+ this.regionFileCache = new RegionFileStorage(directory, dsync, true); // Paper - rewrite chunk system; async chunk IO & Attempt to recalculate regionfile header if it is corrupt +- this.regionFileCache = new RegionFileStorage(storageKey, directory, dsync); // Paper - rewrite chunk system; async chunk IO ++ this.regionFileCache = new RegionFileStorage(storageKey, directory, dsync, true); // Paper - rewrite chunk system; async chunk IO & Attempt to recalculate regionfile header if it is corrupt } public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) { @@ -91,9 +91,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + protected final RegionBitmap usedSectors; public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(); // Paper public final Path regionFile; // Paper - ++ + // Paper start - Attempt to recalculate regionfile header if it is corrupt + private static long roundToSectors(long bytes) { + long sectors = bytes >>> 12; // 4096 = 2^12 @@ -447,31 +448,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final net.minecraft.world.level.chunk.ChunkStatus[] statuses = new net.minecraft.world.level.chunk.ChunkStatus[32 * 32]; @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - public RegionFile(Path file, Path directory, boolean dsync) throws IOException { - this(file, directory, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format + public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException { + this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format } + // Paper start - add can recalc flag -+ public RegionFile(Path file, Path directory, boolean dsync, boolean canRecalcHeader) throws IOException { -+ this(file, directory, RegionFileVersion.getCompressionFormat(), dsync, canRecalcHeader); ++ public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync, boolean canRecalcHeader) throws IOException { ++ this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync, canRecalcHeader); + } -+ // Paper end - add can recalc flag - public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync) throws IOException { -+ // Paper start - add can recalc flag -+ this(file, directory, outputChunkStreamVersion, dsync, false); + public RegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync) throws IOException { ++ this(storageKey, path, directory, compressionFormat, dsync, true); + } -+ public RegionFile(Path file, Path directory, RegionFileVersion outputChunkStreamVersion, boolean dsync, boolean canRecalcHeader) throws IOException { ++ ++ public RegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync, boolean canRecalcHeader) throws IOException { + this.canRecalcHeader = canRecalcHeader; + // Paper end - add can recalc flag this.header = ByteBuffer.allocateDirect(8192); this.regionFile = file; // Paper initOversizedState(); // Paper @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - RegionFile.LOGGER.warn("Region file {} has truncated header: {}", file, i); + RegionFile.LOGGER.warn("Region file {} has truncated header: {}", path, i); } -- long j = Files.size(file); -+ final long j = Files.size(file); final long regionFileSize = j; // Paper - recalculate header on header corruption +- long j = Files.size(path); ++ final long j = Files.size(path); final long regionFileSize = j; // Paper - recalculate header on header corruption - for (int k = 0; k < 1024; ++k) { - int l = this.offsets.get(k); @@ -495,15 +495,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + sectorLength = j1; // Paper - diff on change, we expect this to be sector length of region if (i1 < 2) { - RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{file, k, i1}); + RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{path, k, i1}); - this.offsets.put(k, 0); + //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change } else if (j1 == 0) { - RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", file, k); + RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; size has to be > 0", path, k); - this.offsets.put(k, 0); + //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change } else if ((long) i1 * 4096L > j) { - RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{file, k, i1}); + RegionFile.LOGGER.warn("Region file {} has an invalid sector at index: {}; sector {} is out of bounds", new Object[]{path, k, i1}); - this.offsets.put(k, 0); + //this.offsets.put(k, 0); // Paper - we catch this, but need it in the header for the summary change } else { @@ -559,6 +559,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { } private Path getExternalChunkPath(ChunkPos chunkPos) { @@ -656,6 +657,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - recalculate header on regionfile corruption return null; } else { + JvmProfiler.INSTANCE.onRegionFileRead(this.info, pos, this.version, j1); - return this.createChunkInputStream(pos, b0, RegionFile.createStream(bytebuffer, j1)); + // Paper start - recalculate header on regionfile corruption + final DataInputStream ret = this.createChunkInputStream(pos, b0, RegionFile.createStream(bytebuffer, j1)); @@ -689,7 +691,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { - public final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap(); + private final RegionStorageInfo info; private final Path folder; private final boolean sync; + private final boolean isChunkData; // Paper @@ -699,16 +701,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { // Paper end - cache regionfile does not exist state - protected RegionFileStorage(Path directory, boolean dsync) { // Paper - protected constructor + protected RegionFileStorage(RegionStorageInfo storageKey, Path directory, boolean dsync) { // Paper - protected constructor + // Paper start - add isChunkData param -+ this(directory, dsync, false); ++ this(storageKey, directory, dsync, false); + } -+ RegionFileStorage(Path directory, boolean dsync, boolean isChunkData) { ++ RegionFileStorage(RegionStorageInfo storageKey, Path directory, boolean dsync, boolean isChunkData) { + this.isChunkData = isChunkData; + // Paper end - add isChunkData param this.folder = directory; this.sync = dsync; - } + this.info = storageKey; @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { // Paper - only create directory if not existing only - moved down Path path = this.folder; @@ -722,8 +724,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // Paper end - cache regionfile does not exist state FileUtil.createDirectoriesSafe(this.folder); // Paper - only create directory if not existing only - moved from above -- RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync); -+ RegionFile regionfile1 = new RegionFile(path1, this.folder, this.sync, this.isChunkData); // Paper - allow for chunk regionfiles to regen header +- RegionFile regionfile1 = new RegionFile(this.info, path1, this.folder, this.sync); ++ RegionFile regionfile1 = new RegionFile(this.info, path1, this.folder, this.sync, this.isChunkData); // Paper - allow for chunk regionfiles to regen header this.regionCache.putAndMoveToFirst(i, regionfile1); // Paper start @@ -766,12 +768,12 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVer index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java -@@ -0,0 +0,0 @@ import javax.annotation.Nullable; - import net.minecraft.util.FastBufferedInputStream; +@@ -0,0 +0,0 @@ import org.slf4j.Logger; public class RegionFileVersion { + private static final Logger LOGGER = LogUtils.getLogger(); - private static final Int2ObjectMap<RegionFileVersion> VERSIONS = new Int2ObjectOpenHashMap<>(); + public static final Int2ObjectMap<RegionFileVersion> VERSIONS = new Int2ObjectOpenHashMap<>(); // Paper - private -> public + private static final Object2ObjectMap<String, RegionFileVersion> VERSIONS_BY_NAME = new Object2ObjectOpenHashMap<>(); public static final RegionFileVersion VERSION_GZIP = register( new RegionFileVersion( - 1, stream -> new FastBufferedInputStream(new GZIPInputStream(stream)), stream -> new BufferedOutputStream(new GZIPOutputStream(stream)) diff --git a/patches/unapplied/server/Custom-table-implementation-for-blockstate-state-loo.patch b/patches/server/Custom-table-implementation-for-blockstate-state-loo.patch similarity index 98% rename from patches/unapplied/server/Custom-table-implementation-for-blockstate-state-loo.patch rename to patches/server/Custom-table-implementation-for-blockstate-state-loo.patch index 4adbbb6ff4..cfe59c2249 100644 --- a/patches/unapplied/server/Custom-table-implementation-for-blockstate-state-loo.patch +++ b/patches/server/Custom-table-implementation-for-blockstate-state-loo.patch @@ -177,14 +177,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java +++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java @@ -0,0 +0,0 @@ public abstract class StateHolder<O, S> { - private final ImmutableMap<Property<?>, Comparable<?>> values; + private final Reference2ObjectArrayMap<Property<?>, Comparable<?>> values; private Table<Property<?>, Comparable<?>, S> neighbours; protected final MapCodec<S> propertiesCodec; + protected final io.papermc.paper.util.table.ZeroCollidingReferenceStateTable optimisedTable; // Paper - optimise state lookup - protected StateHolder(O owner, ImmutableMap<Property<?>, Comparable<?>> entries, MapCodec<S> codec) { + protected StateHolder(O owner, Reference2ObjectArrayMap<Property<?>, Comparable<?>> propertyMap, MapCodec<S> codec) { this.owner = owner; - this.values = entries; + this.values = propertyMap; this.propertiesCodec = codec; + this.optimisedTable = new io.papermc.paper.util.table.ZeroCollidingReferenceStateTable(this, entries); // Paper - optimise state lookup } diff --git a/patches/unapplied/server/Eigencraft-redstone-implementation.patch b/patches/server/Eigencraft-redstone-implementation.patch similarity index 99% rename from patches/unapplied/server/Eigencraft-redstone-implementation.patch rename to patches/server/Eigencraft-redstone-implementation.patch index d5aa9977a1..2551e39666 100644 --- a/patches/unapplied/server/Eigencraft-redstone-implementation.patch +++ b/patches/server/Eigencraft-redstone-implementation.patch @@ -1117,7 +1117,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @@ -0,0 +0,0 @@ public class RedStoneWireBlock extends Block { @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { if (!oldState.is(state.getBlock()) && !world.isClientSide) { - this.updatePowerStrength(world, pos, state); + this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone @@ -1134,7 +1134,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } @@ -0,0 +0,0 @@ public class RedStoneWireBlock extends Block { - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { + protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { if (!world.isClientSide) { if (state.canSurvive(world, pos)) { - this.updatePowerStrength(world, pos, state); diff --git a/patches/unapplied/server/Execute-chunk-tasks-mid-tick.patch b/patches/server/Execute-chunk-tasks-mid-tick.patch similarity index 100% rename from patches/unapplied/server/Execute-chunk-tasks-mid-tick.patch rename to patches/server/Execute-chunk-tasks-mid-tick.patch diff --git a/patches/server/Fix-DamageSource-API.patch b/patches/server/Fix-DamageSource-API.patch index e9040be07a..eb4d63f59a 100644 --- a/patches/server/Fix-DamageSource-API.patch +++ b/patches/server/Fix-DamageSource-API.patch @@ -95,7 +95,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit end this.dead = true; - this.level().explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customCausingEntity(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit -+ this.level().explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customEventDamager(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit ++ this.level().explode(this, net.minecraft.world.level.Explosion.getDefaultDamageSource(this.level(), this).customEventDamager(this.entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); // CraftBukkit // Paper - fix DamageSource API this.discard(EntityRemoveEvent.Cause.EXPLODE); // CraftBukkit - add Bukkit remove cause this.spawnLingeringCloud(); // CraftBukkit start diff --git a/patches/unapplied/server/Improve-boat-collision-performance.patch b/patches/server/Improve-boat-collision-performance.patch similarity index 100% rename from patches/unapplied/server/Improve-boat-collision-performance.patch rename to patches/server/Improve-boat-collision-performance.patch diff --git a/patches/unapplied/server/Improved-Watchdog-Support.patch b/patches/server/Improved-Watchdog-Support.patch similarity index 98% rename from patches/unapplied/server/Improved-Watchdog-Support.patch rename to patches/server/Improved-Watchdog-Support.patch index 64e2efee46..06655df6d1 100644 --- a/patches/unapplied/server/Improved-Watchdog-Support.patch +++ b/patches/server/Improved-Watchdog-Support.patch @@ -218,14 +218,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa this.worldData.setDataConfiguration(worlddataconfiguration); - this.resources.managers.updateRegistryTags(this.registryAccess()); - net.minecraft.world.item.alchemy.PotionBrewing.reload(); // Paper - Custom Potion Mixes + this.resources.managers.updateRegistryTags(); + this.potionBrewing.reload(this.worldData.enabledFeatures()); // Paper - Custom Potion Mixes - this.getPlayerList().saveAll(); + // Paper start + if (Thread.currentThread() != this.serverThread) { + return; + } -+ // this.getPlayerList().saveAll(); // Paper - we don't need to save everything, just advancements ++ // this.getPlayerList().saveAll(); // Paper - we don't need to save everything, just advancements // TODO Move this to a different patch + for (ServerPlayer player : this.getPlayerList().getPlayers()) { + player.getAdvancements().save(); + } @@ -537,8 +537,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/resources/log4j2.xml @@ -0,0 +0,0 @@ <?xml version="1.0" encoding="UTF-8"?> --<Configuration status="WARN" packages="com.mojang.util"> -+<Configuration status="WARN" packages="com.mojang.util" shutdownHook="disable"> +-<Configuration status="WARN"> ++<Configuration status="WARN" shutdownHook="disable"> <Appenders> <Queue name="ServerGuiConsole"> - <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" /> + <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg{nolookups}%n" /> diff --git a/patches/unapplied/server/Optimise-general-POI-access.patch b/patches/server/Optimise-general-POI-access.patch similarity index 100% rename from patches/unapplied/server/Optimise-general-POI-access.patch rename to patches/server/Optimise-general-POI-access.patch diff --git a/patches/unapplied/server/Optimise-random-block-ticking.patch b/patches/server/Optimise-random-block-ticking.patch similarity index 99% rename from patches/unapplied/server/Optimise-random-block-ticking.patch rename to patches/server/Optimise-random-block-ticking.patch index 8a6f9859ce..4be93dc764 100644 --- a/patches/unapplied/server/Optimise-random-block-ticking.patch +++ b/patches/server/Optimise-random-block-ticking.patch @@ -389,7 +389,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - public int tickingBlockCount; - public int tickingFluidCount; - -- a() {} +- a(final LevelChunkSection chunksection) {} - - public void accept(BlockState iblockdata, int i) { + // Paper start - unfuck this @@ -425,13 +425,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); } - -- a a0 = new a(); +- a a0 = new a(this); - - this.states.count(a0); - this.nonEmptyBlockCount = (short) a0.nonEmptyBlockCount; - this.tickingBlockCount = (short) a0.tickingBlockCount; - this.tickingFluidCount = (short) a0.tickingFluidCount; -+ // Paper end ++ // Paper end - unfuck this } public PalettedContainer<BlockState> getStates() { diff --git a/patches/unapplied/server/Optimize-Bit-Operations-by-inlining.patch b/patches/server/Optimize-Bit-Operations-by-inlining.patch similarity index 99% rename from patches/unapplied/server/Optimize-Bit-Operations-by-inlining.patch rename to patches/server/Optimize-Bit-Operations-by-inlining.patch index f1e502a1c2..9e77b0a62c 100644 --- a/patches/unapplied/server/Optimize-Bit-Operations-by-inlining.patch +++ b/patches/server/Optimize-Bit-Operations-by-inlining.patch @@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/core/BlockPos.java +++ b/src/main/java/net/minecraft/core/BlockPos.java @@ -0,0 +0,0 @@ public class BlockPos extends Vec3i { - .stable(); + }; private static final Logger LOGGER = LogUtils.getLogger(); public static final BlockPos ZERO = new BlockPos(0, 0, 0); - private static final int PACKED_X_LENGTH = 1 + Mth.log2(Mth.smallestEncompassingPowerOfTwo(30000000)); diff --git a/patches/unapplied/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/patches/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch similarity index 96% rename from patches/unapplied/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch rename to patches/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch index 91b5b9344b..e0d4f9a991 100644 --- a/patches/unapplied/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ b/patches/server/Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -24,11 +24,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return null; } else { - Map<Target, BlockPos> map = positions.stream() -- .collect(Collectors.toMap(pos -> this.nodeEvaluator.getGoal((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()), Function.identity())); +- .collect(Collectors.toMap(pos -> this.nodeEvaluator.getTarget((double)pos.getX(), (double)pos.getY(), (double)pos.getZ()), Function.identity())); + // Paper start - Perf: remove streams and optimize collection + List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList(); -+ for (BlockPos pos : positions) { -+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), pos)); ++ for (final BlockPos pos : positions) { ++ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), pos)); + } + // Paper end - Perf: remove streams and optimize collection Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier); diff --git a/patches/unapplied/server/Optimize-Voxel-Shape-Merging.patch b/patches/server/Optimize-Voxel-Shape-Merging.patch similarity index 100% rename from patches/unapplied/server/Optimize-Voxel-Shape-Merging.patch rename to patches/server/Optimize-Voxel-Shape-Merging.patch diff --git a/patches/unapplied/server/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 96% rename from patches/unapplied/server/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 1ec6f838b0..8bb502418a 100644 --- a/patches/unapplied/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -69,7 +69,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java @@ -0,0 +0,0 @@ public class PistonBaseBlock extends DirectionalBlock { @Override - public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { + protected boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) { Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING); + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; prevent retracting when we're facing the wrong way (we were replaced before retraction could occur) + Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below @@ -110,23 +110,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java @@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement { - /** @deprecated */ - @Deprecated - public void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) { + } + + protected void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) { - if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) { + if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK && state.isDestroyable()) { // Paper - Protect Bedrock and End Portal/Frames from being destroyed Block block = state.getBlock(); boolean flag = explosion.getIndirectSourceEntity() instanceof Player; @@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement { - /** @deprecated */ - @Deprecated - public boolean canBeReplaced(BlockState state, BlockPlaceContext context) { + } + + protected boolean canBeReplaced(BlockState state, BlockPlaceContext context) { - return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())); + return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed } - /** @deprecated */ + protected boolean canBeReplaced(BlockState state, Fluid fluid) { @@ -0,0 +0,0 @@ public abstract class BlockBehaviour implements FeatureElement { return this.legacySolid; } diff --git a/patches/unapplied/server/Remove-streams-from-hot-code.patch b/patches/server/Remove-streams-from-hot-code.patch similarity index 100% rename from patches/unapplied/server/Remove-streams-from-hot-code.patch rename to patches/server/Remove-streams-from-hot-code.patch diff --git a/patches/unapplied/server/Use-distance-map-to-optimise-entity-tracker.patch b/patches/server/Use-distance-map-to-optimise-entity-tracker.patch similarity index 98% rename from patches/unapplied/server/Use-distance-map-to-optimise-entity-tracker.patch rename to patches/server/Use-distance-map-to-optimise-entity-tracker.patch index 51b3f5f6be..ac9eea090a 100644 --- a/patches/unapplied/server/Use-distance-map-to-optimise-entity-tracker.patch +++ b/patches/server/Use-distance-map-to-optimise-entity-tracker.patch @@ -239,7 +239,7 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import net.minecraft.network.syncher.EntityDataSerializers; +@@ -0,0 +0,0 @@ import net.minecraft.network.syncher.SyncedDataHolder; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -247,7 +247,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.teleportTo(worldserver, null); } // Paper end - make end portalling safe diff --git a/patches/unapplied/server/Write-SavedData-IO-async.patch b/patches/server/Write-SavedData-IO-async.patch similarity index 74% rename from patches/unapplied/server/Write-SavedData-IO-async.patch rename to patches/server/Write-SavedData-IO-async.patch index 3bd690831d..cde49336c4 100644 --- a/patches/unapplied/server/Write-SavedData-IO-async.patch +++ b/patches/server/Write-SavedData-IO-async.patch @@ -5,26 +5,6 @@ Subject: [PATCH] Write SavedData IO async Co-Authored-By: Shane Freeder <theboyetronic@gmail.com> -diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -+++ b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java -@@ -0,0 +0,0 @@ public class ThreadedWorldUpgrader { - } - - this.threadPool.execute(new ConvertTask(info, regionPos.x >> 5, regionPos.z >> 5)); -+ // Paper start - Write SavedData IO async -+ this.threadPool.execute(() -> { -+ try { -+ worldPersistentData.close(); -+ } catch (IOException exception) { -+ LOGGER.error("Failed to close persistent world data", exception); -+ } -+ }); -+ // Paper end - Write SavedData IO async - } - this.threadPool.shutdown(); - diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -85,20 +65,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java +++ b/src/main/java/net/minecraft/util/worldupdate/WorldUpgrader.java @@ -0,0 +0,0 @@ public class WorldUpgrader { - } - } - -- this.overworldDataStorage.save(); -+ // Paper start - Write SavedData IO async -+ try { -+ this.overworldDataStorage.close(); -+ } catch (IOException exception) { -+ LOGGER.error("Failed to close persistent world data", exception); -+ } -+ // Paper end - Write SavedData IO async - i = Util.getMillis() - i; - WorldUpgrader.LOGGER.info("World optimizaton finished after {} ms", i); - this.finished = true; + (new WorldUpgrader.PoiUpgrader(this)).upgrade(); + WorldUpgrader.LOGGER.info("Upgrading blocks"); + (new WorldUpgrader.ChunkUpgrader()).upgrade(); +- this.overworldDataStorage.save(); ++ // Paper start - Write SavedData IO async ++ try { ++ this.overworldDataStorage.close(); ++ } catch (final IOException e) { ++ LOGGER.error("Failed to close persistent world data", e); ++ } ++ // Paper end - Write SavedData IO async + i = Util.getMillis() - i; + WorldUpgrader.LOGGER.info("World optimizaton finished after {} seconds", i / 1000L); + this.finished = true; diff --git a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java @@ -107,22 +87,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.dirty; } -+ @io.papermc.paper.annotation.DoNotUse // Paper - Write SavedData IO async - This is dead - public void save(File file) { -+ save(file, null).join(); // Paper - Write SavedData IO async - joining is evil, but we assume the old blocking behavior here just for safety ++ // Paper start - Write SavedData IO async - joining is evil, but we assume the old blocking behavior here just for safety ++ @io.papermc.paper.annotation.DoNotUse + public void save(File file, HolderLookup.Provider registryLookup) { ++ save(file, registryLookup, null).join(); + } + -+ public java.util.concurrent.CompletableFuture<Void> save(File file, @org.jetbrains.annotations.Nullable java.util.concurrent.ExecutorService ioExecutor) { // Paper - Write SavedData IO async ++ public java.util.concurrent.CompletableFuture<Void> save(File file, HolderLookup.Provider registryLookup, @org.jetbrains.annotations.Nullable java.util.concurrent.ExecutorService ioExecutor) { ++ // Paper end - Write SavedData IO async if (this.isDirty()) { CompoundTag compoundTag = new CompoundTag(); - compoundTag.put("data", this.save(new CompoundTag())); + compoundTag.put("data", this.save(new CompoundTag(), registryLookup)); NbtUtils.addCurrentDataVersion(compoundTag); + Runnable writeRunnable = () -> { // Paper - Write SavedData IO async try { NbtIo.writeCompressed(compoundTag, file.toPath()); - } catch (IOException var4) { - LOGGER.error("Could not save data {}", this, var4); + } catch (IOException var5) { + LOGGER.error("Could not save data {}", this, var5); } + }; // Paper - Write SavedData IO async @@ -137,7 +119,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - Write SavedData IO async } - public static record Factory<T extends SavedData>(Supplier<T> constructor, Function<CompoundTag, T> deserializer, DataFixTypes type) { + public static record Factory<T extends SavedData>( diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java @@ -151,14 +133,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private static final Logger LOGGER = LogUtils.getLogger(); public final Map<String, SavedData> cache = Maps.newHashMap(); private final DataFixer fixerUpper; + private final HolderLookup.Provider registries; private final File dataFolder; + protected final java.util.concurrent.ExecutorService ioExecutor; // Paper - Write SavedData IO async - public DimensionDataStorage(File directory, DataFixer dataFixer) { + public DimensionDataStorage(File directory, DataFixer dataFixer, HolderLookup.Provider registryLookup) { this.fixerUpper = dataFixer; this.dataFolder = directory; -+ String worldFolder = dataFolder.getParent(); // Paper - Write SavedData IO async -+ this.ioExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("DimensionDataIO - " + worldFolder + " - %d").setDaemon(true).build()); // Paper - Write SavedData IO async + this.registries = registryLookup; ++ this.ioExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("DimensionDataIO - " + dataFolder.getParent() + " - %d").setDaemon(true).build()); // Paper - Write SavedData IO async } private File getDataFile(String id) { @@ -178,9 +161,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public void save(boolean async) { // Paper - Write SavedData IO async this.cache.forEach((id, state) -> { if (state != null) { -- state.save(this.getDataFile(id)); +- state.save(this.getDataFile(id), this.registries); + // Paper start - Write SavedData IO async -+ final java.util.concurrent.CompletableFuture<Void> save = state.save(this.getDataFile(id), ioExecutor); ++ final java.util.concurrent.CompletableFuture<Void> save = state.save(this.getDataFile(id), this.registries, this.ioExecutor); + if (!async) { + save.join(); + }