mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 03:48:01 +01:00
More more more more more more more work
This commit is contained in:
parent
82f6e6bb0e
commit
c36c2d46d3
@ -72,12 +72,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world);
|
||||
Phantom entityphantom = (Phantom) EntityType.PHANTOM.create(world);
|
||||
-
|
||||
+ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper
|
||||
entityphantom.moveTo(blockposition1, 0.0F, 0.0F);
|
||||
groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null);
|
||||
world.addAllEntities(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
|
||||
world.addFreshEntityWithPassengers(entityphantom, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java
|
@ -23,9 +23,9 @@ diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/sr
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
import net.minecraft.world.level.material.FlowingFluid;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
+import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType;
|
||||
@ -35,8 +35,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@Override
|
||||
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
if (this.shouldSpreadLiquid(world, pos, state)) {
|
||||
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world));
|
||||
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
|
||||
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
|
||||
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
@ -64,8 +64,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
|
||||
if (this.shouldSpreadLiquid(world, pos, state)) {
|
||||
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world));
|
||||
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
|
||||
- world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
|
||||
+ world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
|
||||
}
|
||||
|
||||
}
|
@ -14,11 +14,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
log("Creeper lingering effect: " + disableCreeperLingeringEffect);
|
||||
}
|
||||
+
|
||||
+ public double squidMaxSpawnHeight;
|
||||
+ private void squidMaxSpawnHeight() {
|
||||
+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D);
|
||||
+ }
|
||||
+
|
||||
+ public boolean disableSprintInterruptionOnAttack;
|
||||
+ private void disableSprintInterruptionOnAttack() {
|
||||
+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false);
|
||||
|
39
patches/server/Optimize-MappedRegistry.patch
Normal file
39
patches/server/Optimize-MappedRegistry.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 26 Aug 2018 20:49:50 -0400
|
||||
Subject: [PATCH] Optimize MappedRegistry
|
||||
|
||||
Use larger initial sizes to increase bucket capacity on the BiMap
|
||||
|
||||
BiMap.get was seen to be using a good bit of CPU time.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
+++ b/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
@@ -0,0 +0,0 @@ public class MappedRegistry<T> extends WritableRegistry<T> {
|
||||
|
||||
protected static final Logger LOGGER = LogManager.getLogger();
|
||||
private final ObjectList<T> byId = new ObjectArrayList(256);
|
||||
- private final Object2IntMap<T> toId = (Object2IntMap) Util.make(new Object2IntOpenCustomHashMap(Util.identityStrategy()), (object2intopencustomhashmap) -> {
|
||||
- object2intopencustomhashmap.defaultReturnValue(-1);
|
||||
- });
|
||||
- private final BiMap<ResourceLocation, T> storage = HashBiMap.create();
|
||||
- private final BiMap<ResourceKey<T>, T> keyStorage = HashBiMap.create();
|
||||
- private final Map<T, Lifecycle> lifecycles = Maps.newIdentityHashMap();
|
||||
+ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T> toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T>(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map
|
||||
+ private final BiMap<ResourceLocation, T> storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
|
||||
+ private final BiMap<ResourceKey<T>, T> keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
|
||||
+ private final Map<T, Lifecycle> lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions
|
||||
private Lifecycle elementsLifecycle;
|
||||
@Nullable
|
||||
protected Object[] randomCache;
|
||||
@@ -0,0 +0,0 @@ public class MappedRegistry<T> extends WritableRegistry<T> {
|
||||
|
||||
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
|
||||
super(key, lifecycle);
|
||||
- this.elementsLifecycle = lifecycle;
|
||||
+ this.toId.defaultReturnValue(-1); // Paper
|
||||
}
|
||||
|
||||
public static <T> MapCodec<MappedRegistry.RegistryEntry<T>> withNameAndId(ResourceKey<? extends Registry<T>> key, MapCodec<T> entryCodec) {
|
@ -85,7 +85,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy {
|
||||
this.slime.lookAt((Entity) this.slime.getTarget(), 10.0F, 10.0F);
|
||||
|
||||
((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.getYRot(), this.slime.isDealsDamage());
|
||||
}
|
||||
+
|
||||
@ -107,12 +107,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy {
|
||||
if (--this.nextRandomizeTime <= 0) {
|
||||
this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60);
|
||||
- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
|
||||
this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
|
||||
this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
|
||||
+ // Paper start
|
||||
+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), (float) this.slime.getRandom().nextInt(360));
|
||||
+ SlimeChangeDirectionEvent event = new SlimeChangeDirectionEvent((org.bukkit.entity.Slime) this.slime.getBukkitEntity(), this.chosenDegrees);
|
||||
+ if (!this.slime.canWander || !event.callEvent()) return;
|
||||
+ this.chosenDegrees = event.getNewYaw();
|
||||
+ // Paper end
|
@ -3,6 +3,9 @@ From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sat, 13 Jul 2019 09:23:10 -0700
|
||||
Subject: [PATCH] Asynchronous chunk IO and loading
|
||||
|
||||
# UPDATE NOTES: RegionFileStorage and SectionStorage need resolving (will conflict on apply)
|
||||
# ChunkSerializer needs the new tick lists to be saved (see added todos)
|
||||
|
||||
This patch re-adds a file IO thread as well as shoving de-serializing
|
||||
chunk NBT data onto worker threads. This patch also will shove
|
||||
chunk data serialization onto the same worker threads when the chunk
|
||||
@ -2282,8 +2285,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@@ -0,0 +0,0 @@ public final class MCUtil {
|
||||
return null;
|
||||
}
|
||||
public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
|
||||
return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status);
|
||||
}
|
||||
+
|
||||
+ public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
|
||||
@ -2296,7 +2299,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+++ b/src/main/java/net/minecraft/server/Main.java
|
||||
@@ -0,0 +0,0 @@ public class Main {
|
||||
|
||||
convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object);
|
||||
convertable_conversionsession.saveDataTag(iregistrycustom_dimension, (SaveData) object);
|
||||
*/
|
||||
+ Class.forName(net.minecraft.world.entity.npc.VillagerTrades.class.getName());// Paper - load this sync so it won't fail later async
|
||||
final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> {
|
||||
@ -2364,18 +2367,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
return true;
|
||||
});
|
||||
- this.flushWorker();
|
||||
+ //this.flushWorker(); // Paper - nuke IOWorker
|
||||
+ this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
|
||||
+// this.i(); // Paper - nuke IOWorker
|
||||
} else {
|
||||
this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> {
|
||||
ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
}
|
||||
|
||||
- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot
|
||||
+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more
|
||||
|
||||
protected void tick(BooleanSupplier shouldKeepTicking) {
|
||||
ProfilerFiller gameprofilerfiller = this.level.getProfiler();
|
||||
|
||||
@ -2387,10 +2384,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
if (!this.level.noSave()) {
|
||||
+ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper
|
||||
this.processUnloads(shouldKeepTicking);
|
||||
+ }// Paper
|
||||
+ } // Paper
|
||||
}
|
||||
|
||||
gameprofilerfiller.pop();
|
||||
}
|
||||
|
||||
- private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot
|
||||
+ private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.90; // Spigot // Paper - unload more
|
||||
|
||||
private void processUnloads(BooleanSupplier shouldKeepTicking) {
|
||||
LongIterator longiterator = this.toDrop.iterator();
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
if (playerchunk != null) {
|
||||
this.pendingUnloads.put(j, playerchunk);
|
||||
@ -2402,7 +2406,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
// Spigot end
|
||||
- this.scheduleUnload(j, playerchunk);
|
||||
+ //this.a(j, playerchunk); // Paper - move up because spigot did a dumb
|
||||
+ //this.scheduleUnload(j, playerchunk); // Paper - move up because spigot did a dumb
|
||||
}
|
||||
}
|
||||
activityAccountant.endActivity(); // Spigot
|
||||
@ -2418,7 +2422,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ ChunkPos chunkPos = chunk.getPos();
|
||||
+ CompoundTag poiData;
|
||||
+ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) {
|
||||
+ poiData = this.getVillagePlace().getData(chunk.getPos());
|
||||
+ poiData = this.poiManager.getData(chunk.getPos());
|
||||
+ }
|
||||
+
|
||||
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkPos.x, chunkPos.z,
|
||||
@ -2467,7 +2471,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex);
|
||||
+ this.save(ichunkaccess);
|
||||
+ }
|
||||
+ // Paper end - async chunk saving
|
||||
+ // Paper end - async chunk savin
|
||||
if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) {
|
||||
LevelChunk chunk = (LevelChunk) ichunkaccess;
|
||||
|
||||
@ -2484,30 +2488,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
- try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings
|
||||
- nbttagcompound = this.readChunk(pos);
|
||||
- } // Paper end
|
||||
-
|
||||
- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings
|
||||
- boolean flag = nbttagcompound.contains("Status", 8);
|
||||
-
|
||||
- if (flag) {
|
||||
- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.poiManager, pos, nbttagcompound);
|
||||
+ // Paper start
|
||||
+ if (ioThrowable != null) {
|
||||
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable);
|
||||
+ }
|
||||
|
||||
- if (nbttagcompound != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings
|
||||
- boolean flag = nbttagcompound.contains("Level", 10) && nbttagcompound.getCompound("Level").contains("Status", 8);
|
||||
+ this.getVillagePlace().loadInData(pos, chunkHolder.poiData);
|
||||
+ this.poiManager.loadInData(pos, chunkHolder.poiData);
|
||||
+ chunkHolder.tasks.forEach(Runnable::run);
|
||||
+ // Paper end
|
||||
|
||||
- if (flag) {
|
||||
- ProtoChunk protochunk = ChunkSerializer.read(this.level, this.structureManager, this.poiManager, pos, nbttagcompound);
|
||||
+ if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async
|
||||
+
|
||||
+ if (true) {
|
||||
+ ProtoChunk protochunk = chunkHolder.protoChunk;
|
||||
|
||||
this.markPosition(pos, protochunk.getStatus().getChunkType());
|
||||
return Either.left(protochunk);
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
this.markPositionReplaceable(pos);
|
||||
return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level));
|
||||
return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), (BlendingData) null));
|
||||
- }, this.mainThreadExecutor);
|
||||
+ // Paper start - Async chunk io
|
||||
+ };
|
||||
@ -2537,7 +2540,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private void markPositionReplaceable(ChunkPos chunkcoordintpair) {
|
||||
private void markPositionReplaceable(ChunkPos pos) {
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
@ -2560,13 +2563,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
|
||||
this.level.getProfiler().incrementCounter("chunkSave");
|
||||
- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk);
|
||||
-
|
||||
- this.write(chunkcoordintpair, nbttagcompound);
|
||||
+ CompoundTag nbttagcompound;
|
||||
+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper
|
||||
+ nbttagcompound = ChunkSerializer.write(this.level, chunk);
|
||||
+ } // Paper
|
||||
+ } // Paper;
|
||||
+
|
||||
|
||||
- this.write(chunkcoordintpair, nbttagcompound);
|
||||
+ // Paper start - async chunk io
|
||||
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z,
|
||||
+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY);
|
||||
@ -2581,7 +2584,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ } // Paper
|
||||
}
|
||||
|
||||
private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) {
|
||||
private boolean isExistingChunkFull(ChunkPos pos) {
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
}
|
||||
@ -2618,14 +2621,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@Nullable
|
||||
public CompoundTag readChunk(ChunkPos pos) throws IOException {
|
||||
CompoundTag nbttagcompound = this.read(pos);
|
||||
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
|
||||
}
|
||||
|
||||
+ @Deprecated public PoiManager getVillagePlace() { return this.getPoiManager(); } // Paper - OBFHELPER
|
||||
protected PoiManager getPoiManager() {
|
||||
return this.poiManager;
|
||||
}
|
||||
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
|
||||
@ -2765,7 +2760,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
gameprofilerfiller.incrementCounter("getChunkCacheMiss");
|
||||
- CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create);
|
||||
+ CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper
|
||||
ServerChunkCache.MainThreadExecutor chunkproviderserver_a = this.mainThreadProcessor;
|
||||
ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor;
|
||||
|
||||
Objects.requireNonNull(completablefuture);
|
||||
if (!completablefuture.isDone()) { // Paper
|
||||
@ -2774,7 +2769,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1);
|
||||
+ // Paper end
|
||||
this.level.timings.syncChunkLoad.startTiming(); // Paper
|
||||
chunkproviderserver_a.managedBlock(completablefuture::isDone);
|
||||
chunkproviderserver_b.managedBlock(completablefuture::isDone);
|
||||
+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug
|
||||
this.level.timings.syncChunkLoad.stopTiming(); // Paper
|
||||
} // Paper
|
||||
@ -2937,8 +2932,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
private final LongSet loadedChunks = new LongOpenHashSet();
|
||||
+ private final net.minecraft.server.level.ServerLevel world; // Paper
|
||||
|
||||
public PoiManager(File directory, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) {
|
||||
super(directory, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world);
|
||||
public PoiManager(Path path, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) {
|
||||
super(path, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world);
|
||||
+ this.world = (net.minecraft.server.level.ServerLevel)world; // Paper
|
||||
this.distanceTracker = new PoiManager.DistanceTracker();
|
||||
}
|
||||
@ -2999,32 +2994,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
public static enum Occupancy {
|
||||
HAS_SPACE(PoiRecord::hasSpace),
|
||||
IS_OCCUPIED(PoiRecord::isOccupied),
|
||||
diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java
|
||||
@@ -0,0 +0,0 @@ import java.util.Comparator;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
public class TickNextTickData<T> {
|
||||
- private static long counter;
|
||||
+ private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading
|
||||
private final T type;
|
||||
public final BlockPos pos;
|
||||
public final long triggerTick;
|
||||
@@ -0,0 +0,0 @@ public class TickNextTickData<T> {
|
||||
}
|
||||
|
||||
public TickNextTickData(BlockPos pos, T t, long time, TickPriority priority) {
|
||||
- this.c = (long)(counter++);
|
||||
+ this.c = (TickNextTickData.COUNTER.getAndIncrement()); // Paper - async chunk loading
|
||||
this.pos = pos.immutable();
|
||||
this.type = t;
|
||||
this.triggerTick = time;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.ticks.LevelChunkTicks;
|
||||
import net.minecraft.world.ticks.ProtoChunkTicks;
|
||||
+import net.minecraft.world.ticks.TickContainerAccess;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
|
||||
public ChunkSerializer() {}
|
||||
@ -3044,56 +3025,50 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static ProtoChunk read(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt) {
|
||||
public static ProtoChunk read(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt) {
|
||||
+ // Paper start - add variant for async calls
|
||||
+ InProgressChunkHolder holder = loadChunk(world, structureManager, poiStorage, pos, nbt, true);
|
||||
+ InProgressChunkHolder holder = loadChunk(world, poiStorage, chunkPos, nbt, true);
|
||||
+ holder.tasks.forEach(Runnable::run);
|
||||
+ return holder.protoChunk;
|
||||
+ }
|
||||
+ public static InProgressChunkHolder loadChunk(ServerLevel world, StructureManager structureManager, PoiManager poiStorage, ChunkPos pos, CompoundTag nbt, boolean distinguish) {
|
||||
+
|
||||
+ public static InProgressChunkHolder loadChunk(ServerLevel world, PoiManager poiStorage, ChunkPos chunkPos, CompoundTag nbt, boolean distinguish) {
|
||||
+ java.util.ArrayDeque<Runnable> tasksToExecuteOnMain = new java.util.ArrayDeque<>();
|
||||
+ // Paper end
|
||||
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
|
||||
BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource();
|
||||
CompoundTag nbttagcompound1 = nbt.getCompound("Level");
|
||||
ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos"));
|
||||
|
||||
if (!Objects.equals(chunkPos, chunkcoordintpair1)) {
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
LevelLightEngine lightengine = chunkproviderserver.getLightEngine();
|
||||
|
||||
if (flag) {
|
||||
+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main
|
||||
lightengine.retainData(pos, true);
|
||||
lightengine.retainData(chunkPos, true);
|
||||
+ }); // Paper - delay this task since we're executing off-main
|
||||
}
|
||||
|
||||
for (int j = 0; j < nbttaglist.size(); ++j) {
|
||||
Registry<Biome> iregistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
achunksection[world.getSectionIndexFromSectionY(b0)] = chunksection;
|
||||
}
|
||||
|
||||
+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main
|
||||
poiStorage.checkConsistencyWithBlocks(pos, chunksection);
|
||||
+ }); // Paper - delay this task since we're executing off-main
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
if (nbttagcompound2.contains("BlockLight", 7)) {
|
||||
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true);
|
||||
if (nbttagcompound1.contains("BlockLight", 7)) {
|
||||
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("BlockLight")), true);
|
||||
+ // Paper start - delay this task since we're executing off-main
|
||||
+ DataLayer blockLight = new DataLayer(nbttagcompound2.getByteArray("BlockLight"));
|
||||
+ DataLayer blockLight = new DataLayer(nbttagcompound1.getByteArray("BlockLight"));
|
||||
+ tasksToExecuteOnMain.add(() -> {
|
||||
+ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true);
|
||||
+ });
|
||||
+ // Paper end - delay this task since we're executing off-main
|
||||
}
|
||||
|
||||
if (flag1 && nbttagcompound2.contains("SkyLight", 7)) {
|
||||
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true);
|
||||
if (flag1 && nbttagcompound1.contains("SkyLight", 7)) {
|
||||
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, b0), new DataLayer(nbttagcompound1.getByteArray("SkyLight")), true);
|
||||
+ // Paper start - delay this task since we're executing off-main
|
||||
+ DataLayer skyLight = new DataLayer(nbttagcompound2.getByteArray("SkyLight"));
|
||||
+ DataLayer skyLight = new DataLayer(nbttagcompound1.getByteArray("SkyLight"));
|
||||
+ tasksToExecuteOnMain.add(() -> {
|
||||
+ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair1, b0), skyLight, true);
|
||||
+ });
|
||||
+ // Paper end - delay this task since we're executing off-main
|
||||
+ // Paper end - delay this task since we're executing off-mai
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3101,20 +3076,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
}
|
||||
|
||||
if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) {
|
||||
- return new ImposterProtoChunk((LevelChunk) object);
|
||||
+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading
|
||||
- return new ImposterProtoChunk((LevelChunk) object, false);
|
||||
+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object, false), tasksToExecuteOnMain); // Paper - Async chunk loading
|
||||
} else {
|
||||
ProtoChunk protochunk1 = (ProtoChunk) object;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
protochunk1.setCarvingMask(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1)));
|
||||
protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound4.getLongArray(s1), ((ChunkAccess) object).getMinBuildHeight()));
|
||||
}
|
||||
|
||||
- return protochunk1;
|
||||
+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - async chunk save for unload
|
||||
+ public static final class AsyncSaveData {
|
||||
+ public final DataLayer[] blockLight;
|
||||
@ -3163,8 +3138,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray;
|
||||
+ }
|
||||
+
|
||||
+ TickList<Block> blockTickList = chunk.getBlockTicks();
|
||||
+ TickContainerAccess<Block> blockTickList = chunk.getBlockTicks();
|
||||
+
|
||||
+ //TODO check ChunkSerializer "block_ticks"
|
||||
+ ListTag blockTickListSerialized;
|
||||
+ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) {
|
||||
+ blockTickListSerialized = null;
|
||||
@ -3172,13 +3148,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ blockTickListSerialized = world.getBlockTicks().save(chunkPos);
|
||||
+ }
|
||||
+
|
||||
+ TickList<Fluid> fluidTickList = chunk.getLiquidTicks();
|
||||
+ TickContainerAccess<Fluid> fluidTickList = chunk.getFluidTicks();
|
||||
+
|
||||
+ //TODO
|
||||
+ ListTag fluidTickListSerialized;
|
||||
+ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) {
|
||||
+ fluidTickListSerialized = null;
|
||||
+ } else {
|
||||
+ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos);
|
||||
+ fluidTickListSerialized = world.getFluidTicks().save(chunkPos);
|
||||
+ }
|
||||
+
|
||||
+ ListTag blockEntitiesSerialized = new ListTag();
|
||||
@ -3187,9 +3164,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ if (blockEntityNbt != null) {
|
||||
+ blockEntitiesSerialized.add(blockEntityNbt);
|
||||
+ }
|
||||
}
|
||||
+ }
|
||||
+
|
||||
+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime());
|
||||
+ }
|
||||
+
|
||||
private static void logErrors(ChunkPos chunkPos, int y, String message) {
|
||||
ChunkSerializer.LOGGER.error("Recoverable errors when loading section [" + chunkPos.x + ", " + y + ", " + chunkPos.z + "]: " + message);
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
}
|
||||
|
||||
public static CompoundTag write(ServerLevel world, ChunkAccess chunk) {
|
||||
@ -3199,23 +3182,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ // Paper end
|
||||
ChunkPos chunkcoordintpair = chunk.getPos();
|
||||
CompoundTag nbttagcompound = new CompoundTag();
|
||||
CompoundTag nbttagcompound1 = new CompoundTag();
|
||||
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
nbttagcompound.put("Level", nbttagcompound1);
|
||||
nbttagcompound1.putInt("xPos", chunkcoordintpair.x);
|
||||
nbttagcompound1.putInt("zPos", chunkcoordintpair.z);
|
||||
- nbttagcompound1.putLong("LastUpdate", world.getGameTime());
|
||||
+ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading
|
||||
nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime());
|
||||
nbttagcompound1.putString("Status", chunk.getStatus().getName());
|
||||
UpgradeData chunkconverter = chunk.getUpgradeData();
|
||||
nbttagcompound.putInt("yPos", chunk.getMinSection());
|
||||
nbttagcompound.putInt("zPos", chunkcoordintpair.z);
|
||||
nbttagcompound.putLong("LastUpdate", world.getGameTime());
|
||||
+ nbttagcompound.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading
|
||||
nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime());
|
||||
nbttagcompound.putString("Status", chunk.getStatus().getName());
|
||||
BlendingData blendingdata = chunk.getBlendingData();
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> {
|
||||
return chunksection1 != null && SectionPos.blockToSectionCoord(chunksection1.bottomBlockY()) == finalI; // CraftBukkit - decompile errors
|
||||
}).findFirst().orElse(LevelChunk.EMPTY_SECTION);
|
||||
for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) {
|
||||
int j = chunk.getSectionIndexFromSectionY(i);
|
||||
boolean flag1 = j >= 0 && j < achunksection.length;
|
||||
- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
|
||||
- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
|
||||
-
|
||||
+ // Paper start - async chunk save for unload
|
||||
+ DataLayer nibblearray; // block light
|
||||
+ DataLayer nibblearray1; // sky light
|
||||
@ -3227,11 +3208,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()];
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (chunksection != LevelChunk.EMPTY_SECTION || nibblearray != null || nibblearray1 != null) {
|
||||
CompoundTag nbttagcompound2 = new CompoundTag();
|
||||
|
||||
if (flag1 || nibblearray != null || nibblearray1 != null) {
|
||||
CompoundTag nbttagcompound1 = new CompoundTag();
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes());
|
||||
nbttagcompound.putBoolean("isLightOn", true);
|
||||
}
|
||||
|
||||
- ListTag nbttaglist1 = new ListTag();
|
||||
@ -3248,38 +3229,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
CompoundTag nbttagcompound3;
|
||||
CompoundTag nbttagcompound2;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save());
|
||||
} else if (ticklist instanceof ChunkTickList) {
|
||||
nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save());
|
||||
+ // Paper start - async chunk save for unload
|
||||
+ } else if (asyncsavedata != null) {
|
||||
+ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList);
|
||||
+ // Paper end
|
||||
} else {
|
||||
nbttagcompound1.put("TileTicks", world.getBlockTicks().save(chunkcoordintpair));
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class ChunkSerializer {
|
||||
nbttagcompound1.put("LiquidsToBeTicked", ((ProtoTickList) ticklist1).save());
|
||||
} else if (ticklist1 instanceof ChunkTickList) {
|
||||
nbttagcompound1.put("LiquidTicks", ((ChunkTickList) ticklist1).save());
|
||||
+ // Paper start - async chunk save for unload
|
||||
+ } else if (asyncsavedata != null) {
|
||||
+ nbttagcompound1.put("LiquidTicks", asyncsavedata.fluidTickList);
|
||||
+ // Paper end
|
||||
} else {
|
||||
nbttagcompound1.put("LiquidTicks", world.getLiquidTicks().save(chunkcoordintpair));
|
||||
}
|
||||
private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) {
|
||||
long i = world.getLevelData().getGameTime();
|
||||
|
||||
+ //TODO original patch line 3259
|
||||
nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> {
|
||||
return Registry.BLOCK.getKey(block).toString();
|
||||
}));
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.DimensionDataStorage;
|
||||
|
||||
public class ChunkStorage implements AutoCloseable {
|
||||
|
||||
public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493;
|
||||
- private final IOWorker worker;
|
||||
+ // Paper - nuke IO worker
|
||||
protected final DataFixer fixerUpper;
|
||||
@ -3291,7 +3258,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ public final RegionFileStorage regionFileCache;
|
||||
+ // Paper end - async chunk loading
|
||||
|
||||
public ChunkStorage(File directory, DataFixer dataFixer, boolean dsync) {
|
||||
public ChunkStorage(Path directory, DataFixer dataFixer, boolean dsync) {
|
||||
this.fixerUpper = dataFixer;
|
||||
- this.worker = new IOWorker(directory, dsync, "chunk");
|
||||
+ // Paper start - async chunk io
|
||||
@ -3366,7 +3333,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
- this.worker.close();
|
||||
+ this.regionFileCache.close(); // Paper - nuke IO worker
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkScanAccess chunkScanner() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@ -3377,8 +3345,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
protected final RegionBitmap usedSectors;
|
||||
+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper
|
||||
|
||||
public RegionFile(File file, File directory, boolean dsync) throws IOException {
|
||||
this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync);
|
||||
public RegionFile(Path path, Path path1, boolean dsync) throws IOException {
|
||||
this(path, path1, RegionFileVersion.VERSION_DEFLATE, dsync);
|
||||
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
|
||||
return (byteCount + 4096 - 1) / 4096;
|
||||
}
|
||||
@ -3410,7 +3378,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ } // Paper end
|
||||
|
||||
}
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@ -3418,7 +3386,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
this.sync = dsync;
|
||||
}
|
||||
|
||||
|
||||
- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
|
||||
+ // Paper start
|
||||
+ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) {
|
||||
@ -3438,7 +3406,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ // Paper end
|
||||
long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
|
||||
RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i);
|
||||
|
||||
|
||||
if (regionfile != null) {
|
||||
+ // Paper start
|
||||
+ if (lock) {
|
||||
@ -3451,7 +3419,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync);
|
||||
|
||||
|
||||
this.regionCache.putAndMoveToFirst(i, regionfile1);
|
||||
+ // Paper start
|
||||
+ if (lock) {
|
||||
@ -3474,23 +3442,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
// CraftBukkit end
|
||||
+ try { // Paper
|
||||
DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos);
|
||||
|
||||
|
||||
CompoundTag nbttagcompound;
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
}
|
||||
|
||||
|
||||
return nbttagcompound;
|
||||
+ } finally { // Paper start
|
||||
+ regionfile.fileLock.unlock();
|
||||
+ } // Paper end
|
||||
}
|
||||
|
||||
|
||||
protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException {
|
||||
- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit
|
||||
+ RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper
|
||||
+ try { // Paper
|
||||
int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper
|
||||
|
||||
|
||||
if (nbt == null) {
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
MinecraftServer.LOGGER.error("Failed to save chunk", laste);
|
||||
@ -3500,20 +3468,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ regionfile.fileLock.unlock();
|
||||
+ } // Paper end
|
||||
}
|
||||
|
||||
|
||||
- public void close() throws IOException {
|
||||
+ public synchronized void close() throws IOException { // Paper -> synchronized
|
||||
ExceptionCollector<IOException> exceptionsuppressor = new ExceptionCollector<>();
|
||||
ObjectIterator objectiterator = this.regionCache.values().iterator();
|
||||
|
||||
|
||||
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
|
||||
exceptionsuppressor.throwIfPresent();
|
||||
}
|
||||
|
||||
|
||||
- public void flush() throws IOException {
|
||||
+ public synchronized void flush() throws IOException { // Paper - synchronize
|
||||
ObjectIterator objectiterator = this.regionCache.values().iterator();
|
||||
|
||||
|
||||
while (objectiterator.hasNext()) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
@ -3522,7 +3490,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
||||
-public class SectionStorage<R> implements AutoCloseable {
|
||||
+public class SectionStorage<R> extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
@ -3534,7 +3502,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
private final Function<Runnable, Codec<R>> codec;
|
||||
@@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable {
|
||||
protected final LevelHeightAccessor levelHeightAccessor;
|
||||
|
||||
|
||||
public SectionStorage(File directory, Function<Runnable, Codec<R>> codecFactory, Function<Runnable, R> factory, DataFixer dataFixer, DataFixTypes dataFixTypes, boolean dsync, LevelHeightAccessor world) {
|
||||
+ super(directory, dsync); // Paper - nuke IOWorker
|
||||
this.codec = codecFactory;
|
||||
@ -3545,11 +3513,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
- this.worker = new IOWorker(directory, dsync, directory.getName());
|
||||
+ // Paper - remove mojang I/O thread
|
||||
}
|
||||
|
||||
|
||||
protected void tick(BooleanSupplier shouldKeepTicking) {
|
||||
@@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable {
|
||||
}
|
||||
|
||||
|
||||
private void readColumn(ChunkPos chunkPos) {
|
||||
- this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos));
|
||||
+ // Paper start - expose function to load in data
|
||||
@ -3559,7 +3527,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ this.readColumn(chunkPos, NbtOps.INSTANCE, compound);
|
||||
+ // Paper end - expose function to load in data
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private CompoundTag tryRead(ChunkPos pos) {
|
||||
try {
|
||||
@ -3577,9 +3545,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
} else {
|
||||
LOGGER.error("Expected compound tag, got {}", (Object)tag);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+ // Paper start - internal get data function, copied from above
|
||||
+ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) {
|
||||
+ Dynamic<Tag> dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE);
|
||||
@ -3595,9 +3563,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ // Paper end
|
||||
private <T> Dynamic<T> writeColumn(ChunkPos chunkPos, DynamicOps<T> dynamicOps) {
|
||||
Map<T, T> map = Maps.newHashMap();
|
||||
|
||||
|
||||
@@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable {
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
- this.worker.close();
|
||||
|
@ -1,35 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 26 Aug 2018 20:49:50 -0400
|
||||
Subject: [PATCH] Optimize MappedRegistry
|
||||
|
||||
Use larger initial sizes to increase bucket capacity on the BiMap
|
||||
|
||||
BiMap.get was seen to be using a good bit of CPU time.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/MappedRegistry.java b/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
+++ b/src/main/java/net/minecraft/core/MappedRegistry.java
|
||||
@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
|
||||
public class MappedRegistry<T> extends WritableRegistry<T> {
|
||||
protected static final Logger LOGGER = LogManager.getLogger();
|
||||
private final ObjectList<T> byId = new ObjectArrayList<>(256);
|
||||
- private final Object2IntMap<T> toId = new Object2IntOpenCustomHashMap<>(Util.identityStrategy());
|
||||
+ private final it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T> toId = new it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap<T>(2048);// Paper - use bigger expected size to reduce collisions and direct intent for FastUtil to be identity map
|
||||
private final BiMap<ResourceLocation, T> storage;
|
||||
private final BiMap<ResourceKey<T>, T> keyStorage;
|
||||
private final Map<T, Lifecycle> lifecycles;
|
||||
@@ -0,0 +0,0 @@ public class MappedRegistry<T> extends WritableRegistry<T> {
|
||||
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
|
||||
super(key, lifecycle);
|
||||
this.toId.defaultReturnValue(-1);
|
||||
- this.storage = HashBiMap.create();
|
||||
- this.keyStorage = HashBiMap.create();
|
||||
- this.lifecycles = Maps.newIdentityHashMap();
|
||||
+ this.storage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
|
||||
+ this.keyStorage = HashBiMap.create(2048); // Paper - use bigger expected size to reduce collisions
|
||||
+ this.lifecycles = new java.util.IdentityHashMap<>(2048); // Paper - use bigger expected size to reduce collisions
|
||||
this.elementsLifecycle = lifecycle;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user