13
0
geforkt von Mirrors/Paper

More more more more more more more work

Dieser Commit ist enthalten in:
Nassim Jahnke 2021-11-23 16:50:18 +01:00
Ursprung 82f6e6bb0e
Commit c36c2d46d3
20 geänderte Dateien mit 179 neuen und 212 gelöschten Zeilen

Datei anzeigen

@ -72,12 +72,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ continue; + continue;
+ } + }
+ // Paper end + // Paper end
Phantom entityphantom = (Phantom) EntityType.PHANTOM.create((Level) world); Phantom entityphantom = (Phantom) EntityType.PHANTOM.create(world);
- -
+ entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper + entityphantom.setSpawningEntity(entityhuman.getUUID()); // Paper
entityphantom.moveTo(blockposition1, 0.0F, 0.0F); entityphantom.moveTo(blockposition1, 0.0F, 0.0F);
groupdataentity = entityphantom.finalizeSpawn(world, difficultydamagescaler, MobSpawnType.NATURAL, groupdataentity, (CompoundTag) null); 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 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 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java

Datei anzeigen

@ -23,9 +23,9 @@ diff --git a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java b/sr
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java --- a/src/main/java/net/minecraft/world/level/block/LiquidBlock.java
+++ b/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.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
+import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.level.pathfinder.PathComputationType;
@ -35,8 +35,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) { if (this.shouldSpreadLiquid(world, pos, state)) {
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); - world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
} }
} }
@ -64,8 +64,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
if (this.shouldSpreadLiquid(world, pos, state)) { if (this.shouldSpreadLiquid(world, pos, state)) {
- world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay((LevelReader) world)); - world.scheduleTick(pos, state.getFluidState().getType(), this.fluid.getTickDelay(world));
+ world.getLiquidTicks().scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper + world.scheduleTick(pos, state.getFluidState().getType(), this.getFlowSpeed(world, pos)); // Paper
} }
} }

Datei anzeigen

@ -14,11 +14,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
log("Creeper lingering effect: " + disableCreeperLingeringEffect); log("Creeper lingering effect: " + disableCreeperLingeringEffect);
} }
+ +
+ public double squidMaxSpawnHeight;
+ private void squidMaxSpawnHeight() {
+ squidMaxSpawnHeight = getDouble("squid-spawn-height.maximum", 0.0D);
+ }
+
+ public boolean disableSprintInterruptionOnAttack; + public boolean disableSprintInterruptionOnAttack;
+ private void disableSprintInterruptionOnAttack() { + private void disableSprintInterruptionOnAttack() {
+ disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); + disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false);

Datei anzeigen

@ -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) {

Datei anzeigen

@ -85,7 +85,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
@@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy { @@ -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()); ((Slime.SlimeMoveControl) this.slime.getMoveControl()).setDirection(this.slime.getYRot(), this.slime.isDealsDamage());
} }
+ +
@ -107,12 +107,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
@Override @Override
public void tick() { @@ -0,0 +0,0 @@ public class Slime extends Mob implements Enemy {
if (--this.nextRandomizeTime <= 0) { if (--this.nextRandomizeTime <= 0) {
this.nextRandomizeTime = 40 + this.slime.getRandom().nextInt(60); this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60));
- this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); this.chosenDegrees = (float) this.slime.getRandom().nextInt(360);
+ // Paper start + // 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; + if (!this.slime.canWander || !event.callEvent()) return;
+ this.chosenDegrees = event.getNewYaw(); + this.chosenDegrees = event.getNewYaw();
+ // Paper end + // Paper end

Datei anzeigen

@ -3,6 +3,9 @@ From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 13 Jul 2019 09:23:10 -0700 Date: Sat, 13 Jul 2019 09:23:10 -0700
Subject: [PATCH] Asynchronous chunk IO and loading 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 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 NBT data onto worker threads. This patch also will shove
chunk data serialization onto the same worker threads when the chunk 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 --- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/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 { @@ -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) { + 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 +++ b/src/main/java/net/minecraft/server/Main.java
@@ -0,0 +0,0 @@ public class Main { @@ -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 + 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) -> { final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.spin((thread) -> {
@ -2364,18 +2367,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return true; return true;
}); });
- this.flushWorker(); - this.flushWorker();
+ //this.flushWorker(); // Paper - nuke IOWorker
+ this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour + this.level.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
+// this.i(); // Paper - nuke IOWorker
} else { } else {
this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> { this.visibleChunkMap.values().stream().filter(ChunkHolder::wasAccessibleSinceLastSave).forEach((playerchunk) -> {
ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -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) { protected void tick(BooleanSupplier shouldKeepTicking) {
ProfilerFiller gameprofilerfiller = this.level.getProfiler(); ProfilerFiller gameprofilerfiller = this.level.getProfiler();
@ -2387,10 +2384,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!this.level.noSave()) { if (!this.level.noSave()) {
+ try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper + try (Timing ignored = this.level.timings.chunkUnload.startTiming()) { // Paper
this.processUnloads(shouldKeepTicking); this.processUnloads(shouldKeepTicking);
+ }// Paper + } // Paper
} }
gameprofilerfiller.pop(); 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 @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (playerchunk != null) { if (playerchunk != null) {
this.pendingUnloads.put(j, playerchunk); this.pendingUnloads.put(j, playerchunk);
@ -2402,7 +2406,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
// Spigot end // Spigot end
- this.scheduleUnload(j, playerchunk); - 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 activityAccountant.endActivity(); // Spigot
@ -2418,7 +2422,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ChunkPos chunkPos = chunk.getPos(); + ChunkPos chunkPos = chunk.getPos();
+ CompoundTag poiData; + CompoundTag poiData;
+ try (Timing ignored = this.level.timings.chunkUnloadPOISerialization.startTiming()) { + 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, + 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); + LOGGER.fatal("Failed to prepare async save, attempting synchronous save", ex);
+ this.save(ichunkaccess); + this.save(ichunkaccess);
+ } + }
+ // Paper end - async chunk saving + // Paper end - async chunk savin
if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) { if (this.entitiesInLevel.remove(pos) && ichunkaccess instanceof LevelChunk) {
LevelChunk chunk = (LevelChunk) ichunkaccess; LevelChunk chunk = (LevelChunk) ichunkaccess;
@ -2484,30 +2488,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings - try (Timing ignored2 = this.level.timings.chunkIO.startTimingIfSync()) { // Paper start - timings
- nbttagcompound = this.readChunk(pos); - nbttagcompound = this.readChunk(pos);
- } // Paper end - } // 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 + // Paper start
+ if (ioThrowable != null) { + if (ioThrowable != null) {
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable); + com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable);
+ } + }
+ this.poiManager.loadInData(pos, chunkHolder.poiData);
- 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);
+ chunkHolder.tasks.forEach(Runnable::run); + chunkHolder.tasks.forEach(Runnable::run);
+ // Paper end + // 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 (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.level.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async
+
+ if (true) { + if (true) {
+ ProtoChunk protochunk = chunkHolder.protoChunk;
this.markPosition(pos, protochunk.getStatus().getChunkType()); this.markPosition(pos, protochunk.getStatus().getChunkType());
return Either.left(protochunk); return Either.left(protochunk);
}
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.markPositionReplaceable(pos); 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); - }, this.mainThreadExecutor);
+ // Paper start - Async chunk io + // Paper start - Async chunk io
+ }; + };
@ -2537,7 +2540,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
} }
private void markPositionReplaceable(ChunkPos chunkcoordintpair) { private void markPositionReplaceable(ChunkPos pos) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
} }
@ -2560,13 +2563,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.level.getProfiler().incrementCounter("chunkSave"); this.level.getProfiler().incrementCounter("chunkSave");
- CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk); - CompoundTag nbttagcompound = ChunkSerializer.write(this.level, chunk);
-
- this.write(chunkcoordintpair, nbttagcompound);
+ CompoundTag nbttagcompound; + CompoundTag nbttagcompound;
+ try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper + try (co.aikar.timings.Timing ignored1 = this.level.timings.chunkSaveDataSerialization.startTiming()) { // Paper
+ nbttagcompound = ChunkSerializer.write(this.level, chunk); + nbttagcompound = ChunkSerializer.write(this.level, chunk);
+ } // Paper + } // Paper;
+ +
- this.write(chunkcoordintpair, nbttagcompound);
+ // Paper start - async chunk io + // Paper start - async chunk io
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z, + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.level, chunkcoordintpair.x, chunkcoordintpair.z,
+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); + null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY);
@ -2581,7 +2584,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } // Paper + } // Paper
} }
private boolean isExistingChunkFull(ChunkPos chunkcoordintpair) { private boolean isExistingChunkFull(ChunkPos pos) {
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
} }
} }
@ -2618,14 +2621,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Nullable @Nullable
public CompoundTag readChunk(ChunkPos pos) throws IOException { public CompoundTag readChunk(ChunkPos pos) throws IOException {
CompoundTag nbttagcompound = this.read(pos); 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 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 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@ -2765,7 +2760,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
gameprofilerfiller.incrementCounter("getChunkCacheMiss"); 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);
+ CompletableFuture<Either<ChunkAccess, ChunkHolder.ChunkLoadingFailure>> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create, true); // Paper + 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); Objects.requireNonNull(completablefuture);
if (!completablefuture.isDone()) { // Paper if (!completablefuture.isDone()) { // Paper
@ -2774,7 +2769,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1); + com.destroystokyo.paper.io.chunk.ChunkTaskManager.pushChunkWait(this.level, x1, z1);
+ // Paper end + // Paper end
this.level.timings.syncChunkLoad.startTiming(); // Paper 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 + com.destroystokyo.paper.io.chunk.ChunkTaskManager.popChunkWait(); // Paper - async chunk debug
this.level.timings.syncChunkLoad.stopTiming(); // Paper this.level.timings.syncChunkLoad.stopTiming(); // Paper
} // Paper } // Paper
@ -2937,8 +2932,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final LongSet loadedChunks = new LongOpenHashSet(); private final LongSet loadedChunks = new LongOpenHashSet();
+ private final net.minecraft.server.level.ServerLevel world; // Paper + private final net.minecraft.server.level.ServerLevel world; // Paper
public PoiManager(File directory, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) { public PoiManager(Path path, DataFixer dataFixer, boolean dsync, LevelHeightAccessor world) {
super(directory, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world); super(path, PoiSection::codec, PoiSection::new, dataFixer, DataFixTypes.POI_CHUNK, dsync, world);
+ this.world = (net.minecraft.server.level.ServerLevel)world; // Paper + this.world = (net.minecraft.server.level.ServerLevel)world; // Paper
this.distanceTracker = new PoiManager.DistanceTracker(); this.distanceTracker = new PoiManager.DistanceTracker();
} }
@ -2999,32 +2994,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public static enum Occupancy { public static enum Occupancy {
HAS_SPACE(PoiRecord::hasSpace), HAS_SPACE(PoiRecord::hasSpace),
IS_OCCUPIED(PoiRecord::isOccupied), 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 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 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ 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 { @@ -0,0 +0,0 @@ public class ChunkSerializer {
public ChunkSerializer() {} public ChunkSerializer() {}
@ -3044,56 +3025,50 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // 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 + // 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); + holder.tasks.forEach(Runnable::run);
+ return holder.protoChunk; + 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<>(); + java.util.ArrayDeque<Runnable> tasksToExecuteOnMain = new java.util.ArrayDeque<>();
+ // Paper end + // Paper end
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); ChunkPos chunkcoordintpair1 = new ChunkPos(nbt.getInt("xPos"), nbt.getInt("zPos"));
BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource();
CompoundTag nbttagcompound1 = nbt.getCompound("Level"); if (!Objects.equals(chunkPos, chunkcoordintpair1)) {
@@ -0,0 +0,0 @@ public class ChunkSerializer { @@ -0,0 +0,0 @@ public class ChunkSerializer {
LevelLightEngine lightengine = chunkproviderserver.getLightEngine(); LevelLightEngine lightengine = chunkproviderserver.getLightEngine();
if (flag) { if (flag) {
+ tasksToExecuteOnMain.add(() -> { // Paper - delay this task since we're executing off-main + 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 + }); // 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 { @@ -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 (flag) {
if (nbttagcompound2.contains("BlockLight", 7)) { if (nbttagcompound1.contains("BlockLight", 7)) {
- lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("BlockLight")), true); - 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 + // 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(() -> { + tasksToExecuteOnMain.add(() -> {
+ lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true); + lightengine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkcoordintpair1, b0), blockLight, true);
+ }); + });
+ // Paper end - delay this task since we're executing off-main + // Paper end - delay this task since we're executing off-main
} }
if (flag1 && nbttagcompound2.contains("SkyLight", 7)) { if (flag1 && nbttagcompound1.contains("SkyLight", 7)) {
- lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(pos, b0), new DataLayer(nbttagcompound2.getByteArray("SkyLight")), true); - 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 + // 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(() -> { + tasksToExecuteOnMain.add(() -> {
+ lightengine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkcoordintpair1, b0), skyLight, true); + 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) { if (chunkstatus_type == ChunkStatus.ChunkType.LEVELCHUNK) {
- return new ImposterProtoChunk((LevelChunk) object); - return new ImposterProtoChunk((LevelChunk) object, false);
+ return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object), tasksToExecuteOnMain); // Paper - Async chunk loading + return new InProgressChunkHolder(new ImposterProtoChunk((LevelChunk) object, false), tasksToExecuteOnMain); // Paper - Async chunk loading
} else { } else {
ProtoChunk protochunk1 = (ProtoChunk) object; ProtoChunk protochunk1 = (ProtoChunk) object;
@@ -0,0 +0,0 @@ public class ChunkSerializer { @@ -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 protochunk1;
+ return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading + return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading
+ } }
+ } }
+
+ // Paper start - async chunk save for unload + // Paper start - async chunk save for unload
+ public static final class AsyncSaveData { + public static final class AsyncSaveData {
+ public final DataLayer[] blockLight; + public final DataLayer[] blockLight;
@ -3163,8 +3138,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray; + skyLight[i - lightenginethreaded.getMinLightSection()] = skyArray;
+ } + }
+ +
+ TickList<Block> blockTickList = chunk.getBlockTicks(); + TickContainerAccess<Block> blockTickList = chunk.getBlockTicks();
+ +
+ //TODO check ChunkSerializer "block_ticks"
+ ListTag blockTickListSerialized; + ListTag blockTickListSerialized;
+ if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) { + if (blockTickList instanceof ProtoTickList || blockTickList instanceof ChunkTickList) {
+ blockTickListSerialized = null; + blockTickListSerialized = null;
@ -3172,13 +3148,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ blockTickListSerialized = world.getBlockTicks().save(chunkPos); + blockTickListSerialized = world.getBlockTicks().save(chunkPos);
+ } + }
+ +
+ TickList<Fluid> fluidTickList = chunk.getLiquidTicks(); + TickContainerAccess<Fluid> fluidTickList = chunk.getFluidTicks();
+ +
+ //TODO
+ ListTag fluidTickListSerialized; + ListTag fluidTickListSerialized;
+ if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) { + if (fluidTickList instanceof ProtoTickList || fluidTickList instanceof ChunkTickList) {
+ fluidTickListSerialized = null; + fluidTickListSerialized = null;
+ } else { + } else {
+ fluidTickListSerialized = world.getLiquidTicks().save(chunkPos); + fluidTickListSerialized = world.getFluidTicks().save(chunkPos);
+ } + }
+ +
+ ListTag blockEntitiesSerialized = new ListTag(); + ListTag blockEntitiesSerialized = new ListTag();
@ -3187,9 +3164,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (blockEntityNbt != null) { + if (blockEntityNbt != null) {
+ blockEntitiesSerialized.add(blockEntityNbt); + blockEntitiesSerialized.add(blockEntityNbt);
+ } + }
} + }
+ +
+ return new AsyncSaveData(blockLight, skyLight, blockTickListSerialized, fluidTickListSerialized, blockEntitiesSerialized, world.getGameTime()); + 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) { public static CompoundTag write(ServerLevel world, ChunkAccess chunk) {
@ -3199,23 +3182,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
ChunkPos chunkcoordintpair = chunk.getPos(); ChunkPos chunkcoordintpair = chunk.getPos();
CompoundTag nbttagcompound = new CompoundTag(); CompoundTag nbttagcompound = new CompoundTag();
CompoundTag nbttagcompound1 = new CompoundTag();
@@ -0,0 +0,0 @@ public class ChunkSerializer { @@ -0,0 +0,0 @@ public class ChunkSerializer {
nbttagcompound.put("Level", nbttagcompound1); nbttagcompound.putInt("yPos", chunk.getMinSection());
nbttagcompound1.putInt("xPos", chunkcoordintpair.x); nbttagcompound.putInt("zPos", chunkcoordintpair.z);
nbttagcompound1.putInt("zPos", chunkcoordintpair.z); nbttagcompound.putLong("LastUpdate", world.getGameTime());
- nbttagcompound1.putLong("LastUpdate", world.getGameTime()); + nbttagcompound.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading
+ nbttagcompound1.putLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : world.getGameTime()); // Paper - async chunk unloading nbttagcompound.putLong("InhabitedTime", chunk.getInhabitedTime());
nbttagcompound1.putLong("InhabitedTime", chunk.getInhabitedTime()); nbttagcompound.putString("Status", chunk.getStatus().getName());
nbttagcompound1.putString("Status", chunk.getStatus().getName()); BlendingData blendingdata = chunk.getBlendingData();
UpgradeData chunkconverter = chunk.getUpgradeData();
@@ -0,0 +0,0 @@ public class ChunkSerializer { @@ -0,0 +0,0 @@ public class ChunkSerializer {
LevelChunkSection chunksection = (LevelChunkSection) Arrays.stream(achunksection).filter((chunksection1) -> { for (int i = lightenginethreaded.getMinLightSection(); i < lightenginethreaded.getMaxLightSection(); ++i) {
return chunksection1 != null && SectionPos.blockToSectionCoord(chunksection1.bottomBlockY()) == finalI; // CraftBukkit - decompile errors int j = chunk.getSectionIndexFromSectionY(i);
}).findFirst().orElse(LevelChunk.EMPTY_SECTION); boolean flag1 = j >= 0 && j < achunksection.length;
- DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); - DataLayer nibblearray = lightenginethreaded.getLayerListener(LightLayer.BLOCK).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
- DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i)); - DataLayer nibblearray1 = lightenginethreaded.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(chunkcoordintpair, i));
-
+ // Paper start - async chunk save for unload + // Paper start - async chunk save for unload
+ DataLayer nibblearray; // block light + DataLayer nibblearray; // block light
+ DataLayer nibblearray1; // sky light + DataLayer nibblearray1; // sky light
@ -3227,11 +3208,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()]; + nibblearray1 = asyncsavedata.skyLight[i - lightenginethreaded.getMinLightSection()];
+ } + }
+ // Paper end + // 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 { @@ -0,0 +0,0 @@ public class ChunkSerializer {
nbttagcompound1.putIntArray("Biomes", biomestorage.writeBiomes()); nbttagcompound.putBoolean("isLightOn", true);
} }
- ListTag nbttaglist1 = new ListTag(); - ListTag nbttaglist1 = new ListTag();
@ -3248,38 +3229,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // Paper end
CompoundTag nbttagcompound3; CompoundTag nbttagcompound2;
@@ -0,0 +0,0 @@ public class ChunkSerializer { @@ -0,0 +0,0 @@ public class ChunkSerializer {
nbttagcompound1.put("ToBeTicked", ((ProtoTickList) ticklist).save()); private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) {
} else if (ticklist instanceof ChunkTickList) { long i = world.getLevelData().getGameTime();
nbttagcompound1.put("TileTicks", ((ChunkTickList) ticklist).save());
+ // Paper start - async chunk save for unload + //TODO original patch line 3259
+ } else if (asyncsavedata != null) { nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> {
+ nbttagcompound1.put("TileTicks", asyncsavedata.blockTickList); return Registry.BLOCK.getKey(block).toString();
+ // 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));
}
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 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 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/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; @@ -0,0 +0,0 @@ import net.minecraft.world.level.storage.DimensionDataStorage;
public class ChunkStorage implements AutoCloseable { public class ChunkStorage implements AutoCloseable {
public static final int LAST_MONOLYTH_STRUCTURE_DATA_VERSION = 1493;
- private final IOWorker worker; - private final IOWorker worker;
+ // Paper - nuke IO worker + // Paper - nuke IO worker
protected final DataFixer fixerUpper; protected final DataFixer fixerUpper;
@ -3291,7 +3258,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public final RegionFileStorage regionFileCache; + public final RegionFileStorage regionFileCache;
+ // Paper end - async chunk loading + // 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.fixerUpper = dataFixer;
- this.worker = new IOWorker(directory, dsync, "chunk"); - this.worker = new IOWorker(directory, dsync, "chunk");
+ // Paper start - async chunk io + // Paper start - async chunk io
@ -3366,7 +3333,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.worker.close(); - this.worker.close();
+ this.regionFileCache.close(); // Paper - nuke IO worker + 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 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 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java --- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@ -3377,8 +3345,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected final RegionBitmap usedSectors; protected final RegionBitmap usedSectors;
+ public final java.util.concurrent.locks.ReentrantLock fileLock = new java.util.concurrent.locks.ReentrantLock(true); // Paper + 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 { public RegionFile(Path path, Path path1, boolean dsync) throws IOException {
this(file.toPath(), directory.toPath(), RegionFileVersion.VERSION_DEFLATE, dsync); this(path, path1, RegionFileVersion.VERSION_DEFLATE, dsync);
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
return (byteCount + 4096 - 1) / 4096; return (byteCount + 4096 - 1) / 4096;
} }
@ -3410,7 +3378,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } // Paper end + } // 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 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 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java --- 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 { @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
this.sync = dsync; this.sync = dsync;
} }
- public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit - public RegionFile getFile(ChunkPos chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
+ // Paper start + // Paper start
+ public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) { + public synchronized RegionFile getRegionFileIfLoaded(ChunkPos chunkcoordintpair) {
@ -3438,7 +3406,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); long i = ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i); RegionFile regionfile = (RegionFile) this.regionCache.getAndMoveToFirst(i);
if (regionfile != null) { if (regionfile != null) {
+ // Paper start + // Paper start
+ if (lock) { + if (lock) {
@ -3451,7 +3419,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable if (this.regionCache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync); RegionFile regionfile1 = new RegionFile(file1, this.folder, this.sync);
this.regionCache.putAndMoveToFirst(i, regionfile1); this.regionCache.putAndMoveToFirst(i, regionfile1);
+ // Paper start + // Paper start
+ if (lock) { + if (lock) {
@ -3474,23 +3442,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit end // CraftBukkit end
+ try { // Paper + try { // Paper
DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos); DataInputStream datainputstream = regionfile.getChunkDataInputStream(pos);
CompoundTag nbttagcompound; CompoundTag nbttagcompound;
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
} }
return nbttagcompound; return nbttagcompound;
+ } finally { // Paper start + } finally { // Paper start
+ regionfile.fileLock.unlock(); + regionfile.fileLock.unlock();
+ } // Paper end + } // Paper end
} }
protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException { protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException {
- RegionFile regionfile = this.getFile(pos, false); // CraftBukkit - RegionFile regionfile = this.getFile(pos, false); // CraftBukkit
+ RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper + RegionFile regionfile = this.getFile(pos, false, true); // CraftBukkit // Paper
+ try { // Paper + try { // Paper
int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper
if (nbt == null) { if (nbt == null) {
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
MinecraftServer.LOGGER.error("Failed to save chunk", laste); MinecraftServer.LOGGER.error("Failed to save chunk", laste);
@ -3500,20 +3468,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ regionfile.fileLock.unlock(); + regionfile.fileLock.unlock();
+ } // Paper end + } // Paper end
} }
- public void close() throws IOException { - public void close() throws IOException {
+ public synchronized void close() throws IOException { // Paper -> synchronized + public synchronized void close() throws IOException { // Paper -> synchronized
ExceptionCollector<IOException> exceptionsuppressor = new ExceptionCollector<>(); ExceptionCollector<IOException> exceptionsuppressor = new ExceptionCollector<>();
ObjectIterator objectiterator = this.regionCache.values().iterator(); ObjectIterator objectiterator = this.regionCache.values().iterator();
@@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable { @@ -0,0 +0,0 @@ public class RegionFileStorage implements AutoCloseable {
exceptionsuppressor.throwIfPresent(); exceptionsuppressor.throwIfPresent();
} }
- public void flush() throws IOException { - public void flush() throws IOException {
+ public synchronized void flush() throws IOException { // Paper - synchronize + public synchronized void flush() throws IOException { // Paper - synchronize
ObjectIterator objectiterator = this.regionCache.values().iterator(); ObjectIterator objectiterator = this.regionCache.values().iterator();
while (objectiterator.hasNext()) { 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 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 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -3522,7 +3490,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelHeightAccessor; @@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelHeightAccessor;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
-public class SectionStorage<R> implements AutoCloseable { -public class SectionStorage<R> implements AutoCloseable {
+public class SectionStorage<R> extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker +public class SectionStorage<R> extends RegionFileStorage implements AutoCloseable { // Paper - nuke IOWorker
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
@ -3534,7 +3502,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final Function<Runnable, Codec<R>> codec; private final Function<Runnable, Codec<R>> codec;
@@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable { @@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable {
protected final LevelHeightAccessor levelHeightAccessor; 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) { 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 + super(directory, dsync); // Paper - nuke IOWorker
this.codec = codecFactory; this.codec = codecFactory;
@ -3545,11 +3513,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.worker = new IOWorker(directory, dsync, directory.getName()); - this.worker = new IOWorker(directory, dsync, directory.getName());
+ // Paper - remove mojang I/O thread + // Paper - remove mojang I/O thread
} }
protected void tick(BooleanSupplier shouldKeepTicking) { protected void tick(BooleanSupplier shouldKeepTicking) {
@@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable { @@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable {
} }
private void readColumn(ChunkPos chunkPos) { private void readColumn(ChunkPos chunkPos) {
- this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos)); - this.readColumn(chunkPos, NbtOps.INSTANCE, this.tryRead(chunkPos));
+ // Paper start - expose function to load in data + // Paper start - expose function to load in data
@ -3559,7 +3527,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.readColumn(chunkPos, NbtOps.INSTANCE, compound); + this.readColumn(chunkPos, NbtOps.INSTANCE, compound);
+ // Paper end - expose function to load in data + // Paper end - expose function to load in data
} }
@Nullable @Nullable
private CompoundTag tryRead(ChunkPos pos) { private CompoundTag tryRead(ChunkPos pos) {
try { try {
@ -3577,9 +3545,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} else { } else {
LOGGER.error("Expected compound tag, got {}", (Object)tag); LOGGER.error("Expected compound tag, got {}", (Object)tag);
} }
} }
+ // Paper start - internal get data function, copied from above + // Paper start - internal get data function, copied from above
+ private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) { + private CompoundTag getDataInternal(ChunkPos chunkcoordintpair) {
+ Dynamic<Tag> dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE); + Dynamic<Tag> dynamic = this.writeColumn(chunkcoordintpair, NbtOps.INSTANCE);
@ -3595,9 +3563,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
private <T> Dynamic<T> writeColumn(ChunkPos chunkPos, DynamicOps<T> dynamicOps) { private <T> Dynamic<T> writeColumn(ChunkPos chunkPos, DynamicOps<T> dynamicOps) {
Map<T, T> map = Maps.newHashMap(); Map<T, T> map = Maps.newHashMap();
@@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable { @@ -0,0 +0,0 @@ public class SectionStorage<R> implements AutoCloseable {
@Override @Override
public void close() throws IOException { public void close() throws IOException {
- this.worker.close(); - this.worker.close();

Datei anzeigen

@ -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;
}