even even even even more work

This commit is contained in:
Spottedleaf 2020-06-25 16:38:24 -07:00
parent e943ece469
commit ec7bd6a7c6
52 changed files with 1064 additions and 1106 deletions

View file

@ -4,3 +4,5 @@
* Mini: "Optimize World Server Map": Figure out how to fill PaperWorldMap, it needs a dim key which doesnt exist anymore? * Mini: "Optimize World Server Map": Figure out how to fill PaperWorldMap, it needs a dim key which doesnt exist anymore?
* Mini: "MC-50319": fix if still works * Mini: "MC-50319": fix if still works
* Mini: I definetly dropped a patch I didnt want to drop, we need to go thru in the end and see if all patches are still in, lol * Mini: I definetly dropped a patch I didnt want to drop, we need to go thru in the end and see if all patches are still in, lol
* Make sure the flat bedrock setting doesn't do anything stupid
* Check DataBits foreach

View file

@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
net.minecraft.server.Block block = iblockdata.getBlock(); net.minecraft.server.Block block = iblockdata.getBlock();
@@ -0,0 +0,0 @@ public class CraftBlock implements Block { @@ -0,0 +0,0 @@ public class CraftBlock implements Block {
// Modelled off EntityHuman#hasBlock // Modelled off EntityHuman#hasBlock
if (block != Blocks.AIR && (item == null || iblockdata.getMaterial().isAlwaysDestroyable() || nmsItem.canDestroySpecialBlock(iblockdata))) { if (block != Blocks.AIR && (item == null || !iblockdata.isAlwaysDestroyable() || nmsItem.canDestroySpecialBlock(iblockdata))) {
net.minecraft.server.Block.dropItems(iblockdata, world.getMinecraftWorld(), position, world.getTileEntity(position), null, nmsItem); net.minecraft.server.Block.dropItems(iblockdata, world.getMinecraftWorld(), position, world.getTileEntity(position), null, nmsItem);
+ if (triggerEffect) world.triggerEffect(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.server.Block.getCombinedId(block.getBlockData())); // Paper + if (triggerEffect) world.triggerEffect(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.server.Block.getCombinedId(block.getBlockData())); // Paper
result = true; result = true;

View file

@ -24,7 +24,7 @@ diff --git a/src/main/java/net/minecraft/server/EntityIronGolem.java b/src/main/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityIronGolem.java --- a/src/main/java/net/minecraft/server/EntityIronGolem.java
+++ b/src/main/java/net/minecraft/server/EntityIronGolem.java +++ b/src/main/java/net/minecraft/server/EntityIronGolem.java
@@ -0,0 +0,0 @@ public class EntityIronGolem extends EntityGolem { @@ -0,0 +0,0 @@ public class EntityIronGolem extends EntityGolem implements IEntityAngerable {
BlockPosition blockposition1 = blockposition.down(); BlockPosition blockposition1 = blockposition.down();
IBlockData iblockdata = iworldreader.getType(blockposition1); IBlockData iblockdata = iworldreader.getType(blockposition1);

View file

@ -22,9 +22,9 @@ diff --git a/src/main/java/net/minecraft/server/MobSpawnerPatrol.java b/src/main
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MobSpawnerPatrol.java --- a/src/main/java/net/minecraft/server/MobSpawnerPatrol.java
+++ b/src/main/java/net/minecraft/server/MobSpawnerPatrol.java +++ b/src/main/java/net/minecraft/server/MobSpawnerPatrol.java
@@ -0,0 +0,0 @@ public class MobSpawnerPatrol { @@ -0,0 +0,0 @@ public class MobSpawnerPatrol implements MobSpawner {
public MobSpawnerPatrol() {}
@Override
public int a(WorldServer worldserver, boolean flag, boolean flag1) { public int a(WorldServer worldserver, boolean flag, boolean flag1) {
+ if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper + if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper
if (!flag) { if (!flag) {

View file

@ -23,14 +23,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/BlockPortal.java --- a/src/main/java/net/minecraft/server/BlockPortal.java
+++ b/src/main/java/net/minecraft/server/BlockPortal.java +++ b/src/main/java/net/minecraft/server/BlockPortal.java
@@ -0,0 +0,0 @@ public class BlockPortal extends Block { @@ -0,0 +0,0 @@ public class BlockPortal extends Block {
Entity entity = EntityTypes.ZOMBIE_PIGMAN.spawnCreature(worldserver, (NBTTagCompound) null, (IChatBaseComponent) null, (EntityHuman) null, blockposition.up(), EnumMobSpawn.STRUCTURE, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL);
if (entity != null) { if (entity != null) {
entity.portalCooldown = entity.getDefaultPortalCooldown();
+ entity.fromNetherPortal = true; // Paper + entity.fromNetherPortal = true; // Paper
+ if (worldserver.paperConfig.nerfNetherPortalPigmen) ((EntityInsentient) entity).aware = false; // Paper + if (worldserver.paperConfig.nerfNetherPortalPigmen) ((EntityInsentient) entity).aware = false; // Paper
entity.portalCooldown = entity.ba();
} }
} }
}
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/Entity.java --- a/src/main/java/net/minecraft/server/Entity.java

View file

@ -1039,6 +1039,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ @@ -0,0 +0,0 @@
package net.minecraft.server; package net.minecraft.server;
import java.util.function.Predicate;
+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info +import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -1065,8 +1066,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.nonEmptyBlockCount = short0; this.nonEmptyBlockCount = short0;
this.tickingBlockCount = short1; this.tickingBlockCount = short1;
this.e = short2; this.e = short2;
- this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::d, GameProfileSerializer::a, Blocks.AIR.getBlockData()); - this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData());
+ this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::d, GameProfileSerializer::a, Blocks.AIR.getBlockData(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data + this.blockIds = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), world == null ? null : world.chunkPacketBlockController.getPredefinedBlockData(world, chunk, this, initializeBlocks), initializeBlocks); // Paper - Anti-Xray - Add predefined block data
} }
public final IBlockData getType(int i, int j, int k) { // Paper public final IBlockData getType(int i, int j, int k) { // Paper
@ -1092,10 +1093,10 @@ diff --git a/src/main/java/net/minecraft/server/DataPaletteBlock.java b/src/main
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/DataPaletteBlock.java --- a/src/main/java/net/minecraft/server/DataPaletteBlock.java
+++ b/src/main/java/net/minecraft/server/DataPaletteBlock.java +++ b/src/main/java/net/minecraft/server/DataPaletteBlock.java
@@ -0,0 +0,0 @@ package net.minecraft.server; @@ -0,0 +0,0 @@
import it.unimi.dsi.fastutil.ints.Int2IntMap; package net.minecraft.server;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap.Entry;
+import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info +import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray - Add chunk packet info
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
@ -1195,9 +1196,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize
this.a(); this.a();
- int i = Math.max(4, MathHelper.d(nbttaglist.size())); - int i = Math.max(4, MathHelper.e(nbttaglist.size()));
+ // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)? + // Paper - Anti-Xray - TODO: Should this.predefinedObjects.length just be added here (faster) or should the contents be compared to calculate the size (less RAM)?
+ int i = Math.max(4, MathHelper.d(nbttaglist.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects + int i = Math.max(4, MathHelper.e(nbttaglist.size() + (this.predefinedObjects == null ? 0 : this.predefinedObjects.length))); // Paper - Anti-Xray - Calculate the size with predefined objects
- if (i != this.i) { - if (i != this.i) {
+ if (true || i != this.i) { // Paper - Anti-Xray - Not initialized yet + if (true || i != this.i) { // Paper - Anti-Xray - Not initialized yet
@ -1221,13 +1222,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet<PacketListenerPlayOut> { @@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet<PacketListenerPlayOut> {
private byte[] f; private byte[] getData() { return this.f; } // Paper - OBFHELPER
private List<NBTTagCompound> g;
private boolean h; private boolean h;
+ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager private boolean i;
- public PacketPlayOutMapChunk() {} - public PacketPlayOutMapChunk() {}
+ // Paper start - Async-Anti-Xray - Set the ready flag to true + // Paper start - Async-Anti-Xray - Set the ready flag to true
+ private volatile boolean ready; // Paper - Async-Anti-Xray - Ready flag for the network manager
+ public PacketPlayOutMapChunk() { + public PacketPlayOutMapChunk() {
+ this.ready = true; + this.ready = true;
+ } + }
@ -1238,7 +1238,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet<PacketListenerPlayOut> { @@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet<PacketListenerPlayOut> {
} }
// Paper end // Paper end
public PacketPlayOutMapChunk(Chunk chunk, int i) { public PacketPlayOutMapChunk(Chunk chunk, int i, boolean flag) {
+ ChunkPacketInfo<IBlockData> chunkPacketInfo = chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i); // Paper - Anti-Xray - Add chunk packet info + ChunkPacketInfo<IBlockData> chunkPacketInfo = chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i); // Paper - Anti-Xray - Add chunk packet info
ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
@ -1247,12 +1247,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
this.f = new byte[this.a(chunk, i)]; this.f = new byte[this.a(chunk, i)];
- this.c = this.a(new PacketDataSerializer(this.j()), chunk, i); - this.c = this.a(new PacketDataSerializer(this.k()), chunk, i);
+ // Paper start - Anti-Xray - Add chunk packet info + // Paper start - Anti-Xray - Add chunk packet info
+ if (chunkPacketInfo != null) { + if (chunkPacketInfo != null) {
+ chunkPacketInfo.setData(this.getData()); + chunkPacketInfo.setData(this.getData());
+ } + }
+ this.c = this.writeChunk(new PacketDataSerializer(this.j()), chunk, i, chunkPacketInfo); + this.c = this.writeChunk(new PacketDataSerializer(this.k()), chunk, i, chunkPacketInfo);
+ // Paper end + // Paper end
this.g = Lists.newArrayList(); this.g = Lists.newArrayList();
iterator = chunk.getTileEntities().entrySet().iterator(); iterator = chunk.getTileEntities().entrySet().iterator();
@ -1306,9 +1306,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
PlayerChunkMap.LOGGER.error("Couldn't load chunk {}", chunkcoordintpair, exception);
} }
this.g(chunkcoordintpair);
- return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a)); - return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a));
+ return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter + return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter
}, this.executor); }, this.executor);
@ -1403,17 +1403,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final co.aikar.timings.WorldTimingsHandler timings; // Paper public final co.aikar.timings.WorldTimingsHandler timings; // Paper
public static BlockPosition lastPhysicsProblem; // Spigot public static BlockPosition lastPhysicsProblem; // Spigot
@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return ((ChunkProviderServer) this.chunkProvider).getChunkAt(x, z, false); return (CraftServer) Bukkit.getServer();
} }
- protected World(WorldData worlddata, DimensionManager dimensionmanager, BiFunction<World, WorldProvider, IChunkProvider> bifunction, GameProfilerFiller gameprofilerfiller, boolean flag, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { - protected World(WorldDataMutable worlddatamutable, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, Supplier<GameProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) {
+ protected World(WorldData worlddata, DimensionManager dimensionmanager, java.util.concurrent.Executor executor, BiFunction<World, WorldProvider, IChunkProvider> bifunction, GameProfilerFiller gameprofilerfiller, boolean flag, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { // Paper - executor + protected World(WorldDataMutable worlddatamutable, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, Supplier<GameProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) {
this.spigotConfig = new org.spigotmc.SpigotWorldConfig( worlddata.getName() ); // Spigot this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig(worlddata.getName(), this.spigotConfig); // Paper this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig((((WorldDataServer)worlddatamutable).getName()), this.spigotConfig); // Paper
+ this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this.paperConfig, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.chunkPacketBlockController = this.paperConfig.antiXray ? new ChunkPacketBlockControllerAntiXray(this.paperConfig, executor) : ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray
this.generator = gen; this.generator = gen;
if (dimensionmanager.world == null) dimensionmanager.world = (WorldServer) this; // Paper
this.world = new CraftWorld((WorldServer) this, gen, env); this.world = new CraftWorld((WorldServer) this, gen, env);
this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit
@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
// CraftBukkit end // CraftBukkit end
@ -1426,15 +1426,15 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// Add env and gen to constructor
public WorldServer(MinecraftServer minecraftserver, Executor executor, WorldNBTStorage worldnbtstorage, WorldData worlddata, DimensionManager dimensionmanager, GameProfilerFiller gameprofilerfiller, WorldLoadListener worldloadlistener, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
- super(worlddata, dimensionmanager, (world, worldprovider) -> {
+ super(worlddata, dimensionmanager, executor, (world, worldprovider) -> { // Paper - pass executor down
// CraftBukkit start
ChunkGenerator<?> chunkGenerator;
// Add env and gen to constructor, WorldData -> WorldDataServer
public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
- super(iworlddataserver, resourcekey, resourcekey1, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env);
+ super(iworlddataserver, resourcekey, resourcekey1, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor
this.pvpMode = minecraftserver.getPVP();
convertable = convertable_conversionsession;
uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile());
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java --- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
@ -1452,8 +1452,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
NBTTagCompound data = new NBTTagCompound(); NBTTagCompound data = new NBTTagCompound();
cs[i].getBlocks().a(data, "Palette", "BlockStates"); cs[i].getBlocks().a(data, "Palette", "BlockStates");
- DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.server.Block.REGISTRY_ID, GameProfileSerializer::d, GameProfileSerializer::a, Blocks.AIR.getBlockData()); // TODO: snapshot whole ChunkSection - DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.server.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData()); // TODO: snapshot whole ChunkSection
+ DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.server.Block.REGISTRY_ID, GameProfileSerializer::d, GameProfileSerializer::a, Blocks.AIR.getBlockData(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally + DataPaletteBlock blockids = new DataPaletteBlock<>(ChunkSection.GLOBAL_PALETTE, net.minecraft.server.Block.REGISTRY_ID, GameProfileSerializer::c, GameProfileSerializer::a, Blocks.AIR.getBlockData(), null, false); // TODO: snapshot whole ChunkSection // Paper - Anti-Xray - Add no predefined block data and don't initialize because it's done in the line below internally
blockids.a(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates")); blockids.a(data.getList("Palette", CraftMagicNumbers.NBT.TAG_COMPOUND), data.getLongArray("BlockStates"));
sectionBlockIDs[i] = blockids; sectionBlockIDs[i] = blockids;

View file

@ -2534,7 +2534,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) { + public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) {
+ ArrayDeque<Runnable> tasksToExecuteOnMain = new ArrayDeque<>(); + ArrayDeque<Runnable> tasksToExecuteOnMain = new ArrayDeque<>();
+ // Paper end + // Paper end
ChunkGenerator<?> chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator();
WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager();
NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level");
@@ -0,0 +0,0 @@ public class ChunkRegionLoader { @@ -0,0 +0,0 @@ public class ChunkRegionLoader {
@ -2560,25 +2560,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (flag) { if (flag) {
if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) { if (nbttagcompound2.hasKeyOfType("BlockLight", 7)) {
- lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("BlockLight"))); - lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.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
+ NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight")); + NibbleArray blockLight = new NibbleArray(nbttagcompound2.getByteArray("BlockLight"));
+ // Note: We move the block light nibble array creation here for perf & in case the compound is modified
+ tasksToExecuteOnMain.add(() -> { + tasksToExecuteOnMain.add(() -> {
+ lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), blockLight); + lightengine.a(EnumSkyBlock.BLOCK, SectionPosition.a(chunkcoordintpair, b0), blockLight, true);
+ }); + });
+ // Paper end + // Paper end - delay this task since we're executing off-main
} }
if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) { if (flag2 && nbttagcompound2.hasKeyOfType("SkyLight", 7)) {
- lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.getByteArray("SkyLight"))); - lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), new NibbleArray(nbttagcompound2.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
+ NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight")); + NibbleArray skyLight = new NibbleArray(nbttagcompound2.getByteArray("SkyLight"));
+ // Note: We move the block light nibble array creation here for perf & in case the compound is modified
+ tasksToExecuteOnMain.add(() -> { + tasksToExecuteOnMain.add(() -> {
+ lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight); + lightengine.a(EnumSkyBlock.SKY, SectionPosition.a(chunkcoordintpair, b0), skyLight, true);
+ }); + });
+ // Paper end + // Paper end - delay this task since we're executing off-main
} }
} }
} }
@ -2597,9 +2595,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- 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 NibbleArray[] blockLight; // null or size of 17 (for indices -1 through 15) + public final NibbleArray[] blockLight; // null or size of 17 (for indices -1 through 15)
@ -2617,9 +2615,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.blockTickList = blockTickList; + this.blockTickList = blockTickList;
+ this.fluidTickList = fluidTickList; + this.fluidTickList = fluidTickList;
+ this.worldTime = worldTime; + this.worldTime = worldTime;
+ } }
+ } }
+
+ // must be called sync + // must be called sync
+ public static AsyncSaveData getAsyncSaveData(WorldServer world, IChunkAccess chunk) { + public static AsyncSaveData getAsyncSaveData(WorldServer world, IChunkAccess chunk) {
+ org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save"); + org.spigotmc.AsyncCatcher.catchOp("preparation of chunk data for async save");
@ -2731,8 +2729,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (ticklist instanceof ProtoChunkTickList) { if (ticklist instanceof ProtoChunkTickList) {
nbttagcompound1.set("ToBeTicked", ((ProtoChunkTickList) ticklist).b()); nbttagcompound1.set("ToBeTicked", ((ProtoChunkTickList) ticklist).b());
} else if (ticklist instanceof TickListChunk) { } else if (ticklist instanceof TickListChunk) {
- nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).a(worldserver.getTime())); nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).b());
+ nbttagcompound1.set("TileTicks", ((TickListChunk) ticklist).a(asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime())); // Paper - async chunk unloading
+ // Paper start - async chunk save for unload + // Paper start - async chunk save for unload
+ } else if (asyncsavedata != null) { + } else if (asyncsavedata != null) {
+ nbttagcompound1.set("TileTicks", asyncsavedata.blockTickList); + nbttagcompound1.set("TileTicks", asyncsavedata.blockTickList);
@ -2748,15 +2745,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (ticklist1 instanceof ProtoChunkTickList) { if (ticklist1 instanceof ProtoChunkTickList) {
nbttagcompound1.set("LiquidsToBeTicked", ((ProtoChunkTickList) ticklist1).b()); nbttagcompound1.set("LiquidsToBeTicked", ((ProtoChunkTickList) ticklist1).b());
} else if (ticklist1 instanceof TickListChunk) { } else if (ticklist1 instanceof TickListChunk) {
- nbttagcompound1.set("LiquidTicks", ((TickListChunk) ticklist1).a(worldserver.getTime())); nbttagcompound1.set("LiquidTicks", ((TickListChunk) ticklist1).b());
+ nbttagcompound1.set("LiquidTicks", ((TickListChunk) ticklist1).a(asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime())); // Paper - async chunk unloading
+ // Paper start - async chunk save for unload + // Paper start - async chunk save for unload
+ } else if (asyncsavedata != null) { + } else if (asyncsavedata != null) {
+ nbttagcompound1.set("LiquidTicks", asyncsavedata.fluidTickList); + nbttagcompound1.set("LiquidTicks", asyncsavedata.fluidTickList);
+ // Paper end + // Paper end
} else { } else {
- nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); - nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair));
+ nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData) + nbttagcompound1.set("LiquidTicks", worldserver.getFluidTickList().a(chunkcoordintpair)); // Paper - diff on method change (see getAsyncSaveData)
} }
nbttagcompound1.set("PostProcessing", a(ichunkaccess.l())); nbttagcompound1.set("PostProcessing", a(ichunkaccess.l()));
@ -2824,23 +2820,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.annotation.Nullable; import javax.annotation.Nullable;
-public class IChunkLoader implements AutoCloseable { public class IChunkLoader implements AutoCloseable {
+public class IChunkLoader extends RegionFileCache implements AutoCloseable {
- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER - private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER
+// private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER - nuke IOWorker + // Paper - OBFHELPER - nuke IOWorker
protected final DataFixer b; protected final DataFixer b;
@Nullable @Nullable
- private PersistentStructureLegacy c; - private PersistentStructureLegacy c;
+ private volatile PersistentStructureLegacy c; // Paper - async chunk loading + private volatile PersistentStructureLegacy c; // Paper - async chunk loading
+ +
+ private final Object persistentDataLock = new Object(); // Paper + private final Object persistentDataLock = new Object(); // Paper
+ protected final RegionFileCache regionFileCache;
public IChunkLoader(File file, DataFixer datafixer) { public IChunkLoader(File file, DataFixer datafixer, boolean flag) {
+ super(file); + this.regionFileCache = new RegionFileCache(file, flag); // Paper - nuke IOWorker
this.b = datafixer; this.b = datafixer;
- this.a = new IOWorker(new RegionFileCache(file), "chunk"); - this.a = new IOWorker(file, flag, "chunk");
+// this.a = new IOWorker(new RegionFileCache(file), "chunk"); // Paper - nuke IOWorker + // Paper - nuke IOWorker
} }
// CraftBukkit start // CraftBukkit start
@ -2881,7 +2877,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + synchronized (this.persistentDataLock) { // Paper - Async chunk loading
if (this.c == null) { if (this.c == null) {
this.c = PersistentStructureLegacy.a(dimensionmanager.getType(), (WorldPersistentData) supplier.get()); // CraftBukkit - getType this.c = PersistentStructureLegacy.a(resourcekey, (WorldPersistentData) supplier.get());
} }
nbttagcompound = this.c.a(nbttagcompound); nbttagcompound = this.c.a(nbttagcompound);
@ -2890,49 +2886,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
@@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable { @@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable {
return nbttagcompound.hasKeyOfType("DataVersion", 99) ? nbttagcompound.getInt("DataVersion") : -1;
@Nullable
public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
- return this.a.a(chunkcoordintpair);
+ return this.regionFileCache.read(chunkcoordintpair);
} }
- @Nullable
- public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
- return this.a.a(chunkcoordintpair);
- }
-
- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { - public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) {
- this.a.a(chunkcoordintpair, nbttagcompound); - this.a.a(chunkcoordintpair, nbttagcompound);
+// Paper start - nuke IOWorker
+// @Nullable
+// public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
+// return this.a.a(chunkcoordintpair);
+// }
+//
+ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER + public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER
+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) + public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety)
+ super.write(chunkcoordintpair, nbttagcompound); + this.regionFileCache.write(chunkcoordintpair, nbttagcompound);
if (this.c != null) { if (this.c != null) {
- this.c.a(chunkcoordintpair.pair());
+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + synchronized (this.persistentDataLock) { // Paper - Async chunk loading
+ this.c.a(chunkcoordintpair.pair()); } // Paper - Async chunk loading} this.c.a(chunkcoordintpair.pair());
+ } // Paper - Async chunk loading}
} }
-
} - }
- -
- public void i() { - public void i() {
- this.a.a().join(); - this.a.a().join();
- } }
-
- public void close() throws IOException { public void close() throws IOException {
- this.a.close(); - this.a.close();
- } + this.regionFileCache.close();
+// }
+// public void i() {
+// this.a.a().join();
+// }
+//
+// public void close() throws IOException {
+// this.a.close();
+// }
+// Paper end
} }
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -2948,6 +2929,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return 33 + ChunkStatus.getTicketLevelOffset(status); + return 33 + ChunkStatus.getTicketLevelOffset(status);
+ } + }
} }
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -0,0 +0,0 @@ public class Main {
convertable_conversionsession.a((IRegistryCustom) iregistrycustom_dimension, (SaveData) object);
*/
+ Class.forName("net.minecraft.server.VillagerTrades");// Paper - load this sync so it won't fail later async
final DedicatedServer dedicatedserver = (DedicatedServer) MinecraftServer.a((thread) -> {
DedicatedServer dedicatedserver1 = new DedicatedServer(optionset, datapackconfiguration1, thread, iregistrycustom_dimension, convertable_conversionsession, resourcepackrepository, datapackresources, null, dedicatedserversettings, DataConverterRegistry.a(), minecraftsessionservice, gameprofilerepository, usercache, WorldLoadListenerLogger::new);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java --- a/src/main/java/net/minecraft/server/MinecraftServer.java
@ -2956,18 +2949,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.getUserCache().c(false); // Paper this.getUserCache().c(false); // Paper
} }
// Spigot end // Spigot end
-
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.close(true, true); // Paper + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.close(true, true); // Paper
} }
public String getServerIp() { public String getServerIp() {
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
dedicatedserver.setEraseCache(true);
}
+ Class.forName("net.minecraft.server.VillagerTrades");// Paper - load this sync so it won't fail later async
dedicatedserver.serverThread.setPriority(Thread.NORM_PRIORITY+2); // Paper - boost priority
dedicatedserver.serverThread.start();
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/NextTickListEntry.java --- a/src/main/java/net/minecraft/server/NextTickListEntry.java
@ -3067,7 +3053,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
private final LightEngineThreaded lightEngine; private final LightEngineThreaded lightEngine;
private final IAsyncTaskHandler<Runnable> executor; private final IAsyncTaskHandler<Runnable> executor;
public final ChunkGenerator<?> chunkGenerator; public final ChunkGenerator chunkGenerator;
- private final Supplier<WorldPersistentData> l; - private final Supplier<WorldPersistentData> l;
+ private final Supplier<WorldPersistentData> l; public final Supplier<WorldPersistentData> getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER + private final Supplier<WorldPersistentData> l; public final Supplier<WorldPersistentData> getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER
private final VillagePlace m; private final VillagePlace m;
@ -3083,11 +3069,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private final PlayerMap playerMap; private final PlayerMap playerMap;
public final Int2ObjectMap<PlayerChunkMap.EntityTracker> trackedEntities; public final Int2ObjectMap<PlayerChunkMap.EntityTracker> trackedEntities;
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getWorldProvider().f(), threadedmailbox1, this.p.a(threadedmailbox1, false)); this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getDimensionManager().hasSkyLight(), threadedmailbox1, this.p.a(threadedmailbox1, false));
this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler); this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler);
this.l = supplier; this.l = supplier;
- this.m = new VillagePlace(new File(this.w, "poi"), datafixer); - this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag);
+ this.m = new VillagePlace(new File(this.w, "poi"), datafixer, this.world); // Paper + this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper
this.setViewDistance(i); this.setViewDistance(i);
} }
@ -3240,15 +3226,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.lightEngine.queueUpdate(); this.lightEngine.queueUpdate();
this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null); this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null);
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
} }
+ // Paper start - Async chunk io
+ public NBTTagCompound completeChunkData(NBTTagCompound compound, ChunkCoordIntPair chunkcoordintpair) throws IOException {
+ return compound == null ? null : this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.getWorldPersistentDataSupplier(), compound, chunkcoordintpair, this.world);
+ }
+ // Paper end
+
private CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> f(ChunkCoordIntPair chunkcoordintpair) { private CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> f(ChunkCoordIntPair chunkcoordintpair) {
- return CompletableFuture.supplyAsync(() -> { - return CompletableFuture.supplyAsync(() -> {
+ // Paper start - Async chunk io + // Paper start - Async chunk io
@ -3259,38 +3238,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings - try (Timing ignored2 = this.world.timings.chunkIO.startTimingIfSync()) { // Paper start - timings
- nbttagcompound = this.readChunkData(chunkcoordintpair); - nbttagcompound = this.readChunkData(chunkcoordintpair);
- } // Paper end - } // Paper end
- + // Paper start
+ if (ioThrowable != null) {
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(ioThrowable);
+ }
+ // Paper end
- if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings - if (nbttagcompound != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings
- boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8); - boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8);
+ if (ioThrowable != null) { + if (chunkHolder.protoChunk != null) {try (Timing ignored2 = this.world.timings.chunkLoadLevelTimer.startTimingIfSync()) { // Paper start - timings // Paper - chunk is created async
+ com.destroystokyo.paper.io.IOUtil.rethrow(ioThrowable);
+ }
- if (flag) { - if (flag) {
- ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.m, chunkcoordintpair, nbttagcompound); - ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.m, chunkcoordintpair, nbttagcompound);
+ this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData); + if (true) {
+ chunkHolder.tasks.forEach(Runnable::run); + ProtoChunk protochunk = chunkHolder.protoChunk;
+ // Paper - async load completes this
+ // Paper end
- protochunk.setLastSaved(this.world.getTime());
- return Either.left(protochunk);
- }
-
- PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair);
- }} // Paper
+ // Paper start - This is done async
+ if (chunkHolder.protoChunk != null) {
+ chunkHolder.protoChunk.setLastSaved(this.world.getTime());
+ return Either.left(chunkHolder.protoChunk);
+ }
+ // Paper end
} catch (ReportedException reportedexception) {
Throwable throwable = reportedexception.getCause();
protochunk.setLastSaved(this.world.getTime());
this.a(chunkcoordintpair, protochunk.getChunkStatus().getType());
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
this.g(chunkcoordintpair);
return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray - Add parameter
- }, this.executor); - }, this.executor);
+ // Paper start - Async chunk io + // Paper start - Async chunk io
@ -3321,7 +3288,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
} }
private CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> b(PlayerChunk playerchunk, ChunkStatus chunkstatus) { private void g(ChunkCoordIntPair chunkcoordintpair) {
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
} }
@ -3330,43 +3297,37 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
this.m.a(ichunkaccess.getPos()); this.m.a(ichunkaccess.getPos());
if (!ichunkaccess.isNeedsSaving()) { if (!ichunkaccess.isNeedsSaving()) {
return false; return false;
} else {
- try {
- this.world.checkSession();
- } catch (ExceptionWorldConflict exceptionworldconflict) {
- PlayerChunkMap.LOGGER.error("Couldn't save chunk; already in use by another instance of Minecraft?", exceptionworldconflict);
- com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exceptionworldconflict); // Paper
- return false;
- }
+ // Paper - The save session check is performed on the IO thread
ichunkaccess.setLastSaved(this.world.getTime());
ichunkaccess.setNeedsSaving(false);
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
NBTTagCompound nbttagcompound; ChunkStatus chunkstatus = ichunkaccess.getChunkStatus();
if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) { if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) {
+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper + try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveOverwriteCheck.startTiming()) { // Paper
// Paper start - Optimize save by using status cache if (this.h(chunkcoordintpair)) {
ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkcoordintpair); return false;
if (statusOnDisk != null && statusOnDisk.getType() == ChunkStatus.Type.LEVELCHUNK) {
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
} }
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
if (chunkstatus == ChunkStatus.EMPTY && ichunkaccess.h().values().stream().noneMatch(StructureStart::e)) {
return false;
}
+ } // Paper
} }
+ } // Paper
this.world.getMethodProfiler().c("chunkSave"); this.world.getMethodProfiler().c("chunkSave");
- NBTTagCompound nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess);
+ NBTTagCompound nbttagcompound;
+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper + try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper
nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess); + nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess);
- this.a(chunkcoordintpair, nbttagcompound);
+ } // Paper + } // Paper
+
- this.a(chunkcoordintpair, nbttagcompound);
+ // Paper start - async chunk io + // Paper start - async chunk io
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkcoordintpair.x, chunkcoordintpair.z, + com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkcoordintpair.x, chunkcoordintpair.z,
+ null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY); + null, nbttagcompound, com.destroystokyo.paper.io.PrioritizedTaskQueue.NORMAL_PRIORITY);
+ // Paper end - async chunk io + // Paper end - async chunk io
this.a(chunkcoordintpair, chunkstatus.getType());
return true; return true;
} catch (Exception exception) { } catch (Exception exception) {
PlayerChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception);
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return false; return false;
} }
@ -3374,7 +3335,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } // Paper + } // Paper
} }
protected void setViewDistance(int i) { private boolean h(ChunkCoordIntPair chunkcoordintpair) {
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
} }
} }
@ -3417,14 +3378,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) {
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); - RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos);
+ synchronized (this) { // Paper + synchronized (this) { // Paper
+ RegionFile regionFile = this.getRegionFileIfLoaded(chunkPos); + RegionFile regionFile = this.regionFileCache.getRegionFileIfLoaded(chunkPos);
return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+ } // Paper + } // Paper
} }
public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); - RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true);
+ // Paper start - async chunk save for unload + // Paper start - async chunk save for unload
+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z); + IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z);
+ if (unloadingChunk != null) { + if (unloadingChunk != null) {
@ -3435,20 +3396,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE + NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE
+ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false); + .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false);
- if (!regionFile.chunkExists(chunkPos)) { - if (regionFile == null || !regionFile.chunkExists(chunkPos)) {
- return null; - return null;
+ if (inProgressWrite != null) { + if (inProgressWrite != null) {
+ return ChunkRegionLoader.getStatus(inProgressWrite); + return ChunkRegionLoader.getStatus(inProgressWrite);
} }
+ // Paper end + // Paper end
+ synchronized (this) { // Paper - async io + synchronized (this) { // Paper - async io
+ RegionFile regionFile = this.getFile(chunkPos, false); + RegionFile regionFile = this.regionFileCache.getFile(chunkPos, true);
+
+ if (!regionFile.chunkExists(chunkPos)) {
+ return null;
+ }
- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); - ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) {
+ return null;
+ }
+
+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
- if (status != null) { - if (status != null) {
@ -3470,7 +3431,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); - RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+ synchronized (this) { + synchronized (this) {
+ RegionFile regionFile = this.getFile(chunkPos, false); + RegionFile regionFile = this.regionFileCache.getFile(chunkPos, false);
- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); - regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); + regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
@ -3506,7 +3467,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ synchronized (world.getChunkProvider().playerChunkMap) { + synchronized (world.getChunkProvider().playerChunkMap) {
+ net.minecraft.server.RegionFile file; + net.minecraft.server.RegionFile file;
+ try { + try {
+ file = world.getChunkProvider().playerChunkMap.getFile(chunkPos, false); + file = world.getChunkProvider().playerChunkMap.regionFileCache.getFile(chunkPos, false);
+ } catch (IOException ex) { + } catch (IOException ex) {
+ throw new RuntimeException(ex); + throw new RuntimeException(ex);
+ } + }
@ -3577,9 +3538,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
this.closed = true; // Paper this.closed = true; // Paper
try { try {
this.c(); this.d();
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
} this.dataFile.close();
} }
} }
+ } finally { // Paper start - Prevent regionfiles from being closed during use + } finally { // Paper start - Prevent regionfiles from being closed during use
@ -3633,7 +3594,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} else { } else {
if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable if (this.cache.size() >= com.destroystokyo.paper.PaperConfig.regionFileCacheSize) { // Paper - configurable
@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { @@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable {
RegionFile regionfile1 = new RegionFile(file, this.b); RegionFile regionfile1 = new RegionFile(file, this.b, this.c);
this.cache.putAndMoveToFirst(i, regionfile1); this.cache.putAndMoveToFirst(i, regionfile1);
+ // Paper start + // Paper start
@ -3686,9 +3647,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- 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
ExceptionSuppressor<IOException> exceptionsuppressor = new ExceptionSuppressor<>();
ObjectIterator objectiterator = this.cache.values().iterator(); ObjectIterator objectiterator = this.cache.values().iterator();
while (objectiterator.hasNext()) {
@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { @@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable {
} }
@ -3710,39 +3671,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
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 RegionFileSection<R extends MinecraftSerializable> implements AutoCloseable { -public class RegionFileSection<R> implements AutoCloseable {
+public class RegionFileSection<R extends MinecraftSerializable> extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker +public class RegionFileSection<R> extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
- private final IOWorker b; - private final IOWorker b;
+// private final IOWorker b; + // Paper - nuke IOWorker
private final Long2ObjectMap<Optional<R>> c = new Long2ObjectOpenHashMap(); private final Long2ObjectMap<Optional<R>> c = new Long2ObjectOpenHashMap();
- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); - private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet();
+ protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected + protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected
private final BiFunction<Runnable, Dynamic<?>, R> e; private final Function<Runnable, Codec<R>> e;
private final Function<Runnable, R> f; private final Function<Runnable, R> f;
private final DataFixer g; private final DataFixer g;
private final DataFixTypes h; private final DataFixTypes h;
public RegionFileSection(File file, BiFunction<Runnable, Dynamic<?>, R> bifunction, Function<Runnable, R> function, DataFixer datafixer, DataFixTypes datafixtypes) { public RegionFileSection(File file, Function<Runnable, Codec<R>> function, Function<Runnable, R> function1, DataFixer datafixer, DataFixTypes datafixtypes, boolean flag) {
+ super(file); // Paper - nuke IOWorker + super(file, flag); // Paper - nuke IOWorker
this.e = bifunction; this.e = function;
this.f = function; this.f = function1;
this.g = datafixer; this.g = datafixer;
this.h = datafixtypes; this.h = datafixtypes;
- this.b = new IOWorker(new RegionFileCache(file), file.getName()); - this.b = new IOWorker(file, flag, file.getName());
+// this.b = new IOWorker(new RegionFileCache(file), file.getName()); // Paper - nuke IOWorker + //this.b = new IOWorker(file, flag, file.getName()); // Paper - nuke IOWorker
} }
protected void a(BooleanSupplier booleansupplier) { protected void a(BooleanSupplier booleansupplier) {
- while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) { while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) {
- ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).u(); - ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r();
+ while (!this.d.isEmpty() && booleansupplier.getAsBoolean()) { // Paper - conflict here to avoid obfhelpers + ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).r(); // Paper - conflict here to avoid obfhelpers
+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(this.d.firstLong()).u(); // Paper - conflict here to avoid obfhelpers
this.d(chunkcoordintpair); this.d(chunkcoordintpair);
} }
@@ -0,0 +0,0 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -0,0 +0,0 @@ public class RegionFileSection<R> implements AutoCloseable {
} }
private void b(ChunkCoordIntPair chunkcoordintpair) { private void b(ChunkCoordIntPair chunkcoordintpair) {
@ -3763,7 +3723,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} catch (IOException ioexception) { } catch (IOException ioexception) {
RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception); RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception);
return null; return null;
@@ -0,0 +0,0 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -0,0 +0,0 @@ public class RegionFileSection<R> implements AutoCloseable {
} }
private void d(ChunkCoordIntPair chunkcoordintpair) { private void d(ChunkCoordIntPair chunkcoordintpair) {
@ -3797,19 +3757,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private <T> Dynamic<T> a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops) { private <T> Dynamic<T> a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops) {
Map<T, T> map = Maps.newHashMap(); Map<T, T> map = Maps.newHashMap();
@@ -0,0 +0,0 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -0,0 +0,0 @@ public class RegionFileSection<R> implements AutoCloseable {
public void a(ChunkCoordIntPair chunkcoordintpair) { public void a(ChunkCoordIntPair chunkcoordintpair) {
if (!this.d.isEmpty()) { if (!this.d.isEmpty()) {
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 16; ++i) {
- long j = SectionPosition.a(chunkcoordintpair, i).v(); - long j = SectionPosition.a(chunkcoordintpair, i).s();
+ long j = SectionPosition.a(chunkcoordintpair, i).v(); // Paper - conflict here to avoid obfhelpers + long j = SectionPosition.a(chunkcoordintpair, i).s(); // Paper - conflict here to avoid obfhelpers
- if (this.d.contains(j)) { - if (this.d.contains(j)) {
+ if (this.d.contains(j)) { // Paper - conflict here to avoid obfhelpers + if (this.d.contains(j)) { // Paper - conflict here to avoid obfhelpers
this.d(chunkcoordintpair); this.d(chunkcoordintpair);
return; return;
} }
@@ -0,0 +0,0 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -0,0 +0,0 @@ public class RegionFileSection<R> implements AutoCloseable {
} }
@ -3827,7 +3787,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair) + // This is checking if the data exists, then it builds it later in getDataInternal(ChunkCoordIntPair)
+ if (!this.d.isEmpty()) { + if (!this.d.isEmpty()) {
+ for (int i = 0; i < 16; ++i) { + for (int i = 0; i < 16; ++i) {
+ long j = SectionPosition.a(chunkcoordintpair, i).v(); + long j = SectionPosition.a(chunkcoordintpair, i).s();
+ +
+ if (this.d.contains(j)) { + if (this.d.contains(j)) {
+ return this.getDataInternal(chunkcoordintpair); + return this.getDataInternal(chunkcoordintpair);
@ -3860,14 +3820,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private final WorldServer world; // Paper + private final WorldServer world; // Paper
+ +
public VillagePlace(File file, DataFixer datafixer) { public VillagePlace(File file, DataFixer datafixer, boolean flag) {
+ // Paper start + // Paper start - add world parameter
+ this(file, datafixer, null); + this(file, datafixer, flag, null);
+ } + }
+ public VillagePlace(File file, DataFixer datafixer, WorldServer world) { + public VillagePlace(File file, DataFixer datafixer, boolean flag, WorldServer world) {
+ // Paper end super(file, VillagePlaceSection::a, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK, flag);
super(file, VillagePlaceSection::new, VillagePlaceSection::new, datafixer, DataFixTypes.POI_CHUNK); + this.world = world;
+ this.world = world; // Paper + // Paper end - add world parameter
} }
public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) { public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) {
@ -3882,7 +3842,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } else { + } else {
+ //super.a(booleansupplier); // re-implement below + //super.a(booleansupplier); // re-implement below
+ while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) { + while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) {
+ ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).u(); + ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).r();
+ +
+ NBTTagCompound data; + NBTTagCompound data;
+ try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) { + try (co.aikar.timings.Timing ignored1 = this.world.timings.poiSaveDataSerialization.startTiming()) {
@ -3936,8 +3896,8 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
return new Throwable(entity + " Added to world at " + new java.util.Date()); return this.chunkProvider.getChunkAt(x, z, false);
} }
+ // Paper start - Asynchronous IO + // Paper start - Asynchronous IO
@ -3993,7 +3953,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ RegionFile file; + RegionFile file;
+ +
+ try { + try {
+ file = WorldServer.this.getChunkProvider().playerChunkMap.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false); + file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false);
+ } catch (java.io.IOException ex) { + } catch (java.io.IOException ex) {
+ throw new RuntimeException(ex); + throw new RuntimeException(ex);
+ } + }
@ -4005,7 +3965,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ @Override + @Override
+ public <T> T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function<RegionFile, T> function) { + public <T> T computeForRegionFileIfLoaded(int chunkX, int chunkZ, java.util.function.Function<RegionFile, T> function) {
+ synchronized (WorldServer.this.getChunkProvider().playerChunkMap) { + synchronized (WorldServer.this.getChunkProvider().playerChunkMap) {
+ RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ)); + RegionFile file = WorldServer.this.getChunkProvider().playerChunkMap.regionFileCache.getRegionFileIfLoaded(new ChunkCoordIntPair(chunkX, chunkZ));
+ return function.apply(file); + return function.apply(file);
+ } + }
+ } + }
@ -4013,19 +3973,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; + public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager;
+ // Paper end + // Paper end
+ +
// Add env and gen to constructor // Add env and gen to constructor, WorldData -> WorldDataServer
public WorldServer(MinecraftServer minecraftserver, Executor executor, WorldNBTStorage worldnbtstorage, WorldData worlddata, DimensionManager dimensionmanager, GameProfilerFiller gameprofilerfiller, WorldLoadListener worldloadlistener, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
super(worlddata, dimensionmanager, executor, (world, worldprovider) -> { // Paper - pass executor down super(iworlddataserver, resourcekey, resourcekey1, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.dragonBattle = null;
this.mobSpawnerTrader = this.worldProvider.getDimensionManager().getType() == DimensionManager.OVERWORLD ? new MobSpawnerTrader(this) : null; // CraftBukkit - getType() }
this.getServer().addWorld(this.getWorld()); // CraftBukkit this.getServer().addWorld(this.getWorld()); // CraftBukkit
+ +
+ this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper + this.asyncChunkTaskManager = new com.destroystokyo.paper.io.chunk.ChunkTaskManager(this); // Paper
} }
// CraftBukkit start // CraftBukkit start
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} }
MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> { MCUtil.getSpiralOutChunks(spawn, radiusInBlocks >> 4).forEach(pair -> {
@ -4082,8 +4042,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// fall through to load // fall through to load
// we do this so we do not re-read the chunk data on disk // we do this so we do not re-read the chunk data on disk
@@ -0,0 +0,0 @@ public class CraftWorld implements World { @@ -0,0 +0,0 @@ public class CraftWorld implements World {
public DragonBattle getEnderDragonBattle() {
return new CraftDragonBattle(worldProvider.o()); // PAIL rename getDragonBattle return (getHandle().getDragonBattle() == null) ? null : new CraftDragonBattle(getHandle().getDragonBattle());
} }
+ // Paper start + // Paper start
+ @Override + @Override

View file

@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Fri, 21 Feb 2020 18:44:28 +0000
Subject: [PATCH] Backport fix for MC-167561
diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityWolf.java
+++ b/src/main/java/net/minecraft/server/EntityWolf.java
@@ -0,0 +0,0 @@ public class EntityWolf extends EntityTameableAnimal {
boolean flag = super.a(entityhuman, enumhand);
if (!flag || this.isBaby()) {
- this.goalSit.setSitting(!this.isSitting());
+ //this.goalSit.setSitting(!this.isSitting()); // Paper start - copied from below
+ if (this.i((EntityLiving) entityhuman) && !this.i(itemstack)) {
+ this.goalSit.setSitting(!this.isSitting());
+ this.jumping = false;
+ this.navigation.o();
+ this.setGoalTarget((EntityLiving) null, TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason
+ }
+ // Paper end - copied from below
}
return flag;
@@ -0,0 +0,0 @@ public class EntityWolf extends EntityTameableAnimal {
return true;
}
+ /* Paper start - Move into above
if (this.i((EntityLiving) entityhuman) && !this.i(itemstack)) {
this.goalSit.setSitting(!this.isSitting());
this.jumping = false;
this.navigation.o();
this.setGoalTarget((EntityLiving) null, TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason
}
+ */ // Paper end
} else if (item == Items.BONE && !this.isAngry()) {
if (!entityhuman.abilities.canInstantlyBuild) {
itemstack.subtract(1);

View file

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zach Brown <1254957+zachbr@users.noreply.github.com>
Date: Thu, 6 Feb 2020 19:20:27 -0600
Subject: [PATCH] Be more tolerant of invalid attributes
Prior to this commit, the player would be disconnected if they ever encountered an attribute with a name that did
not match Bukkit's expected vanilla scheme. It appears that datapacks can set whatever attribute name they want,
ignoring vanilla's typical scheme.
In a more perfect world the API would expose some way to interact with these attributes, however Bukkit is not
particularly flexible in this area. Perhaps this is an area for future expansion at a later time.
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeMap.java
@@ -0,0 +0,0 @@ public class CraftAttributeMap implements Attributable {
public static Attribute fromMinecraft(String nms) {
String[] split = nms.split("\\.", 2);
+ // Paper start - Datapacks can set their own attributes that may not match our expectations, ignore them
+ if (split.length != 2) {
+ return null;
+ }
+ // Paper end
+
String generic = split[0];
String descriptor = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, split[1]); // movementSpeed -> MOVEMENT_SPEED
String fin = generic + "_" + descriptor;

View file

@ -34,7 +34,7 @@ diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/n
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityBee.java --- a/src/main/java/net/minecraft/server/EntityBee.java
+++ b/src/main/java/net/minecraft/server/EntityBee.java +++ b/src/main/java/net/minecraft/server/EntityBee.java
@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements EntityBird { @@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
public EntityBee(EntityTypes<? extends EntityBee> entitytypes, World world) { public EntityBee(EntityTypes<? extends EntityBee> entitytypes, World world) {
super(entitytypes, world); super(entitytypes, world);
@ -51,5 +51,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }; + };
+ // Paper end + // Paper end
this.lookController = new EntityBee.j(this); this.lookController = new EntityBee.j(this);
this.a(PathType.DANGER_FIRE, -1.0F);
this.a(PathType.WATER, -1.0F); this.a(PathType.WATER, -1.0F);
this.a(PathType.COCOA, -1.0F);

View file

@ -27,18 +27,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/EntityZombie.java +++ b/src/main/java/net/minecraft/server/EntityZombie.java
@@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster { @@ -0,0 +0,0 @@ public class EntityZombie extends EntityMonster {
@Override @Override
public void b(EntityLiving entityliving) { public void a_(EntityLiving entityliving) {
super.b(entityliving); super.a_(entityliving);
- if ((this.world.getDifficulty() == EnumDifficulty.NORMAL || this.world.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { - if ((this.world.getDifficulty() == EnumDifficulty.NORMAL || this.world.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) {
- if (this.world.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { - if (this.world.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) {
+ // Paper start + // Paper start
+ if (world.paperConfig.zombieVillagerInfectionChance != 0.0 && (world.paperConfig.zombieVillagerInfectionChance != -1.0 || this.world.getDifficulty() == EnumDifficulty.NORMAL || this.world.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) { + if (world.paperConfig.zombieVillagerInfectionChance != 0.0 && (world.paperConfig.zombieVillagerInfectionChance != -1.0 || this.world.getDifficulty() == EnumDifficulty.NORMAL || this.world.getDifficulty() == EnumDifficulty.HARD) && entityliving instanceof EntityVillager) {
+ if (world.paperConfig.zombieVillagerInfectionChance == -1.0 && this.world.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) { + if (world.paperConfig.zombieVillagerInfectionChance == -1.0 && this.world.getDifficulty() != EnumDifficulty.HARD && this.random.nextBoolean()) {
+ return;
+ }
+ if (world.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > world.paperConfig.zombieVillagerInfectionChance) {
return; return;
- } }
+ if (world.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > world.paperConfig.zombieVillagerInfectionChance) {
+ return;
+ } // Paper end + } // Paper end
EntityVillager entityvillager = (EntityVillager) entityliving; EntityVillager entityvillager = (EntityVillager) entityliving;

View file

@ -38,29 +38,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false);
+ } + }
} }
diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java diff --git a/src/main/java/net/minecraft/server/IProjectile.java b/src/main/java/net/minecraft/server/IProjectile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityArrow.java --- a/src/main/java/net/minecraft/server/IProjectile.java
+++ b/src/main/java/net/minecraft/server/EntityArrow.java +++ b/src/main/java/net/minecraft/server/IProjectile.java
@@ -0,0 +0,0 @@ public abstract class EntityArrow extends Entity implements IProjectile { @@ -0,0 +0,0 @@ public abstract class IProjectile extends Entity {
float f7 = MathHelper.cos(f1 * 0.017453292F) * MathHelper.cos(f * 0.017453292F);
this.shoot((double) f5, (double) f6, (double) f7, f3, f4);
- this.setMot(this.getMot().add(entity.getMot().x, entity.onGround ? 0.0D : entity.getMot().y, entity.getMot().z));
+ if (!entity.world.paperConfig.disableRelativeProjectileVelocity) this.setMot(this.getMot().add(entity.getMot().x, entity.onGround ? 0.0D : entity.getMot().y, entity.getMot().z)); // Paper - allow disabling relative velocity
}
@Override
diff --git a/src/main/java/net/minecraft/server/EntityProjectile.java b/src/main/java/net/minecraft/server/EntityProjectile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityProjectile.java
+++ b/src/main/java/net/minecraft/server/EntityProjectile.java
@@ -0,0 +0,0 @@ public abstract class EntityProjectile extends Entity implements IProjectile {
this.shoot((double) f5, (double) f6, (double) f7, f3, f4); this.shoot((double) f5, (double) f6, (double) f7, f3, f4);
Vec3D vec3d = entity.getMot(); Vec3D vec3d = entity.getMot();
- this.setMot(this.getMot().add(vec3d.x, entity.onGround ? 0.0D : vec3d.y, vec3d.z)); - this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z));
+ if (!entity.world.paperConfig.disableRelativeProjectileVelocity) this.setMot(this.getMot().add(vec3d.x, entity.onGround ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity + if (!entity.world.paperConfig.disableRelativeProjectileVelocity) this.setMot(this.getMot().add(vec3d.x, entity.isOnGround() ? 0.0D : vec3d.y, vec3d.z)); // Paper - allow disabling relative velocity
} }
@Override protected void a(MovingObjectPosition movingobjectposition) {

View file

@ -6,41 +6,35 @@ Subject: [PATCH] Do less work if we have a custom Bukkit generator
If the Bukkit generator already has a spawn, use it immediately instead If the Bukkit generator already has a spawn, use it immediately instead
of spending time generating one that we won't use of spending time generating one that we won't use
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
} else if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { } else if (flag1) {
this.worldData.setSpawn(BlockPosition.ZERO.up()); iworlddataserver.setSpawn(BlockPosition.ZERO.up());
} else { } else {
- WorldChunkManager worldchunkmanager = this.getChunkProvider().getChunkGenerator().getWorldChunkManager(); - WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager();
- List<BiomeBase> list = worldchunkmanager.a(); - List<BiomeBase> list = worldchunkmanager.b();
- Random random = new Random(this.getSeed()); - Random random = new Random(worldserver.getSeed());
- BlockPosition blockposition = worldchunkmanager.a(0, this.getSeaLevel(), 0, 256, list, random); - BlockPosition blockposition = worldchunkmanager.a(0, worldserver.getSeaLevel(), 0, 256, list, random);
- ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); - ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition);
- + // Paper start - moved down
+// Paper start - moved down
+// WorldChunkManager worldchunkmanager = this.getChunkProvider().getChunkGenerator().getWorldChunkManager();
+// List<BiomeBase> list = worldchunkmanager.a();
+// Random random = new Random(this.getSeed());
+// BlockPosition blockposition = worldchunkmanager.a(0, this.getSeaLevel(), 0, 256, list, random);
+// ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition);
+// Paper end
// CraftBukkit start // CraftBukkit start
if (this.generator != null) { if (worldserver.generator != null) {
Random rand = new Random(this.getSeed()); Random rand = new Random(worldserver.getSeed());
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
}
} }
// CraftBukkit end // CraftBukkit end
+ // Paper start - if the generator created a spawn for us, then there is no need for us to also create a spawn -
+ // Paper start - this is useless if craftbukkit returns early + // only do it if the generator did not
+ WorldChunkManager worldchunkmanager = this.getChunkProvider().getChunkGenerator().getWorldChunkManager(); + WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager();
+ List<BiomeBase> list = worldchunkmanager.a(); + List<BiomeBase> list = worldchunkmanager.b();
+ Random random = new Random(this.getSeed()); + Random random = new Random(worldserver.getSeed());
+ BlockPosition blockposition = worldchunkmanager.a(0, this.getSeaLevel(), 0, 256, list, random); + BlockPosition blockposition = worldchunkmanager.a(0, worldserver.getSeaLevel(), 0, 256, list, random);
+ ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition); + ChunkCoordIntPair chunkcoordintpair = blockposition == null ? new ChunkCoordIntPair(0, 0) : new ChunkCoordIntPair(blockposition);
+ // Paper end + // Paper end
if (blockposition == null) { if (blockposition == null) {
WorldServer.LOGGER.warn("Unable to find spawn biome"); MinecraftServer.LOGGER.warn("Unable to find spawn biome");
}

View file

@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/n
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityBee.java --- a/src/main/java/net/minecraft/server/EntityBee.java
+++ b/src/main/java/net/minecraft/server/EntityBee.java +++ b/src/main/java/net/minecraft/server/EntityBee.java
@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements EntityBird { @@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
if (this.hivePos == null) { if (this.hivePos == null) {
return false; return false;
} else { } else {
@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
TileEntity tileentity = this.world.getTileEntity(this.hivePos); TileEntity tileentity = this.world.getTileEntity(this.hivePos);
return tileentity instanceof TileEntityBeehive && ((TileEntityBeehive) tileentity).d(); return tileentity instanceof TileEntityBeehive && ((TileEntityBeehive) tileentity).d();
@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements EntityBird { @@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
} }
private boolean i(BlockPosition blockposition) { private boolean i(BlockPosition blockposition) {
@ -24,15 +24,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
TileEntity tileentity = this.world.getTileEntity(blockposition); TileEntity tileentity = this.world.getTileEntity(blockposition);
return tileentity instanceof TileEntityBeehive ? !((TileEntityBeehive) tileentity).isFull() : false; return tileentity instanceof TileEntityBeehive ? !((TileEntityBeehive) tileentity).isFull() : false;
@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements EntityBird { @@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
@Override @Override
public boolean g() { public boolean g() {
if (EntityBee.this.hasHivePos() && EntityBee.this.eI() && EntityBee.this.hivePos.a((IPosition) EntityBee.this.getPositionVector(), 2.0D)) { if (EntityBee.this.hasHivePos() && EntityBee.this.fe() && EntityBee.this.hivePos.a((IPosition) EntityBee.this.getPositionVector(), 2.0D)) {
+ if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return false; // Paper + if (!EntityBee.this.world.isLoadedAndInBounds(EntityBee.this.hivePos)) return false; // Paper
TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos); TileEntity tileentity = EntityBee.this.world.getTileEntity(EntityBee.this.hivePos);
if (tileentity instanceof TileEntityBeehive) { if (tileentity instanceof TileEntityBeehive) {
@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements EntityBird { @@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
@Override @Override
public void c() { public void c() {

View file

@ -21,13 +21,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} else { } else {
BlockPosition blockposition1 = blockposition.shift((EnumDirection) function1.apply(iblockdata)); BlockPosition blockposition1 = blockposition.shift((EnumDirection) function1.apply(iblockdata));
- IBlockData iblockdata1 = generatoraccess.getType(blockposition1); - IBlockData iblockdata1 = generatoraccess.getType(blockposition1);
- + // Paper start
+ // Paper start - don't load chunks if the other side of the chest is in unloaded chunk
+ IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1); + IBlockData iblockdata1 = generatoraccess.getTypeIfLoaded(blockposition1);
+ if (iblockdata1 == null) { + if (iblockdata1 == null) {
+ return new DoubleBlockFinder.Result.Single<>(s0); + return new DoubleBlockFinder.Result.Single<>(s0);
+ } + }
+ // Paper end + // Paper end
if (iblockdata1.getBlock() == iblockdata.getBlock()) {
DoubleBlockFinder.BlockType doubleblockfinder_blocktype1 = (DoubleBlockFinder.BlockType) function.apply(iblockdata1);
if (iblockdata1.a(iblockdata.getBlock())) {
DoubleBlockFinder.BlockType doubleblockfinder_blocktype1 = (DoubleBlockFinder.BlockType) function.apply(iblockdata1);

View file

@ -26,15 +26,15 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
Entity entity2;
try (co.aikar.timings.Timing ignored = this.timings.newEntities.startTiming()) { // Paper - timings while ((entity2 = (Entity) this.entitiesToAdd.poll()) != null) {
while ((entity = (Entity) this.entitiesToAdd.poll()) != null) { + if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers
+ if (!entity.isQueuedForRegister) continue; // Paper - ignore cancelled registers this.registerEntity(entity2);
this.registerEntity(entity);
} }
} // Paper - timings
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public void unregisterEntity(Entity entity) { public void unregisterEntity(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot
@ -54,7 +54,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// Spigot start // Spigot start
if ( entity instanceof EntityHuman ) if ( entity instanceof EntityHuman )
{ {
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
private void registerEntity(Entity entity) { private void registerEntity(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
@ -76,4 +76,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ entity.isQueuedForRegister = false; // Paper + entity.isQueuedForRegister = false; // Paper
this.entitiesById.put(entity.getId(), entity); this.entitiesById.put(entity.getId(), entity);
if (entity instanceof EntityEnderDragon) { if (entity instanceof EntityEnderDragon) {
EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eo(); EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eK();

View file

@ -17,13 +17,13 @@ diff --git a/src/main/java/net/minecraft/server/BehaviorController.java b/src/ma
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/BehaviorController.java --- a/src/main/java/net/minecraft/server/BehaviorController.java
+++ b/src/main/java/net/minecraft/server/BehaviorController.java +++ b/src/main/java/net/minecraft/server/BehaviorController.java
@@ -0,0 +0,0 @@ public class BehaviorController<E extends EntityLiving> implements MinecraftSeri @@ -0,0 +0,0 @@ public class BehaviorController<E extends EntityLiving> {
});
} }
+ public boolean hasActivity(Activity activity) { return c(activity); } // Paper - OBFHELPER + public boolean hasActivity(Activity activity) { return c(activity); } // Paper - OBFHELPER
public boolean c(Activity activity) { public boolean c(Activity activity) {
return this.g.contains(activity); return this.j.contains(activity);
} }
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -46,7 +46,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (vec3d.equals(Vec3D.a)) { if (vec3d.equals(Vec3D.a)) {
return; return;
@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
this.y = Vec3D.a; this.x = Vec3D.a;
this.setMot(Vec3D.a); this.setMot(Vec3D.a);
} }
+ // Paper start - ignore movement changes while inactive. + // Paper start - ignore movement changes while inactive.
@ -58,13 +58,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
vec3d = this.a(vec3d, enummovetype); vec3d = this.a(vec3d, enummovetype);
Vec3D vec3d1 = this.e(vec3d); Vec3D vec3d1 = this.f(vec3d);
@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
return this.am; return this.al;
} }
+ public boolean isPushedByWater() { return this.bM(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! + public boolean isPushedByWater() { return this.bU(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it!
public boolean bM() { public boolean bU() {
// Paper start // Paper start
return this.pushedByWater(); return this.pushedByWater();
diff --git a/src/main/java/net/minecraft/server/EntityCreature.java b/src/main/java/net/minecraft/server/EntityCreature.java diff --git a/src/main/java/net/minecraft/server/EntityCreature.java b/src/main/java/net/minecraft/server/EntityCreature.java
@ -88,10 +88,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public long lootTableSeed; public long lootTableSeed;
@Nullable @Nullable
- private Entity leashHolder; - private Entity leashHolder;
+ public Entity leashHolder; // Paper + public Entity leashHolder; // Paper - private -> public
private int bF; private int bE;
@Nullable @Nullable
private NBTTagCompound bG; private NBTTagCompound bF;
@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { @@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving {
return this.lookController; return this.lookController;
} }
@ -115,25 +115,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/EntityLiving.java --- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
protected float aV; protected float aU;
protected int aW; protected int getKillCount() { return this.aW; } // Paper - OBFHELPER protected int aV; protected int getKillCount() { return this.aV; } // Paper - OBFHELPER
public float lastDamage; public float lastDamage;
- protected boolean jumping; - protected boolean jumping;
+ public boolean jumping; // Paper + public boolean jumping; // Paper protected -> public
public float aY;
public float aZ; public float aZ;
public float ba; public float ba;
public float bb;
diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityLlama.java --- a/src/main/java/net/minecraft/server/EntityLlama.java
+++ b/src/main/java/net/minecraft/server/EntityLlama.java +++ b/src/main/java/net/minecraft/server/EntityLlama.java
@@ -0,0 +0,0 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn @@ -0,0 +0,0 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn
return this.bK != null; return this.bJ != null;
} }
+ public boolean inCaravan() { return this.fd(); } // Paper - OBFHELPER + public final boolean inCaravan() { return this.fD(); } // Paper - OBFHELPER
public boolean fd() { public boolean fD() {
return this.bJ != null; return this.bI != null;
} }
diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -148,14 +148,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper start + // Paper start
+ if (this.getUnhappy() > 0) { + if (this.getUnhappy() > 0) {
+ this.setUnhappy(this.getUnhappy() - 1); + this.setUnhappy(this.getUnhappy() - 1);
+ } }
+ if (this.doAITick()) { + if (this.doAITick()) {
+ if (world.spigotConfig.tickInactiveVillagers) { + if (world.spigotConfig.tickInactiveVillagers) {
+ this.mobTick(); + this.mobTick();
+ } else { + } else {
+ this.mobTick(true); + this.mobTick(true);
+ } + }
} + }
+ doReputationTick(); + doReputationTick();
+ // Paper end + // Paper end
+ +
@ -163,30 +163,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
// Spigot End // Spigot End
- @Override @Override
- protected void mobTick() { - protected void mobTick() {
+ @Override // Paper start - tick trades while inactive
+ protected void mobTick() { mobTick(false); } + protected void mobTick() { mobTick(false); }
+ protected void mobTick(boolean inactive) { + protected void mobTick(boolean inactive) {
+ // Paper end this.world.getMethodProfiler().enter("villagerBrain");
this.world.getMethodProfiler().enter("brain");
- this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error - this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error
- this.world.getMethodProfiler().exit();
+ if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper + if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
this.world.getMethodProfiler().exit(); if (this.bM) {
if (!this.et() && this.bB > 0) { this.bM = false;
--this.bB; }
@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation @@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
this.bD = null; this.bC = null;
} }
- if (!this.isNoAI() && this.random.nextInt(100) == 0) { - if (!this.isNoAI() && this.random.nextInt(100) == 0) {
+ if (!inactive && !this.isNoAI() && this.random.nextInt(100) == 0) { // Paper + if (!inactive && !this.isNoAI() && this.random.nextInt(100) == 0) { // Paper
Raid raid = ((WorldServer) this.world).c_(new BlockPosition(this)); Raid raid = ((WorldServer) this.world).c_(this.getChunkCoordinates());
if (raid != null && raid.v() && !raid.a()) { if (raid != null && raid.v() && !raid.a()) {
@@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation @@ -0,0 +0,0 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.et()) { if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.eO()) {
this.ey(); this.eT();
} }
+ if (inactive) return; // Paper + if (inactive) return; // Paper
@ -196,8 +195,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
} }
+ private void doReputationTick() { fa(); } // Paper - OBFHELPER + private void doReputationTick() { fv(); } // Paper - OBFHELPER
private void fa() { private void fv() {
long i = this.world.getTime(); long i = this.world.getTime();
diff --git a/src/main/java/net/minecraft/server/EntityVillagerAbstract.java b/src/main/java/net/minecraft/server/EntityVillagerAbstract.java diff --git a/src/main/java/net/minecraft/server/EntityVillagerAbstract.java b/src/main/java/net/minecraft/server/EntityVillagerAbstract.java
@ -208,14 +207,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return super.prepare(generatoraccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound); return super.prepare(generatoraccess, difficultydamagescaler, enummobspawn, (GroupDataEntity) groupdataentity, nbttagcompound);
} }
+ public final int getUnhappy() { return eq(); } // Paper - OBFHELPER + public final int getUnhappy() { return eL(); } // Paper - OBFHELPER
public int eq() { public int eL() {
return (Integer) this.datawatcher.get(EntityVillagerAbstract.bx); return (Integer) this.datawatcher.get(EntityVillagerAbstract.bw);
} }
+ public final void setUnhappy(int i) { s(i); } // Paper - OBFHELPER + public final void setUnhappy(int i) { s(i); } // Paper - OBFHELPER
public void s(int i) { public void s(int i) {
this.datawatcher.set(EntityVillagerAbstract.bx, i); this.datawatcher.set(EntityVillagerAbstract.bw, i);
} }
diff --git a/src/main/java/net/minecraft/server/PathfinderGoal.java b/src/main/java/net/minecraft/server/PathfinderGoal.java diff --git a/src/main/java/net/minecraft/server/PathfinderGoal.java b/src/main/java/net/minecraft/server/PathfinderGoal.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -267,7 +266,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i, int j) { public PathfinderGoalGotoTarget(EntityCreature entitycreature, double d0, int i, int j) {
this.e = BlockPosition.ZERO; this.e = BlockPosition.ZERO;
@@ -0,0 +0,0 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal { @@ -0,0 +0,0 @@ public abstract class PathfinderGoalGotoTarget extends PathfinderGoal {
blockposition_mutableblockposition.g(blockposition).e(i1, k - 1, j1); blockposition_mutableblockposition.a((BaseBlockPosition) blockposition, i1, k - 1, j1);
if (this.a.a((BlockPosition) blockposition_mutableblockposition) && this.a(this.a.world, blockposition_mutableblockposition)) { if (this.a.a((BlockPosition) blockposition_mutableblockposition) && this.a(this.a.world, blockposition_mutableblockposition)) {
this.e = blockposition_mutableblockposition; this.e = blockposition_mutableblockposition;
+ setTarget(blockposition_mutableblockposition.immutableCopy()); // Paper + setTarget(blockposition_mutableblockposition.immutableCopy()); // Paper
@ -283,15 +282,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}; };
private final Map<PathfinderGoal.Type, PathfinderGoalWrapped> c = new EnumMap(PathfinderGoal.Type.class); private final Map<PathfinderGoal.Type, PathfinderGoalWrapped> c = new EnumMap(PathfinderGoal.Type.class);
- private final Set<PathfinderGoalWrapped> d = Sets.newLinkedHashSet(); - private final Set<PathfinderGoalWrapped> d = Sets.newLinkedHashSet();
+ private final Set<PathfinderGoalWrapped> d = Sets.newLinkedHashSet();private Set<PathfinderGoalWrapped> getTasks() { return d; }// Paper - OBFHELPER + private final Set<PathfinderGoalWrapped> d = Sets.newLinkedHashSet(); private Set<PathfinderGoalWrapped> getTasks() { return d; }// Paper - OBFHELPER
private final GameProfilerFiller e; private final Supplier<GameProfilerFiller> e;
private final EnumSet<PathfinderGoal.Type> f = EnumSet.noneOf(PathfinderGoal.Type.class); private final EnumSet<PathfinderGoal.Type> f = EnumSet.noneOf(PathfinderGoal.Type.class);
- private int g = 3; - private int g = 3;
+ private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER + private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER
+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO
public PathfinderGoalSelector(GameProfilerFiller gameprofilerfiller) { public PathfinderGoalSelector(Supplier<GameProfilerFiller> supplier) {
this.e = gameprofilerfiller; this.e = supplier;
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector { @@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
this.d.add(new PathfinderGoalWrapped(i, pathfindergoal)); this.d.add(new PathfinderGoalWrapped(i, pathfindergoal));
} }
@ -593,8 +592,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
if ( !( entity instanceof EntityArrow ) ) if ( !( entity instanceof EntityArrow ) )
{ {
- if ( !entity.onGround || !entity.passengers.isEmpty() || entity.isPassenger() ) - if ( !entity.isOnGround() || !entity.passengers.isEmpty() || entity.isPassenger() )
+ if ( (!entity.onGround && !(entity instanceof EntityFlying)) || !entity.passengers.isEmpty() || entity.isPassenger() ) // Paper + if ( (!entity.isOnGround() && !(entity instanceof EntityFlying)) || !entity.passengers.isEmpty() || entity.isPassenger() )
{ {
- return true; - return true;
+ return 10; // Paper + return 10; // Paper

View file

@ -9,9 +9,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/EntityLiving.java --- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
} else if (this.aH()) { } else if (this.aN() && (!this.onGround || d7 > d8)) {
this.c(TagsFluid.LAVA); this.c((Tag) TagsFluid.LAVA);
} else if ((this.onGround || this.N > 0.0D && this.N <= 0.4D) && this.jumpTicks == 0) { } else if ((this.onGround || flag && d7 <= d8) && this.jumpTicks == 0) {
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper
this.jump(); this.jump();
this.jumpTicks = 10; this.jumpTicks = 10;
@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class EntityPanda extends EntityAnimal { @@ -0,0 +0,0 @@ public class EntityPanda extends EntityAnimal {
EntityPanda entitypanda = (EntityPanda) iterator.next(); EntityPanda entitypanda = (EntityPanda) iterator.next();
if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.eL()) { if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.fi()) {
+ if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper + if (new com.destroystokyo.paper.event.entity.EntityJumpEvent(getBukkitLivingEntity()).callEvent()) { // Paper
entitypanda.jump(); entitypanda.jump();
+ } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop + } else { this.setJumping(false); } // Paper - setJumping(false) stops a potential loop

View file

@ -11,10 +11,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/EntityLiving.java --- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
return this.getEquipment(EnumItemSlot.OFFHAND); return predicate.test(this.getItemInMainHand().getItem()) || predicate.test(this.getItemInOffHand().getItem());
} }
+ public ItemStack getItemInHand(EnumHand enumhand) { return this.b(enumhand); } // Paper - OBFHELPER + public final ItemStack getItemInHand(EnumHand enumhand) { return this.b(enumhand); } // Paper - OBFHELPER
public ItemStack b(EnumHand enumhand) { public ItemStack b(EnumHand enumhand) {
if (enumhand == EnumHand.MAIN_HAND) { if (enumhand == EnumHand.MAIN_HAND) {
return this.getEquipment(EnumItemSlot.MAINHAND); return this.getEquipment(EnumItemSlot.MAINHAND);
@ -23,13 +23,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/PlayerConnection.java --- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { @@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn {
if (cancelled) {
this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524
} else { return;
+ // Paper start
+ itemstack = this.player.getItemInHand(enumhand);
+ if (itemstack.isEmpty()) return;
+ // Paper end
this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand);
} }
// CraftBukkit end + // Paper start
+ itemstack = this.player.getItemInHand(enumhand);
+ if (itemstack.isEmpty()) return;
+ // Paper end
EnumInteractionResult enuminteractionresult = this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand);
if (enuminteractionresult.b()) {

View file

@ -142,14 +142,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { - private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException {
+ public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public + public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public
NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); NBTTagCompound nbttagcompound = this.read(chunkcoordintpair);
- return nbttagcompound == null ? null : this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit
+ // Paper start - Cache chunk status on disk + // Paper start - Cache chunk status on disk
+ if (nbttagcompound == null) { + if (nbttagcompound == null) {
+ return null; + return null;
+ } + }
+ +
+ nbttagcompound = this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit + nbttagcompound = this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit
+ if (nbttagcompound == null) { + if (nbttagcompound == null) {
+ return null; + return null;
+ } + }
@ -165,12 +163,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos); + RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos);
+ +
+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
} + }
+ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+ +
+ if (!regionFile.chunkExists(chunkPos)) { + public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, true);
+
+ if (regionFile == null || !regionFile.chunkExists(chunkPos)) {
+ return null; + return null;
+ } + }
+ +
@ -181,10 +179,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ this.readChunkData(chunkPos); + this.readChunkData(chunkPos);
+
- return nbttagcompound == null ? null : this.getChunkData(this.world.getTypeKey(), this.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit
+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); + return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+ } }
+
+ public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { + public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); + RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+ +
@ -232,8 +231,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // Paper end
+ +
public RegionFile(File file, File file1) throws IOException { public RegionFile(File file, File file1, boolean flag) throws IOException {
this(file.toPath(), file1.toPath(), RegionFileCompression.b); this(file.toPath(), file1.toPath(), RegionFileCompression.b, flag);
} }
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { @@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
return this.getOffset(chunkcoordintpair) != 0; return this.getOffset(chunkcoordintpair) != 0;
@ -247,14 +246,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void close() throws IOException { public void close() throws IOException {
+ this.closed = true; // Paper + this.closed = true; // Paper
try { try {
this.c(); this.d();
} finally { } finally {
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/RegionFileCache.java --- a/src/main/java/net/minecraft/server/RegionFileCache.java
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java +++ b/src/main/java/net/minecraft/server/RegionFileCache.java
@@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable { @@ -0,0 +0,0 @@ public final class RegionFileCache implements AutoCloseable {
this.b = file; this.c = flag;
} }
- private RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit - private RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 22 Jan 2020 21:00:21 +0000
Subject: [PATCH] Fix comparator behavior for EntityPhanton goal
diff --git a/src/main/java/net/minecraft/server/EntityPhantom.java b/src/main/java/net/minecraft/server/EntityPhantom.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityPhantom.java
+++ b/src/main/java/net/minecraft/server/EntityPhantom.java
@@ -0,0 +0,0 @@ public class EntityPhantom extends EntityFlying implements IMonster {
if (!list.isEmpty()) {
list.sort((entityhuman, entityhuman1) -> {
- return entityhuman.locY() > entityhuman1.locY() ? -1 : 1;
+ return Double.compare(entityhuman1.locY(), entityhuman.locY()); // Paper
});
Iterator iterator = list.iterator();

View file

@ -19,12 +19,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
if (blockposition == null) { // CraftBukkit if (blockposition == null) { // CraftBukkit
if (dimensionmanager1.getType() == DimensionManager.THE_END && dimensionmanager == DimensionManager.OVERWORLD) { // CraftBukkit if (this.world.getDimensionKey() == World.THE_END && worldserver.getDimensionKey() == World.OVERWORLD) {
+ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate + // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate
+ if (!worldserver1.isLoaded(worldserver1.getSpawn())) { + this.world.getChunkAtWorldCoords(this.world.getSpawn());
+ worldserver1.getChunkAtWorldCoords(worldserver1.getSpawn());
+ }
+ // Paper end + // Paper end
// CraftBukkit start // CraftBukkit start
EntityPortalEvent event = CraftEventFactory.callEntityPortalEvent(this, worldserver1, worldserver1.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver1.getSpawn()), 0); EntityPortalEvent event = CraftEventFactory.callEntityPortalEvent(this, worldserver, worldserver.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver.getSpawn()), 0);
if (event == null) { if (event == null) {

View file

@ -16,8 +16,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
- EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack, d3, d4, d5, true); - EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true);
+ EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack1, d3, d4, d5, true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed + EntityFireworks entityfireworks = new EntityFireworks(isourceblock.getWorld(), itemstack1, isourceblock.getX(), isourceblock.getY(), isourceblock.getX(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed
entityfireworks.shoot(d0, d1, d2, 0.5F, 1.0F); IDispenseBehavior.a(isourceblock, entityfireworks, enumdirection);
isourceblock.getWorld().addEntity(entityfireworks); entityfireworks.shoot((double) enumdirection.getAdjacentX(), (double) enumdirection.getAdjacentY(), (double) enumdirection.getAdjacentZ(), 0.5F, 1.0F);

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 15 Dec 2019 19:41:28 +0000
Subject: [PATCH] Fix spawn radius being treated as 0
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
public final BlockPosition getSpawnPoint(WorldServer worldserver) {
BlockPosition blockposition = worldserver.getSpawn();
- if (worldserver.worldProvider.g() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) {
+ if (worldserver.worldProvider.f() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) { // Paper
int i = Math.max(0, this.server.a(worldserver));
int j = MathHelper.floor(worldserver.getWorldBorder().b((double) blockposition.getX(), (double) blockposition.getZ()));

View file

@ -18,7 +18,7 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} }
private void removeEntityFromChunk(Entity entity) { private void removeEntityFromChunk(Entity entity) {

View file

@ -22,32 +22,68 @@ diff --git a/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java b/sr
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java --- a/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java
+++ b/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java +++ b/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java
@@ -0,0 +0,0 @@ public abstract class ChunkGeneratorAbstract<T extends GeneratorSettingsDefault> @@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
int i = ichunkaccess.getPos().d(); int i = ichunkaccess.getPos().d();
int j = ichunkaccess.getPos().e(); int j = ichunkaccess.getPos().e();
T t0 = this.getSettings(); - int k = this.h.f();
- int k = t0.u(); - int l = this.x - 1 - this.h.e();
- int l = t0.t(); + int k = this.h.f(); final int floorHeight = k; // Paper
+ int k = t0.u(); final int floorHeight = k; // Paper + int l = this.x - 1 - this.h.e(); final int roofHeight = l; // Paper
+ int l = t0.t(); final int roofHeight = l; // Paper boolean flag = true;
Iterator iterator = BlockPosition.b(i, 0, j, i + 15, 0, j + 15).iterator(); boolean flag1 = l + 4 >= 0 && l < this.x;
boolean flag2 = k + 4 >= 0 && k < this.x;
@@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
while (iterator.hasNext()) { if (flag1) {
@@ -0,0 +0,0 @@ public abstract class ChunkGeneratorAbstract<T extends GeneratorSettingsDefault> for (i1 = 0; i1 < 5; ++i1) {
- if (i1 <= random.nextInt(5)) {
if (l > 0) { + if (i1 <= (ichunkaccess.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof
for (i1 = l; i1 >= l - 4; --i1) { ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false);
- if (i1 >= l - random.nextInt(5)) { }
+ if (i1 >= (getWorld().paperConfig.generateFlatBedrock ? roofHeight : l - random.nextInt(5))) { // Paper - Configurable flat bedrock roof
ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false);
} }
} @@ -0,0 +0,0 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
@@ -0,0 +0,0 @@ public abstract class ChunkGeneratorAbstract<T extends GeneratorSettingsDefault>
if (k < 256) { if (flag2) {
for (i1 = k + 4; i1 >= k; --i1) { for (i1 = 4; i1 >= 0; --i1) {
- if (i1 <= k + random.nextInt(5)) { - if (i1 <= random.nextInt(5)) {
+ if (i1 <= (getWorld().paperConfig.generateFlatBedrock ? floorHeight : k + random.nextInt(5))) { // Paper - Configurable flat bedrock floor + if (i1 <= (ichunkaccess.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor
ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false); ichunkaccess.setType(blockposition_mutableblockposition.d(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.getBlockData(), false);
}
} }
} diff --git a/src/main/java/net/minecraft/server/IChunkAccess.java b/src/main/java/net/minecraft/server/IChunkAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/IChunkAccess.java
+++ b/src/main/java/net/minecraft/server/IChunkAccess.java
@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager;
public interface IChunkAccess extends IBlockAccess, IStructureAccess {
+ // Paper start
+ default boolean generateFlatBedrock() {
+ if (this instanceof ProtoChunk) {
+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock;
+ } else if (this instanceof Chunk) {
+ return ((Chunk)this).world.paperConfig.generateFlatBedrock;
+ } else {
+ return false;
+ }
+ }
+ // Paper end
+
IBlockData getType(final int x, final int y, final int z); // Paper
@Nullable
IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag);
diff --git a/src/main/java/net/minecraft/server/ProtoChunk.java b/src/main/java/net/minecraft/server/ProtoChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/ProtoChunk.java
+++ b/src/main/java/net/minecraft/server/ProtoChunk.java
@@ -0,0 +0,0 @@ public class ProtoChunk implements IChunkAccess {
private long s;
private final Map<WorldGenStage.Features, BitSet> t;
private volatile boolean u;
- private final World world; // Paper - Anti-Xray - Add world
+ final World world; // Paper - Anti-Xray - Add world // Paper - private -> default
// Paper start - Anti-Xray - Add world
@Deprecated public ProtoChunk(ChunkCoordIntPair chunkcoordintpair, ChunkConverter chunkconverter) { this(chunkcoordintpair, chunkconverter, null); } // Notice for updates: Please make sure this constructor isn't used anywhere

View file

@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ChunkRegionLoader { @@ -0,0 +0,0 @@ public class ChunkRegionLoader {
// Paper end // Paper end
ChunkGenerator<?> chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator();
WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager(); WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager();
- NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level"); - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level");
- ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); - ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos"));
@ -38,8 +38,8 @@ diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/jav
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/IChunkLoader.java --- a/src/main/java/net/minecraft/server/IChunkLoader.java
+++ b/src/main/java/net/minecraft/server/IChunkLoader.java +++ b/src/main/java/net/minecraft/server/IChunkLoader.java
@@ -0,0 +0,0 @@ public class IChunkLoader extends RegionFileCache implements AutoCloseable { @@ -0,0 +0,0 @@ public class IChunkLoader implements AutoCloseable {
//
public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER
public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety)
+ // Paper start + // Paper start
@ -49,6 +49,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ + " but compound says coordinate is " + ChunkRegionLoader.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); + + " but compound says coordinate is " + ChunkRegionLoader.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world)));
+ } + }
+ // Paper end + // Paper end
super.write(chunkcoordintpair, nbttagcompound); this.regionFileCache.write(chunkcoordintpair, nbttagcompound);
if (this.c != null) { if (this.c != null) {
synchronized (this.persistentDataLock) { // Paper - Async chunk loading synchronized (this.persistentDataLock) { // Paper - Async chunk loading

View file

@ -123,5 +123,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
+ +
@Override @Override
public Packet<?> L() { public Packet<?> O() {
return new PacketPlayOutSpawnEntity(this); return new PacketPlayOutSpawnEntity(this);

View file

@ -14,45 +14,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private int jumpTicks; private int jumpTicks;
private float bD; private float bD;
public ItemStack activeItem; // Paper - public public ItemStack activeItem; // Paper - public
- protected int bl; - protected int bk;
+ protected int bl; protected final int getEatTimeTicks() { return this.bl; } protected final void setEatTimeTicks(int value) { this.bl = value; } // Paper - OBFHELPER + protected int bk; protected final int getEatTimeTicks() { return this.bk; } protected final void setEatTimeTicks(int value) { this.bk = value; } // Paper - OBFHELPER
protected int bm; protected int bl;
private BlockPosition bE; private BlockPosition bE;
private DamageSource bF; private Optional<BlockPosition> bF;
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
return ((Byte) this.datawatcher.get(EntityLiving.ao) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND; return ((Byte) this.datawatcher.get(EntityLiving.an) & 2) > 0 ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND;
} }
+ // Paper start - lag compensate eating + // Paper start - lag compensate eating
+ protected long eatStartTime; + protected long eatStartTime;
+ protected int totalEatTimeTicks; + protected int totalEatTimeTicks;
+ // Paper end + // Paper end
private void o() { +
private void u() {
if (this.isHandRaised()) { if (this.isHandRaised()) {
if (ItemStack.d(this.b(this.getRaisedHand()), this.activeItem)) { if (ItemStack.d(this.b(this.getRaisedHand()), this.activeItem)) {
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
this.b(this.activeItem, 5); this.b(this.activeItem, 5);
} }
- if (--this.bl == 0 && !this.world.isClientSide && !this.activeItem.m()) { - if (--this.bk == 0 && !this.world.isClientSide && !this.activeItem.m()) {
+
+ // Paper start - lag compensate eating + // Paper start - lag compensate eating
+ // we add 1 to the expected time to avoid lag compensating when we should not + // we add 1 to the expected time to avoid lag compensating when we should not
+ boolean shouldLagCompensate + boolean shouldLagCompensate
+ = this.activeItem.getItem().isFood() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); + = this.activeItem.getItem().isFood() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000));
+ if ((--this.bl == 0 || shouldLagCompensate) && !this.world.isClientSide && !this.activeItem.m()) { + if ((--this.bk == 0 || shouldLagCompensate) && !this.world.isClientSide && !this.activeItem.m()) {
+ this.setEatTimeTicks(0); + this.setEatTimeTicks(0);
+ // Paper end + // Paper end
this.q(); this.s();
} }
} else { } else {
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag
this.activeItem = itemstack; this.activeItem = itemstack;
- this.bl = itemstack.k(); - this.bk = itemstack.k();
+ // Paper start - lag compensate eating + // Paper start - lag compensate eating
+ this.bl = this.totalEatTimeTicks = itemstack.k(); + this.bk = this.totalEatTimeTicks = itemstack.k();
+ this.eatStartTime = System.nanoTime(); + this.eatStartTime = System.nanoTime();
+ // Paper end + // Paper end
if (!this.world.isClientSide) { if (!this.world.isClientSide) {
@ -61,10 +61,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
} }
} else if (!this.isHandRaised() && !this.activeItem.isEmpty()) { } else if (!this.isHandRaised() && !this.activeItem.isEmpty()) {
this.activeItem = ItemStack.a; this.activeItem = ItemStack.b;
- this.bl = 0; - this.bk = 0;
+ // Paper start - lag compensate eating + // Paper start - lag compensate eating
+ this.bl = this.totalEatTimeTicks = 0; + this.bk = this.totalEatTimeTicks = 0;
+ this.eatStartTime = -1L; + this.eatStartTime = -1L;
+ // Paper end + // Paper end
} }
@ -73,10 +73,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
} }
this.activeItem = ItemStack.a; this.activeItem = ItemStack.b;
- this.bl = 0; - this.bk = 0;
+ // Paper start - lag compensate eating + // Paper start - lag compensate eating
+ this.bl = this.totalEatTimeTicks = 0; + this.bk = this.totalEatTimeTicks = 0;
+ this.eatStartTime = -1L; + this.eatStartTime = -1L;
+ // Paper end + // Paper end
} }

View file

@ -403,12 +403,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
private String motd; private String motd;
private int F;
private int G; private int G;
private int H; - public final long[] h;
- public final long[] f = new long[100]; + public final long[] h; public long[] getTickTimes() { return h; } // Paper - OBFHELPER
+ public final long[] f = new long[100]; public long[] getTickTimes() { return f; } // Paper - OBFHELPER
@Nullable @Nullable
private KeyPair I; private KeyPair H;
@Nullable @Nullable
diff --git a/src/main/java/net/minecraft/server/ServerGUI.java b/src/main/java/net/minecraft/server/ServerGUI.java diff --git a/src/main/java/net/minecraft/server/ServerGUI.java b/src/main/java/net/minecraft/server/ServerGUI.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644

View file

@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition); VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition);
if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) { if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) {
@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
Iterator iterator = this.navigators.iterator(); Iterator iterator = this.navigators.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} }
} }

View file

@ -37,21 +37,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean antiXray; public boolean antiXray;
public EngineMode engineMode; public EngineMode engineMode;
public int maxChunkSectionIndex; public int maxChunkSectionIndex;
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public final class SpawnerCreature {
EnumCreatureType enumcreaturetype = entity.getEntityType().e(); EnumCreatureType enumcreaturetype = entity.getEntityType().e();
if (enumcreaturetype != EnumCreatureType.MISC && this.getChunkProvider().b(entity)) { if (enumcreaturetype != EnumCreatureType.MISC) {
+ // Paper start - Only count natural spawns + // Paper start - Only count natural spawns
+ if (!this.paperConfig.countAllMobsForSpawning && + if (!entity.world.paperConfig.countAllMobsForSpawning &&
+ !(entity.spawnReason == CreatureSpawnEvent.SpawnReason.NATURAL || + !(entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL ||
+ entity.spawnReason == CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { + entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) {
+ continue; + continue;
+ } + }
+ // Paper end + // Paper end
object2intmap.mergeInt(enumcreaturetype, 1, Integer::sum); BlockPosition blockposition = entity.getChunkCoordinates();
} long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4);
}

View file

@ -26,9 +26,9 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
return new Throwable(entity + " Added to world at " + new java.util.Date());
} }
// Paper end
+ // Paper start - optimise getPlayerByUUID + // Paper start - optimise getPlayerByUUID
+ @Nullable + @Nullable
@ -39,6 +39,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // Paper end
+ +
// Paper start - Asynchronous IO // Add env and gen to constructor, WorldData -> WorldDataServer
public final com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController poiDataController = new com.destroystokyo.paper.io.PaperFileIOThread.ChunkDataController() { public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
@Override super(iworlddataserver, resourcekey, resourcekey1, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor

View file

@ -113,7 +113,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private final WorldServer world; + private final WorldServer world;
+ private final Predicate<T> excludeFromScheduling; + private final Predicate<T> excludeFromScheduling;
+ private final Function<T, MinecraftKey> getMinecraftKeyFrom; + private final Function<T, MinecraftKey> getMinecraftKeyFrom;
+ private final Function<MinecraftKey, T> getObjectFronMinecraftKey; + //private final Function<MinecraftKey, T> getObjectFronMinecraftKey;
+ private final Consumer<NextTickListEntry<T>> tickFunction; + private final Consumer<NextTickListEntry<T>> tickFunction;
+ +
+ private final co.aikar.timings.Timing timingCleanup; // Paper + private final co.aikar.timings.Timing timingCleanup; // Paper
@ -156,12 +156,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ +
+ public PaperTickList(final WorldServer world, final Predicate<T> excludeFromScheduling, final Function<T, MinecraftKey> getMinecraftKeyFrom, + public PaperTickList(final WorldServer world, final Predicate<T> excludeFromScheduling, final Function<T, MinecraftKey> getMinecraftKeyFrom,
+ final Function<MinecraftKey, T> getObjectFronMinecraftKey, final Consumer<NextTickListEntry<T>> tickFunction, final String timingsType) { + final Consumer<NextTickListEntry<T>> tickFunction, final String timingsType) {
+ super(world, excludeFromScheduling, getMinecraftKeyFrom, getObjectFronMinecraftKey, tickFunction, timingsType); + super(world, excludeFromScheduling, getMinecraftKeyFrom, tickFunction, timingsType);
+ this.world = world; + this.world = world;
+ this.excludeFromScheduling = excludeFromScheduling; + this.excludeFromScheduling = excludeFromScheduling;
+ this.getMinecraftKeyFrom = getMinecraftKeyFrom; + this.getMinecraftKeyFrom = getMinecraftKeyFrom;
+ this.getObjectFronMinecraftKey = getObjectFronMinecraftKey;
+ this.tickFunction = tickFunction; + this.tickFunction = tickFunction;
+ this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper + this.timingCleanup = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Cleanup"); // Paper
+ this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper + this.timingTicking = co.aikar.timings.WorldTimingsHandler.getTickList(world, timingsType + " - Ticking"); // Paper
@ -521,10 +520,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.addToSchedule(entry); + this.addToSchedule(entry);
+ } + }
+ +
+ @Override
+ public void scheduleAll(final Stream<NextTickListEntry<T>> stream) {
+ this.scheduleAll(stream.iterator());
+ }
+ public void scheduleAll(final Iterator<NextTickListEntry<T>> iterator) { + public void scheduleAll(final Iterator<NextTickListEntry<T>> iterator) {
+ while (iterator.hasNext()) { + while (iterator.hasNext()) {
+ this.schedule(iterator.next()); + this.schedule(iterator.next());
@ -886,7 +881,7 @@ diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/ja
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/BlockPosition.java --- a/src/main/java/net/minecraft/server/BlockPosition.java
+++ b/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java
@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali @@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition {
return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k); return i == 0 && j == 0 && k == 0 ? this : new BlockPosition(this.getX() + i, this.getY() + j, this.getZ() + k);
} }
@ -909,9 +904,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end - rewrite ticklistserver + // Paper end - rewrite ticklistserver
+ +
public ChunkProviderServer(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, boolean flag, WorldLoadListener worldloadlistener, Supplier<WorldPersistentData> supplier) {
public ChunkProviderServer(WorldServer worldserver, File file, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator<?> chunkgenerator, int i, WorldLoadListener worldloadlistener, Supplier<WorldPersistentData> supplier) {
this.world = worldserver; this.world = worldserver;
this.serverThreadQueue = new ChunkProviderServer.a(worldserver);
diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/NextTickListEntry.java --- a/src/main/java/net/minecraft/server/NextTickListEntry.java
@ -1030,7 +1025,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return this.d >= structureboundingbox.a && this.a <= structureboundingbox.d && this.f >= structureboundingbox.c && this.c <= structureboundingbox.f && this.e >= structureboundingbox.b && this.b <= structureboundingbox.e; return this.d >= structureboundingbox.a && this.a <= structureboundingbox.d && this.f >= structureboundingbox.c && this.c <= structureboundingbox.f && this.e >= structureboundingbox.b && this.b <= structureboundingbox.e;
} }
@@ -0,0 +0,0 @@ public class StructureBoundingBox { @@ -0,0 +0,0 @@ public class StructureBoundingBox {
return new StructureBoundingBox(this.a + i, this.b + j, this.c + k, this.d + i, this.e + j, this.f + k); this.a(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ());
} }
+ public final boolean hasPoint(BaseBlockPosition baseblockposition) { return this.b(baseblockposition); } // Paper - OBFHELPER + public final boolean hasPoint(BaseBlockPosition baseblockposition) { return this.b(baseblockposition); } // Paper - OBFHELPER
@ -1062,17 +1057,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ public boolean isPendingTickThisTick(BlockPosition blockposition, T t0) { + public boolean isPendingTickThisTick(BlockPosition blockposition, T t0) {
+ // Paper end + // Paper end
return this.g.contains(new NextTickListEntry<>(blockposition, t0)); return this.f.contains(new NextTickListEntry<>(blockposition, t0));
}
@Override
public void a(Stream<NextTickListEntry<T>> stream) {
+ // Paper start - allow overriding
+ this.scheduleAll(stream);
+ }
+ public void scheduleAll(Stream<NextTickListEntry<T>> stream) {
+ // Paper end
stream.forEach(this::a);
} }
public List<NextTickListEntry<T>> a(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) { public List<NextTickListEntry<T>> a(ChunkCoordIntPair chunkcoordintpair, boolean flag, boolean flag1) {
@ -1119,11 +1104,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end + // Paper end
List<NextTickListEntry<T>> list = this.a(chunkcoordintpair, false, true); List<NextTickListEntry<T>> list = this.a(chunkcoordintpair, false, true);
return a(this.b, list, this.f.getTime()); return a(this.b, list, this.e.getTime());
} }
+ public static <T> NBTTagList serialize(Function<T, MinecraftKey> function, Iterable<NextTickListEntry<T>> iterable, long i) { return TickListServer.a(function, iterable, i); } // Paper - OBFHELPER + public static <T> NBTTagList serialize(Function<T, MinecraftKey> function, Iterable<NextTickListEntry<T>> iterable, long i) { return TickListServer.a(function, iterable, i); } // Paper - OBFHELPER
public static <T> NBTTagList a(Function<T, MinecraftKey> function, Iterable<NextTickListEntry<T>> iterable, long i) { private static <T> NBTTagList a(Function<T, MinecraftKey> function, Iterable<NextTickListEntry<T>> iterable, long i) {
NBTTagList nbttaglist = new NBTTagList(); NBTTagList nbttaglist = new NBTTagList();
Iterator iterator = iterable.iterator(); Iterator iterator = iterable.iterator();
@@ -0,0 +0,0 @@ public class TickListServer<T> implements TickList<T> { @@ -0,0 +0,0 @@ public class TickListServer<T> implements TickList<T> {
@ -1146,7 +1131,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public void schedule(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) { + public void schedule(BlockPosition blockposition, T t0, int i, TickListPriority ticklistpriority) {
+ // Paper end + // Paper end
if (!this.a.test(t0)) { if (!this.a.test(t0)) {
this.a(new NextTickListEntry<>(blockposition, t0, (long) i + this.f.getTime(), ticklistpriority)); this.a(new NextTickListEntry<>(blockposition, t0, (long) i + this.e.getTime(), ticklistpriority));
} }
@@ -0,0 +0,0 @@ public class TickListServer<T> implements TickList<T> { @@ -0,0 +0,0 @@ public class TickListServer<T> implements TickList<T> {
} }
@ -1164,7 +1149,7 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} }
// Paper end // Paper end
@ -1177,35 +1162,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end - rewrite ticklistserver + // Paper end - rewrite ticklistserver
+ +
// Add env and gen to constructor // Add env and gen to constructor, WorldData -> WorldDataServer
public WorldServer(MinecraftServer minecraftserver, Executor executor, WorldNBTStorage worldnbtstorage, WorldData worlddata, DimensionManager dimensionmanager, GameProfilerFiller gameprofilerfiller, WorldLoadListener worldloadlistener, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
super(worlddata, dimensionmanager, executor, (world, worldprovider) -> { // Paper - pass executor down super(iworlddataserver, resourcekey, resourcekey1, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.pvpMode = minecraftserver.getPVP(); convertable = convertable_conversionsession;
worlddata.world = this; uuid = WorldUUID.getUUID(convertable_conversionsession.folder.toFile());
// CraftBukkit end // CraftBukkit end
- this.nextTickListBlock = new TickListServer<>(this, (block) -> { - this.nextTickListBlock = new TickListServer<>(this, (block) -> {
- return block == null || block.getBlockData().isAir(); - return block == null || block.getBlockData().isAir();
- }, IRegistry.BLOCK::getKey, IRegistry.BLOCK::get, this::b, "Blocks"); // Paper - Timings - }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings
- this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { - this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> {
- return fluidtype == null || fluidtype == FluidTypes.EMPTY; - return fluidtype == null || fluidtype == FluidTypes.EMPTY;
- }, IRegistry.FLUID::getKey, IRegistry.FLUID::get, this::a, "Fluids"); // Paper - Timings - }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings
+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) { + if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) {
+ this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> { // Paper - optimise TickListServer + this.nextTickListBlock = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> {
+ return block == null || block.getBlockData().isAir(); + return block == null || block.getBlockData().isAir();
+ }, IRegistry.BLOCK::getKey, IRegistry.BLOCK::get, this::b, "Blocks"); // Paper - Timings + }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings
+ this.nextTickListFluid = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> { // Paper - optimise TickListServer + this.nextTickListFluid = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> {
+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; + return fluidtype == null || fluidtype == FluidTypes.EMPTY;
+ }, IRegistry.FLUID::getKey, IRegistry.FLUID::get, this::a, "Fluids"); // Paper - Timings + }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings
+ } else { + } else {
+ this.nextTickListBlock = new TickListServer<>(this, (block) -> { // Paper - optimise TickListServer + this.nextTickListBlock = new TickListServer<>(this, (block) -> {
+ return block == null || block.getBlockData().isAir(); + return block == null || block.getBlockData().isAir();
+ }, IRegistry.BLOCK::getKey, IRegistry.BLOCK::get, this::b, "Blocks"); // Paper - Timings + }, IRegistry.BLOCK::getKey, this::b, "Blocks"); // Paper - Timings
+ this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> { // Paper - optimise TickListServer + this.nextTickListFluid = new TickListServer<>(this, (fluidtype) -> {
+ return fluidtype == null || fluidtype == FluidTypes.EMPTY; + return fluidtype == null || fluidtype == FluidTypes.EMPTY;
+ }, IRegistry.FLUID::getKey, IRegistry.FLUID::get, this::a, "Fluids"); // Paper - Timings + }, IRegistry.FLUID::getKey, this::a, "Fluids"); // Paper - Timings
+ } + }
+
this.navigators = Sets.newHashSet(); this.navigators = Sets.newHashSet();
this.I = new ObjectLinkedOpenHashSet(); this.L = new ObjectLinkedOpenHashSet();
this.dataManager = worldnbtstorage; this.Q = flag1;

View file

@ -70,39 +70,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound); + return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound);
+ } + }
+} +}
diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/Block.java
+++ b/src/main/java/net/minecraft/server/Block.java
@@ -0,0 +0,0 @@ public class Block implements IMaterial {
return iblockdata.d(iblockaccess, blockposition, EnumDirection.UP) && this.n < 14;
}
- @Deprecated
- public boolean d(IBlockData iblockdata) {
+ public final boolean isAir(IBlockData iblockdata) { return this.d(iblockdata); } // Paper - OBFHELPER
+ @Deprecated public boolean d(IBlockData iblockdata) { // Paper - OBFHELPER
return false;
}
diff --git a/src/main/java/net/minecraft/server/BlockFluids.java b/src/main/java/net/minecraft/server/BlockFluids.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/BlockFluids.java
+++ b/src/main/java/net/minecraft/server/BlockFluids.java
@@ -0,0 +0,0 @@ public class BlockFluids extends Block implements IFluidSource {
@Override
public void b(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, Random random) {
- worldserver.getFluid(blockposition).b(worldserver, blockposition, random);
+ iblockdata.getFluid().b(worldserver, blockposition, random); // Paper - avoid getType call
}
@Override
diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/BlockPosition.java --- a/src/main/java/net/minecraft/server/BlockPosition.java
+++ b/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java
@@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali @@ -0,0 +0,0 @@ public class BlockPosition extends BaseBlockPosition {
return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2));
} }
@ -119,9 +91,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
- @Override - @Override
- public int a(HeightMap.Type heightmap_type, int i, int j) { - public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) {
+ public int getHighestBlockY(HeightMap.Type heightmap_type, int i, int j) { return this.a(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1 + public final int getHighestBlockY(HeightMap.Type heightmap_type, int i, int j) { return this.getHighestBlock(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1
+ @Override public int a(HeightMap.Type heightmap_type, int i, int j) { // Paper + @Override public int getHighestBlock(HeightMap.Type heightmap_type, int i, int j) { // Paper
return ((HeightMap) this.heightMap.get(heightmap_type)).a(i & 15, j & 15) - 1; return ((HeightMap) this.heightMap.get(heightmap_type)).a(i & 15, j & 15) - 1;
} }
@ -148,7 +120,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) { public ChunkSection(int i, IChunkAccess chunk, World world, boolean initializeBlocks) {
@@ -0,0 +0,0 @@ public class ChunkSection { @@ -0,0 +0,0 @@ public class ChunkSection {
--this.nonEmptyBlockCount; --this.nonEmptyBlockCount;
if (iblockdata1.q()) { if (iblockdata1.isTicking()) {
--this.tickingBlockCount; --this.tickingBlockCount;
+ // Paper start + // Paper start
+ this.tickingList.remove(i, j, k); + this.tickingList.remove(i, j, k);
@ -158,7 +130,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public class ChunkSection { @@ -0,0 +0,0 @@ public class ChunkSection {
++this.nonEmptyBlockCount; ++this.nonEmptyBlockCount;
if (iblockdata.q()) { if (iblockdata.isTicking()) {
++this.tickingBlockCount; ++this.tickingBlockCount;
+ // Paper start + // Paper start
+ this.tickingList.add(i, j, k, iblockdata); + this.tickingList.add(i, j, k, iblockdata);
@ -182,10 +154,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!iblockdata.isAir()) { if (!iblockdata.isAir()) {
- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); - this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i);
+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper + this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1);
if (iblockdata.q()) { if (iblockdata.isTicking()) {
- this.tickingBlockCount = (short) (this.tickingBlockCount + i); - this.tickingBlockCount = (short) (this.tickingBlockCount + i);
+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1); // Paper + this.tickingBlockCount = (short) (this.tickingBlockCount + 1);
+ // Paper start + // Paper start
+ this.tickingList.add(location, iblockdata); + this.tickingList.add(location, iblockdata);
+ // Paper end + // Paper end
@ -194,10 +166,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (!fluid.isEmpty()) { if (!fluid.isEmpty()) {
- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i); - this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i);
+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper + this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1);
if (fluid.h()) { if (fluid.f()) {
- this.e = (short) (this.e + i); - this.e = (short) (this.e + i);
+ this.e = (short) (this.e + 1); // Paper + this.e = (short) (this.e + 1);
} }
} }
@ -206,41 +178,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/DataBits.java --- a/src/main/java/net/minecraft/server/DataBits.java
+++ b/src/main/java/net/minecraft/server/DataBits.java +++ b/src/main/java/net/minecraft/server/DataBits.java
@@ -0,0 +0,0 @@ public class DataBits { @@ -0,0 +0,0 @@ public class DataBits {
} }
} }
+ +
+ // Paper start + // Paper start
+ public final void forEach(DataBitConsumer consumer) { + public final void forEach(DataBitConsumer consumer) {
+ // Note: copied from above + int i = 0;
+ int i = this.a.length; + long[] along = this.b;
+ int j = along.length;
+ +
+ if (i != 0) { + for (int k = 0; k < j; ++k) {
+ int j = 0; + long l = along[k];
+ long k = this.a[0];
+ long l = i > 1 ? this.a[1] : 0L;
+ +
+ for (int i1 = 0; i1 < this.d; ++i1) { + for (int i1 = 0; i1 < this.f; ++i1) {
+ int j1 = i1 * this.b; + consumer.accept(i, (int) (l & this.d));
+ int k1 = j1 >> 6; + l >>= this.c;
+ int l1 = (i1 + 1) * this.b - 1 >> 6; + ++i;
+ int i2 = j1 ^ k1 << 6; + if (i >= this.e) {
+ + return;
+ if (k1 != j) {
+ k = l;
+ l = k1 + 1 < i ? this.a[k1 + 1] : 0L;
+ j = k1;
+ }
+
+ if (k1 == l1) {
+ consumer.accept(i1, (int) (k >>> i2 & this.c));
+ } else {
+ int j2 = 64 - i2;
+
+ consumer.accept(i1, (int) ((k >>> i2 | l << j2) & this.c));
+ } + }
+ } + }
+
+ } + }
+ } + }
+ +
@ -277,72 +235,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/EntityTurtle.java +++ b/src/main/java/net/minecraft/server/EntityTurtle.java
@@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal { @@ -0,0 +0,0 @@ public class EntityTurtle extends EntityAnimal {
public final void setHome(BlockPosition pos) { g(pos); } // Paper - OBFHELPER public final void setHome(BlockPosition pos) { setHomePos(pos); } // Paper - OBFHELPER
public void g(BlockPosition blockposition) { public void setHomePos(BlockPosition blockposition) {
- this.datawatcher.set(EntityTurtle.bx, blockposition); - this.datawatcher.set(EntityTurtle.bw, blockposition);
+ this.datawatcher.set(EntityTurtle.bx, blockposition.immutableCopy()); // Paper - make sure home position can't change + this.datawatcher.set(EntityTurtle.bw, blockposition.immutableCopy()); // Paper - called with mutablepos...
} }
// TODO Paper: Obf helpers here can prolly be removed? check that no newer patches use them
public final BlockPosition getHome() { return this.es(); } // Paper - OBFHELPER public final BlockPosition getHome() { return this.getHomePos(); } // Paper - OBFHELPER
diff --git a/src/main/java/net/minecraft/server/IBlockData.java b/src/main/java/net/minecraft/server/IBlockData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/IBlockData.java
+++ b/src/main/java/net/minecraft/server/IBlockData.java
@@ -0,0 +0,0 @@ public class IBlockData extends BlockDataAbstract<Block, IBlockData> implements
private IBlockData.a c;
private final int d;
private final boolean e;
+ private final boolean isAir; // Paper
+ private final boolean isTicking; // Paper
public IBlockData(Block block, ImmutableMap<IBlockState<?>, Comparable<?>> immutablemap) {
super(block, immutablemap);
this.d = block.a(this);
this.e = block.o(this);
+ this.isAir = this.getBlock().isAir(this); // Paper
+ this.isTicking = this.getBlock().isTicking(this); // Paper
}
public void c() {
@@ -0,0 +0,0 @@ public class IBlockData extends BlockDataAbstract<Block, IBlockData> implements
return this.d;
}
- public boolean isAir() {
- return this.getBlock().d(this);
+ public final boolean isAir() { // Paper - compile fail if the impl changes
+ return this.isAir; // Paper - improve inlining of isAir
}
public MaterialMapColor c(IBlockAccess iblockaccess, BlockPosition blockposition) {
@@ -0,0 +0,0 @@ public class IBlockData extends BlockDataAbstract<Block, IBlockData> implements
return this.getBlock().a(tag);
}
+ private Fluid fluidData; // Paper - cache result
public Fluid getFluid() {
- return this.getBlock().a_(this);
+ // Paper start
+ // This can't be done during the constructor, order issues
+ if (this.fluidData != null) {
+ return this.fluidData;
+ }
+ return this.fluidData = this.getBlock().a_(this);
+ // Paper end
}
public boolean q() {
- return this.getBlock().isTicking(this);
+ return this.isTicking; // Paper
}
public final SoundEffectType getStepSound() { return this.r(); } // Paper - OBFHELPER
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
public abstract TagRegistry t(); public abstract TagRegistry p();
public BlockPosition a(int i, int j, int k, int l) { public BlockPosition a(int i, int j, int k, int l) {
+ // Paper start - allow use of mutable pos + // Paper start - allow use of mutable pos
@ -350,11 +255,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.getRandomBlockPosition(i, j, k, l, ret); + this.getRandomBlockPosition(i, j, k, l, ret);
+ return ret.immutableCopy(); + return ret.immutableCopy();
+ } + }
+
+ public final BlockPosition.MutableBlockPosition getRandomBlockPosition(int i, int j, int k, int l, BlockPosition.MutableBlockPosition out) { + public final BlockPosition.MutableBlockPosition getRandomBlockPosition(int i, int j, int k, int l, BlockPosition.MutableBlockPosition out) {
+ // Paper end + // Paper end
this.i = this.i * 3 + 1013904223; this.n = this.n * 3 + 1013904223;
int i1 = this.i >> 2; int i1 = this.n >> 2;
- return new BlockPosition(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); - return new BlockPosition(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15));
+ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call + out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call
@ -366,7 +270,7 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}); });
} }
@ -380,21 +284,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining(); boolean flag = this.isRaining();
int j = chunkcoordintpair.d(); int j = chunkcoordintpair.d();
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
GameProfilerFiller gameprofilerfiller = this.getMethodProfiler(); GameProfilerFiller gameprofilerfiller = this.getMethodProfiler();
gameprofilerfiller.enter("thunder"); gameprofilerfiller.enter("thunder");
- BlockPosition blockposition; - BlockPosition blockposition;
+ final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change + final BlockPosition.MutableBlockPosition blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
- if (!this.paperConfig.disableThunder && flag && this.U() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder if (!this.paperConfig.disableThunder && flag && this.T() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder
- blockposition = this.a(this.a(j, 0, k, 15)); - blockposition = this.a(this.a(j, 0, k, 15));
+ if (!this.paperConfig.disableThunder && flag && this.U() && this.randomTickRandom.nextInt(100000) == 0) { // Paper - Disable thunder // Paper - optimise random ticking + blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper
+ blockposition.setValues(this.a(this.getRandomBlockPosition(j, 0, k, 15, blockposition))); // Paper
if (this.isRainingAt(blockposition)) { if (this.isRainingAt(blockposition)) {
DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition);
boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper boolean flag1 = this.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} }
gameprofilerfiller.exitEnter("iceandsnow"); gameprofilerfiller.exitEnter("iceandsnow");
@ -469,10 +372,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ continue; + continue;
+ } + }
- if (iblockdata.q()) { - if (iblockdata.isTicking()) {
- iblockdata.getBlock().randomTick = true; // Paper - fix MC-113809
- iblockdata.b(this, blockposition2, this.random); - iblockdata.b(this, blockposition2, this.random);
- iblockdata.getBlock().randomTick = false; // Paper - fix MC-113809
- } - }
+ long raw = section.tickingList.getRaw(index); + long raw = section.tickingList.getRaw(index);
+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); + int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw);
@ -484,12 +385,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ); + BlockPosition blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ);
+ IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); + IBlockData iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw);
- if (fluid.h()) { - if (fluid.f()) {
- fluid.b(this, blockposition2, this.random); - fluid.b(this, blockposition2, this.random);
- } - }
+ iblockdata.getBlock().randomTick = true; // Paper - fix MC-113809
+ iblockdata.b(this, blockposition2, this.randomTickRandom); + iblockdata.b(this, blockposition2, this.randomTickRandom);
+ iblockdata.getBlock().randomTick = false; // Paper - fix MC-113809
- gameprofilerfiller.exit(); - gameprofilerfiller.exit();
- } - }

View file

@ -43,14 +43,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
World getWorld(); World getWorld();
+ default BlockPosition getBlockPosition() { return new BlockPosition(getX(), getY(), getZ()); } // Paper + default BlockPosition getBlockPosition() { return new BlockPosition(getX(), getY(), getZ()); } // Paper
- double x();
+ double x(); default double getX() { return this.x(); } // Paper - OBFHELPER
- double z(); - double z();
+ double z();default double getX() { return z(); } // Paper - OBFHELPER + double z(); default double getY() { return this.z(); } // Paper - OBFHELPER
- double A(); - double A();
+ double A();default double getY() { return A(); } // Paper - OBFHELPER + double A(); default double getZ() { return this.A(); } // Paper - OBFHELPER
- double B();
+ double B();default double getZ() { return B(); } // Paper - OBFHELPER
} }
diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -65,25 +65,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper + public ItemStack cloneItemStack() { return cloneItemStack(false); } // Paper
+ public ItemStack cloneItemStack(boolean origItem) { // Paper + public ItemStack cloneItemStack(boolean origItem) { // Paper
+ if (!origItem && this.isEmpty()) { // Paper + if (!origItem && this.isEmpty()) { // Paper
return ItemStack.a; return ItemStack.b;
} else { } else {
- ItemStack itemstack = new ItemStack(this.getItem(), this.count); - ItemStack itemstack = new ItemStack(this.getItem(), this.count);
+ ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper + ItemStack itemstack = new ItemStack(origItem ? this.item : this.getItem(), this.count); // Paper
itemstack.d(this.C()); itemstack.d(this.D());
if (this.tag != null) { if (this.tag != null) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java --- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
while (iterator.hasNext()) {
WorldServer worldserver = (WorldServer) iterator.next(); WorldServer worldserver = (WorldServer) iterator.next();
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper
+ TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + TileEntityHopper.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper
if (true || worldserver.worldProvider.getDimensionManager() == DimensionManager.OVERWORLD || this.getAllowNether()) { // CraftBukkit
this.methodProfiler.a(() -> { this.methodProfiler.a(() -> {
return worldserver.getWorldData().getName() + " " + IRegistry.DIMENSION_TYPE.getKey(worldserver.worldProvider.getDimensionManager()); return worldserver + " " + worldserver.getDimensionKey().a();
diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/TileEntity.java --- a/src/main/java/net/minecraft/server/TileEntity.java
@ -266,8 +266,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // Paper end
+ +
private boolean j() { private boolean k() {
IInventory iinventory = this.k(); IInventory iinventory = this.l();
@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi @@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
if (this.b(iinventory, enumdirection)) { if (this.b(iinventory, enumdirection)) {
@ -412,15 +412,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ IGNORE_TILE_UPDATES = true; // Paper + IGNORE_TILE_UPDATES = true; // Paper
iinventory1.setItem(i, itemstack); iinventory1.setItem(i, itemstack);
+ IGNORE_TILE_UPDATES = false; // Paper + IGNORE_TILE_UPDATES = false; // Paper
itemstack = ItemStack.a; itemstack = ItemStack.b;
flag = true; flag = true;
} else if (a(itemstack1, itemstack)) { } else if (a(itemstack1, itemstack)) {
@@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi @@ -0,0 +0,0 @@ public class TileEntityHopper extends TileEntityLootable implements IHopper, ITi
} }
public static List<EntityItem> c(IHopper ihopper) { public static List<EntityItem> c(IHopper ihopper) {
- return (List) ihopper.P_().d().stream().flatMap((axisalignedbb) -> { - return (List) ihopper.ac_().d().stream().flatMap((axisalignedbb) -> {
- return ihopper.getWorld().a(EntityItem.class, axisalignedbb.d(ihopper.z() - 0.5D, ihopper.A() - 0.5D, ihopper.B() - 0.5D), IEntitySelector.a).stream(); - return ihopper.getWorld().a(EntityItem.class, axisalignedbb.d(ihopper.x() - 0.5D, ihopper.z() - 0.5D, ihopper.A() - 0.5D), IEntitySelector.a).stream();
- }).collect(Collectors.toList()); - }).collect(Collectors.toList());
+ // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! + // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?!
+ World world = ihopper.getWorld(); + World world = ihopper.getWorld();

View file

@ -14,6 +14,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
IBlockData iblockdata = this.world.getType(blockposition); IBlockData iblockdata = this.world.getType(blockposition);
- Fluid fluid = this.world.getFluid(blockposition); - Fluid fluid = this.world.getFluid(blockposition);
+ Fluid fluid = iblockdata.getFluid(); // Paper + Fluid fluid = iblockdata.getFluid(); // Paper
Optional<Float> optional = this.k.a(this, this.world, blockposition, iblockdata, fluid);
if (!iblockdata.isAir() || !fluid.isEmpty()) { if (optional.isPresent()) {
float f2 = Math.max(iblockdata.getBlock().getDurability(), fluid.k());

View file

@ -53,7 +53,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+++ b/src/main/java/net/minecraft/server/MobSpawnerPatrol.java +++ b/src/main/java/net/minecraft/server/MobSpawnerPatrol.java
@@ -0,0 +0,0 @@ import java.util.Random; @@ -0,0 +0,0 @@ import java.util.Random;
public class MobSpawnerPatrol { public class MobSpawnerPatrol implements MobSpawner {
+ private int getSpawnDelay() { return a; } // Paper - OBFHELPER + private int getSpawnDelay() { return a; } // Paper - OBFHELPER
+ private void setSpawnDelay(int spawnDelay) { this.a = spawnDelay; } // Paper - OBFHELPER + private void setSpawnDelay(int spawnDelay) { this.a = spawnDelay; } // Paper - OBFHELPER
@ -61,13 +61,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public MobSpawnerPatrol() {} public MobSpawnerPatrol() {}
@Override
public int a(WorldServer worldserver, boolean flag, boolean flag1) { public int a(WorldServer worldserver, boolean flag, boolean flag1) {
- if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper - if (worldserver.paperConfig.disablePillagerPatrols) return 0; // Paper
+ if (worldserver.paperConfig.disablePillagerPatrols || worldserver.paperConfig.patrolSpawnChance == 0) return 0; // Paper + if (worldserver.paperConfig.disablePillagerPatrols || worldserver.paperConfig.patrolSpawnChance == 0) return 0; // Paper
if (!flag) { if (!flag) {
return 0; return 0;
} else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) { } else if (!worldserver.getGameRules().getBoolean(GameRules.DO_PATROL_SPAWNING)) {
@@ -0,0 +0,0 @@ public class MobSpawnerPatrol { @@ -0,0 +0,0 @@ public class MobSpawnerPatrol implements MobSpawner {
} else { } else {
Random random = worldserver.random; Random random = worldserver.random;

View file

@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/EntityPlayer.java --- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
this.eW();
this.releaseShoulderEntities(); }
// SPIGOT-5478 must be called manually now // SPIGOT-5478 must be called manually now
- this.dropExperience(); - this.dropExperience();
+ if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event + if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event

View file

@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ +
+ +
} }
world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemEgg.i.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemEgg.RANDOM.nextFloat() * 0.4F + 0.8F)); // CraftBukkit - from above
+ /* // Paper start - moved up + /* // Paper start - moved up
entityhuman.b(StatisticList.ITEM_USED.b(this)); entityhuman.b(StatisticList.ITEM_USED.b(this));
@ -58,7 +58,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
+ */ // Paper end + */ // Paper end
return InteractionResultWrapper.success(itemstack); return InteractionResultWrapper.a(itemstack, world.s_());
} }
diff --git a/src/main/java/net/minecraft/server/ItemEnderPearl.java b/src/main/java/net/minecraft/server/ItemEnderPearl.java diff --git a/src/main/java/net/minecraft/server/ItemEnderPearl.java b/src/main/java/net/minecraft/server/ItemEnderPearl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -91,7 +91,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
} }
- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.i.nextFloat() * 0.4F + 0.8F)); - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F));
- entityhuman.getCooldownTracker().setCooldown(this, 20); - entityhuman.getCooldownTracker().setCooldown(this, 20);
- // CraftBukkit end - // CraftBukkit end
- -
@ -100,7 +100,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- itemstack.subtract(1); - itemstack.subtract(1);
- } - }
+ // Paper start - moved up + // Paper start - moved up
+// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.i.nextFloat() * 0.4F + 0.8F)); +// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_ENDER_PEARL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderPearl.RANDOM.nextFloat() * 0.4F + 0.8F));
+// entityhuman.getCooldownTracker().setCooldown(this, 20); +// entityhuman.getCooldownTracker().setCooldown(this, 20);
+// // CraftBukkit end +// // CraftBukkit end
+// +//
@ -108,9 +108,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+// if (!entityhuman.abilities.canInstantlyBuild) { +// if (!entityhuman.abilities.canInstantlyBuild) {
+// itemstack.subtract(1); +// itemstack.subtract(1);
+// } +// }
+ // Paper end + // Paper end - moved up
return InteractionResultWrapper.success(itemstack); return InteractionResultWrapper.a(itemstack, world.s_());
} }
diff --git a/src/main/java/net/minecraft/server/ItemExpBottle.java b/src/main/java/net/minecraft/server/ItemExpBottle.java diff --git a/src/main/java/net/minecraft/server/ItemExpBottle.java b/src/main/java/net/minecraft/server/ItemExpBottle.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -120,8 +120,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public InteractionResultWrapper<ItemStack> a(World world, EntityHuman entityhuman, EnumHand enumhand) { public InteractionResultWrapper<ItemStack> a(World world, EntityHuman entityhuman, EnumHand enumhand) {
ItemStack itemstack = entityhuman.b(enumhand); ItemStack itemstack = entityhuman.b(enumhand);
- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.i.nextFloat() * 0.4F + 0.8F)); - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F));
+// world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.i.nextFloat() * 0.4F + 0.8F)); // Paper - moved down + //world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_EXPERIENCE_BOTTLE_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemExpBottle.RANDOM.nextFloat() * 0.4F + 0.8F)); // Paper - moved down
if (!world.isClientSide) { if (!world.isClientSide) {
EntityThrownExpBottle entitythrownexpbottle = new EntityThrownExpBottle(world, entityhuman); EntityThrownExpBottle entitythrownexpbottle = new EntityThrownExpBottle(world, entityhuman);
@ -155,7 +155,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
+ */ // Paper end + */ // Paper end
return InteractionResultWrapper.success(itemstack); return InteractionResultWrapper.a(itemstack, world.s_());
} }
diff --git a/src/main/java/net/minecraft/server/ItemLingeringPotion.java b/src/main/java/net/minecraft/server/ItemLingeringPotion.java diff --git a/src/main/java/net/minecraft/server/ItemLingeringPotion.java b/src/main/java/net/minecraft/server/ItemLingeringPotion.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -165,12 +165,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public InteractionResultWrapper<ItemStack> a(World world, EntityHuman entityhuman, EnumHand enumhand) { public InteractionResultWrapper<ItemStack> a(World world, EntityHuman entityhuman, EnumHand enumhand) {
- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.i.nextFloat() * 0.4F + 0.8F)); - world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F));
- return super.a(world, entityhuman, enumhand); - return super.a(world, entityhuman, enumhand);
+ // Paper start + // Paper start
+ InteractionResultWrapper<ItemStack> wrapper = super.a(world, entityhuman, enumhand); + InteractionResultWrapper<ItemStack> wrapper = super.a(world, entityhuman, enumhand);
+ if (wrapper.getResult() != EnumInteractionResult.FAIL) + if (wrapper.getResult() != EnumInteractionResult.FAIL) {
+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.i.nextFloat() * 0.4F + 0.8F)); + world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_LINGERING_POTION_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemLingeringPotion.RANDOM.nextFloat() * 0.4F + 0.8F));
+ }
+ return wrapper; + return wrapper;
+ // Paper end + // Paper end
} }
@ -210,7 +211,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
+ */ // Paper end + */ // Paper end
return InteractionResultWrapper.success(itemstack); return InteractionResultWrapper.a(itemstack, world.s_());
} }
diff --git a/src/main/java/net/minecraft/server/ItemSnowball.java b/src/main/java/net/minecraft/server/ItemSnowball.java diff --git a/src/main/java/net/minecraft/server/ItemSnowball.java b/src/main/java/net/minecraft/server/ItemSnowball.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@ -226,30 +227,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity()); + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) entitysnowball.getBukkitEntity());
+ if (event.callEvent() && world.addEntity(entitysnowball)) { + if (event.callEvent() && world.addEntity(entitysnowball)) {
+ if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) { + if (event.shouldConsume() && !entityhuman.abilities.canInstantlyBuild) {
+ // Paper end
itemstack.subtract(1); itemstack.subtract(1);
+ } else if (entityhuman instanceof EntityPlayer) { + } else if (entityhuman instanceof EntityPlayer) { // Paper
+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); + ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper
} }
- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.i.nextFloat() * 0.4F + 0.8F)); world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.RANDOM.nextFloat() * 0.4F + 0.8F));
- } else if (entityhuman instanceof EntityPlayer) { - } else if (entityhuman instanceof EntityPlayer) {
- ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); - ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory();
+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (Entity.SHARED_RANDOM.nextFloat() * 0.4F + 0.8F)); + } else { // Paper
+ entityhuman.b(StatisticList.ITEM_USED.b(this)); + if (entityhuman instanceof EntityPlayer) ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory(); // Paper
+ } else { + return new InteractionResultWrapper<ItemStack>(EnumInteractionResult.FAIL, itemstack); // Paper
+ if (entityhuman instanceof EntityPlayer) {
+ ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory();
+ }
+ return new InteractionResultWrapper<ItemStack>(EnumInteractionResult.FAIL, itemstack);
} }
} }
// CraftBukkit end // CraftBukkit end
- entityhuman.b(StatisticList.ITEM_USED.b(this));
+// entityhuman.b(StatisticList.ITEM_USED.b(this)); // Paper - moved up
// CraftBukkit start - moved up
/*
if (!entityhuman.abilities.canInstantlyBuild) {
diff --git a/src/main/java/net/minecraft/server/ItemSplashPotion.java b/src/main/java/net/minecraft/server/ItemSplashPotion.java diff --git a/src/main/java/net/minecraft/server/ItemSplashPotion.java b/src/main/java/net/minecraft/server/ItemSplashPotion.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/ItemSplashPotion.java --- a/src/main/java/net/minecraft/server/ItemSplashPotion.java
@ -258,12 +250,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@Override @Override
public InteractionResultWrapper<ItemStack> a(World world, EntityHuman entityhuman, EnumHand enumhand) { public InteractionResultWrapper<ItemStack> a(World world, EntityHuman entityhuman, EnumHand enumhand) {
- world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SPLASH_POTION_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemSplashPotion.i.nextFloat() * 0.4F + 0.8F));
- return super.a(world, entityhuman, enumhand);
+ // Paper start + // Paper start
+ InteractionResultWrapper<ItemStack> wrapper = super.a(world, entityhuman, enumhand); + InteractionResultWrapper<ItemStack> wrapper = super.a(world, entityhuman, enumhand);
+ if (wrapper.getResult() != EnumInteractionResult.FAIL) + if (wrapper.getResult() != EnumInteractionResult.FAIL) {
+ world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SPLASH_POTION_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemSplashPotion.i.nextFloat() * 0.4F + 0.8F)); world.playSound((EntityHuman) null, entityhuman.locX(), entityhuman.locY(), entityhuman.locZ(), SoundEffects.ENTITY_SPLASH_POTION_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (ItemSplashPotion.RANDOM.nextFloat() * 0.4F + 0.8F));
- return super.a(world, entityhuman, enumhand);
+ }
+ return wrapper; + return wrapper;
+ // Paper end + // Paper end
} }

View file

@ -23,13 +23,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // Paper end
if (!(entity instanceof EntityComplexPart)) { if (!(entity instanceof EntityComplexPart)) {
if (!(entity instanceof EntityLightning)) { EntityTypes<?> entitytypes = entity.getEntityType();
EntityTypes<?> entitytypes = entity.getEntityType(); int i = entitytypes.getChunkRange() * 16;
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} }
} }
@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit start - SPIGOT-5278 // CraftBukkit start - SPIGOT-5278
if (entity instanceof EntityDrowned) { if (entity instanceof EntityDrowned) {
this.navigators.add(((EntityDrowned) entity).navigationWater); this.navigators.add(((EntityDrowned) entity).navigationWater);
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.navigators.add(((EntityInsentient) entity).getNavigation()); this.navigators.add(((EntityInsentient) entity).getNavigation());
} }
entity.valid = true; // CraftBukkit entity.valid = true; // CraftBukkit

View file

@ -8,7 +8,7 @@ diff --git a/src/main/java/net/minecraft/server/EntityBee.java b/src/main/java/n
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityBee.java --- a/src/main/java/net/minecraft/server/EntityBee.java
+++ b/src/main/java/net/minecraft/server/EntityBee.java +++ b/src/main/java/net/minecraft/server/EntityBee.java
@@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements EntityBird { @@ -0,0 +0,0 @@ public class EntityBee extends EntityAnimal implements IEntityAngerable, EntityB
if (!this.hasHivePos()) { if (!this.hasHivePos()) {
return false; return false;
} else { } else {

View file

@ -9,7 +9,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/EntityLiving.java --- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
this.datawatcher.set(EntityLiving.ao, (byte) j); this.datawatcher.set(EntityLiving.an, (byte) j);
} }
- public void c(EnumHand enumhand) { - public void c(EnumHand enumhand) {
@ -22,10 +22,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (!itemstack.isEmpty() && !this.isHandRaised()) { - if (!itemstack.isEmpty() && !this.isHandRaised()) {
+ if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag + if (!itemstack.isEmpty() && !this.isHandRaised() || forceUpdate) { // Paper use override flag
this.activeItem = itemstack; this.activeItem = itemstack;
this.bl = itemstack.k(); this.bk = itemstack.k();
if (!this.world.isClientSide) { if (!this.world.isClientSide) {
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
this.clearActiveItem(); this.releaseActiveItem();
} else { } else {
if (!this.activeItem.isEmpty() && this.isHandRaised()) { if (!this.activeItem.isEmpty() && this.isHandRaised()) {
+ this.updateActiveItem(this.getRaisedHand(), true); // Paper + this.updateActiveItem(this.getRaisedHand(), true); // Paper
@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity {
this.a(this.getRaisedHand(), itemstack); this.a(this.getRaisedHand(), itemstack);
// CraftBukkit end // CraftBukkit end
this.dH(); this.clearActiveItem();
- // Paper start - if the replacement is anything but the default, update the client inventory - // Paper start - if the replacement is anything but the default, update the client inventory
- if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) { - if (this instanceof EntityPlayer && !com.google.common.base.Objects.equal(defaultReplacement, itemstack)) {
+ // Paper start + // Paper start

View file

@ -9,12 +9,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/BehaviorSleep.java --- a/src/main/java/net/minecraft/server/BehaviorSleep.java
+++ b/src/main/java/net/minecraft/server/BehaviorSleep.java +++ b/src/main/java/net/minecraft/server/BehaviorSleep.java
@@ -0,0 +0,0 @@ public class BehaviorSleep extends Behavior<EntityLiving> { @@ -0,0 +0,0 @@ public class BehaviorSleep extends Behavior<EntityLiving> {
if (optional.isPresent() && worldserver.getTime() - ((MinecraftSerializableLong) optional.get()).a() < 100L) { }
return false;
} else {
- IBlockData iblockdata = worldserver.getType(globalpos.getBlockPosition());
+ IBlockData iblockdata = worldserver.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper
+ if(iblockdata == null) return false; // Paper
return globalpos.getBlockPosition().a((IPosition) entityliving.getPositionVector(), 2.0D) && iblockdata.getBlock().a(TagsBlock.BEDS) && !(Boolean) iblockdata.get(BlockBed.OCCUPIED);
} }
- IBlockData iblockdata = worldserver.getType(globalpos.getBlockPosition());
+ IBlockData iblockdata = worldserver.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper
+ if (iblockdata == null) { return false; } // Paper
return globalpos.getBlockPosition().a((IPosition) entityliving.getPositionVector(), 2.0D) && iblockdata.getBlock().a((Tag) TagsBlock.BEDS) && !(Boolean) iblockdata.get(BlockBed.OCCUPIED);
}

View file

@ -267,7 +267,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ final ThrowableWithEquals other = (ThrowableWithEquals)obj; + final ThrowableWithEquals other = (ThrowableWithEquals)obj;
+ final StackTraceElement[] otherStackTrace = other.stacktrace; + final StackTraceElement[] otherStackTrace = other.stacktrace;
+ +
+ if (this.stacktrace.length != otherStackTrace.length) { + if (this.stacktrace.length != otherStackTrace.length || this.hash != other.hash) {
+ return false; + return false;
+ } + }
+ +
@ -305,7 +305,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
for (int i1 = i; i1 <= j; ++i1) { for (int i1 = i; i1 <= j; ++i1) {
for (int j1 = k; j1 <= l; ++j1) { for (int j1 = k; j1 <= l; ++j1) {
- Chunk chunk = this.getChunkProvider().getChunkAt(i1, j1, false); - Chunk chunk = ichunkprovider.getChunkAt(i1, j1, false);
+ Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper + Chunk chunk = (Chunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
if (chunk != null) { if (chunk != null) {
@ -332,7 +332,7 @@ diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World { @@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}; };
public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; public final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager;
// Paper end // Paper end
@ -343,5 +343,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // Paper end
// Add env and gen to constructor // Add env and gen to constructor, WorldData -> WorldDataServer
public WorldServer(MinecraftServer minecraftserver, Executor executor, WorldNBTStorage worldnbtstorage, WorldData worlddata, DimensionManager dimensionmanager, GameProfilerFiller gameprofilerfiller, WorldLoadListener worldloadlistener, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {

View file

@ -1,110 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Phoenix616 <mail@moep.tv>
Date: Mon, 13 Jan 2020 15:40:32 +0100
Subject: [PATCH] Seed based feature search
This fixes the issue where the server will load surrounding chunks up to
a radius of 100 chunks in order to search for features e.g. when running
the /locate command or for treasure maps (issue #2312).
This is done by using the same seed checking functionality that is used
by the server when generating these features before actually attempting
to load the chunk to check if a feature is available in it.
The only downside of this is that it breaks once the seed or generator
changes but this should usually not happen. A config option to disable
this improvement is added though in case that should ever be necessary.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
}
}
+ public boolean seedBasedFeatureSearch = true;
+ private void seedBasedFeatureSearch() {
+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch);
+ log("Feature search is based on seed: " + seedBasedFeatureSearch);
+ }
+
public int maxCollisionsPerEntity;
private void maxEntityCollision() {
maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) );
diff --git a/src/main/java/net/minecraft/server/BiomeManager.java b/src/main/java/net/minecraft/server/BiomeManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/BiomeManager.java
+++ b/src/main/java/net/minecraft/server/BiomeManager.java
@@ -0,0 +0,0 @@ public class BiomeManager {
this.c = genlayerzoomer;
}
+ public BiomeManager withProvider(WorldChunkManager worldchunkmanager) { return a(worldchunkmanager); } // Paper - OBFHELPER
public BiomeManager a(WorldChunkManager worldchunkmanager) {
return new BiomeManager(worldchunkmanager, this.b, this.c);
}
+ public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER
public BiomeBase a(BlockPosition blockposition) {
return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a);
}
diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
+++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
@@ -0,0 +0,0 @@ public class ChunkCoordIntPair {
}
}
+ public int getBlockX() { return d(); } // Paper - OBFHELPER
public int d() {
return this.x << 4;
}
+ public int getBlockZ() { return e(); } // Paper - OBFHELPER
public int e() {
return this.z << 4;
}
diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/StructureGenerator.java
+++ b/src/main/java/net/minecraft/server/StructureGenerator.java
@@ -0,0 +0,0 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
if (flag1 || flag2) {
ChunkCoordIntPair chunkcoordintpair = this.a(chunkgenerator, seededrandom, j, k, i1, j1);
if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper
+ // Paper start - seed based feature search
+ if (world.paperConfig.seedBasedFeatureSearch) {
+ BiomeManager biomeManager = world.getBiomeManager().withProvider(chunkgenerator.getWorldChunkManager());
+ BiomeBase biomeBase = biomeManager.getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9));
+ if (!shouldGenerate(biomeManager, chunkgenerator, seededrandom, chunkcoordintpair.x, chunkcoordintpair.z, biomeBase)) {
+ continue;
+ }
+ }
+ // Paper end
StructureStart structurestart = world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS).a(this.b());
if (structurestart != null && structurestart.e()) {
@@ -0,0 +0,0 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
return new ChunkCoordIntPair(i + k, j + l);
}
+ public boolean shouldGenerate(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int chunkX, int chunkZ, BiomeBase biomebase) { return a(biomemanager, chunkgenerator, random, chunkX, chunkZ, biomebase); } // Paper - OBFHELPER
public abstract boolean a(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int i, int j, BiomeBase biomebase);
public abstract StructureGenerator.a a();
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return this.methodProfiler;
}
- @Override
- public BiomeManager d() {
+ public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER
+ @Override public BiomeManager d() {
return this.biomeManager;
}
}

View file

@ -88,7 +88,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- public void a(NBTTagList nbttaglist, long[] along) { - public void a(NBTTagList nbttaglist, long[] along) {
+ public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize + public synchronized void a(NBTTagList nbttaglist, long[] along) { // Paper - synchronize
this.a(); this.a();
int i = Math.max(4, MathHelper.d(nbttaglist.size())); int i = Math.max(4, MathHelper.e(nbttaglist.size()));
@@ -0,0 +0,0 @@ public class DataPaletteBlock<T> implements DataPaletteExpandable<T> { @@ -0,0 +0,0 @@ public class DataPaletteBlock<T> implements DataPaletteExpandable<T> {
this.b(); this.b();

View file

@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 22 Jun 2019 04:20:47 -0700
Subject: [PATCH] Use ChunkStatus cache when saving protochunks
The cache should contain the chunk status when saving. If not it
will load it.
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
NBTTagCompound nbttagcompound;
if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) {
- nbttagcompound = this.readChunkData(chunkcoordintpair);
- if (nbttagcompound != null && ChunkRegionLoader.a(nbttagcompound) == ChunkStatus.Type.LEVELCHUNK) {
+ // Paper start - Optimize save by using status cache
+ ChunkStatus statusOnDisk = this.getChunkStatusOnDisk(chunkcoordintpair);
+ if (statusOnDisk != null && statusOnDisk.getType() == ChunkStatus.Type.LEVELCHUNK) {
+ // Paper end
return false;
}

View file

@ -25,39 +25,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/World.java --- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java
@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
return (CraftServer) Bukkit.getServer();
} }
public Chunk getChunkIfLoaded(int x, int z) {
- return ((ChunkProviderServer) this.chunkProvider).getChunkAt(x, z, false);
+ return ((ChunkProviderServer) this.chunkProvider).getChunkAtIfLoadedImmediately(x, z); // Paper
}
+ // Paper start + // Paper start
+ @Override + @Override
+ public boolean isChunkLoaded(int x, int z) { + public boolean isChunkLoaded(int x, int z) {
+ return getChunkIfLoaded(x, z) != null; + return ((WorldServer)this).getChunkIfLoaded(x, z) != null;
+ } + }
+
+
+ // Paper end + // Paper end
+
protected World(WorldData worlddata, DimensionManager dimensionmanager, java.util.concurrent.Executor executor, BiFunction<World, WorldProvider, IChunkProvider> bifunction, GameProfilerFiller gameprofilerfiller, boolean flag, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env) { // Paper - executor protected World(WorldDataMutable worlddatamutable, ResourceKey<World> resourcekey, ResourceKey<DimensionManager> resourcekey1, DimensionManager dimensionmanager, Supplier<GameProfilerFiller> supplier, boolean flag, boolean flag1, long i, org.bukkit.generator.ChunkGenerator gen, org.bukkit.World.Environment env, java.util.concurrent.Executor executor) {
this.spigotConfig = new org.spigotmc.SpigotWorldConfig( worlddata.getName() ); // Spigot this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((WorldDataServer) worlddatamutable).getName()); // Spigot
this.paperConfig = new com.destroystokyo.paper.PaperWorldConfig((((WorldDataServer)worlddatamutable).getName()), this.spigotConfig); // Paper
@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
} }
public boolean n(BlockPosition blockposition) { public boolean p(BlockPosition blockposition) {
- return isOutsideWorld(blockposition) ? false : this.chunkProvider.b(blockposition.getX() >> 4, blockposition.getZ() >> 4); - return isOutsideWorld(blockposition) ? false : this.getChunkProvider().b(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ return isOutsideWorld(blockposition) ? false : isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper + return isOutsideWorld(blockposition) ? false : isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper
} }
public boolean a(BlockPosition blockposition, Entity entity) { public boolean a(BlockPosition blockposition, Entity entity, EnumDirection enumdirection) {
if (isOutsideWorld(blockposition)) { if (isOutsideWorld(blockposition)) {
return false; return false;
} else { } else {
- IChunkAccess ichunkaccess = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false); - IChunkAccess ichunkaccess = this.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, ChunkStatus.FULL, false);
+ IChunkAccess ichunkaccess = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper + IChunkAccess ichunkaccess = this.getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper
return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a((IBlockAccess) this, blockposition, entity); return ichunkaccess == null ? false : ichunkaccess.getType(blockposition).a((IBlockAccess) this, blockposition, entity, enumdirection);
} }
@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -68,6 +64,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (chunk != null) { if (chunk != null) {
chunk.a(oclass, axisalignedbb, list, predicate); chunk.a(oclass, axisalignedbb, list, predicate);
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
public Chunk getChunkIfLoaded(int x, int z) {
- return this.chunkProvider.getChunkAt(x, z, false);
+ return this.chunkProvider.getChunkAtIfLoadedImmediately(x, z); // Paper
}
// Paper start - Asynchronous IO
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java --- a/src/main/java/org/spigotmc/ActivationRange.java

View file

@ -549,12 +549,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider { @@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.getMethodProfiler().enter("naturalSpawnCount");
this.world.timings.countNaturalMobs.startTiming(); // Paper - timings this.world.timings.countNaturalMobs.startTiming(); // Paper - timings
int l = this.chunkMapDistance.b(); int l = this.chunkMapDistance.b();
EnumCreatureType[] aenumcreaturetype = EnumCreatureType.values(); - SpawnerCreature.d spawnercreature_d = SpawnerCreature.a(l, this.world.z(), this::a);
- Object2IntMap<EnumCreatureType> object2intmap = this.world.l();
+ // Paper start - per player mob spawning + // Paper start - per player mob spawning
+ int[] worldMobCount; + SpawnerCreature.d spawnercreature_d; // moved down
+ if (this.playerChunkMap.playerMobDistanceMap != null) { + if (this.playerChunkMap.playerMobDistanceMap != null) {
+ // update distance map + // update distance map
+ this.world.timings.playerMobDistanceMapUpdate.startTiming(); + this.world.timings.playerMobDistanceMapUpdate.startTiming();
@ -564,40 +564,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (EntityPlayer player : this.world.players) { + for (EntityPlayer player : this.world.players) {
+ Arrays.fill(player.mobCounts, 0); + Arrays.fill(player.mobCounts, 0);
+ } + }
+ worldMobCount = this.world.countMobs(true); + spawnercreature_d = SpawnerCreature.countMobs(l, this.world.z(), this::a, true);
+ } else { + } else {
+ worldMobCount = this.world.countMobs(false); + spawnercreature_d = SpawnerCreature.countMobs(l, this.world.z(), this::a, false);
+ } + }
+ // Paper end + // Paper end
this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings
this.world.getMethodProfiler().exit();
@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider {
if (enumcreaturetype != EnumCreatureType.MISC && (!enumcreaturetype.c() || this.allowAnimals) && (enumcreaturetype.c() || this.allowMonsters) && (!enumcreaturetype.d() || flag2)) {
int k1 = limit * l / ChunkProviderServer.b; // CraftBukkit - use per-world limits
- if (object2intmap.getInt(enumcreaturetype) <= k1) { this.p = spawnercreature_d;
- SpawnerCreature.a(enumcreaturetype, this.world, chunk, blockposition);
+ // Paper start - only allow spawns upto the limit per chunk and update count afterwards
+ int currEntityCount = worldMobCount[enumcreaturetype.ordinal()];
+ int difference = k1 - currEntityCount;
+
+ if (this.world.paperConfig.perPlayerMobSpawns) {
+ int minDiff = Integer.MAX_VALUE;
+ for (EntityPlayer entityplayer : this.playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) {
+ minDiff = Math.min(limit - this.playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff);
+ }
+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
+ }
+
+ if (difference > 0) {
+ int spawnCount = SpawnerCreature.spawnMobs(enumcreaturetype, this.world, chunk, blockposition, difference,
+ this.world.paperConfig.perPlayerMobSpawns ? this.playerChunkMap::updatePlayerMobTypeMap : null);
+ worldMobCount[enumcreaturetype.ordinal()] += spawnCount;
+ // Paper end
}
}
}
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java --- a/src/main/java/net/minecraft/server/EntityPlayer.java
@ -626,30 +600,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
} }
+ public SectionPosition getPlayerMapSection() { return this.K(); } // Paper - OBFHELPER + public final SectionPosition getPlayerMapSection() { return this.N(); } // Paper - OBFHELPER
public SectionPosition K() { public SectionPosition N() {
return this.cs; return this.cq;
} }
diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/EntityTypes.java --- a/src/main/java/net/minecraft/server/EntityTypes.java
+++ b/src/main/java/net/minecraft/server/EntityTypes.java +++ b/src/main/java/net/minecraft/server/EntityTypes.java
@@ -0,0 +0,0 @@ public class EntityTypes<T extends Entity> { @@ -0,0 +0,0 @@ public class EntityTypes<T extends Entity> {
return this.bf; return this.bk;
} }
+ public EnumCreatureType getEnumCreatureType() { return this.e(); } // Paper - OBFHELPER + public final EnumCreatureType getEnumCreatureType() { return this.e(); } // Paper - OBFHELPER
public EnumCreatureType e() { public EnumCreatureType e() {
return this.bb; return this.bf;
} }
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
private final PlayerMap playerMap;
public final Int2ObjectMap<PlayerChunkMap.EntityTracker> trackedEntities; public final Int2ObjectMap<PlayerChunkMap.EntityTracker> trackedEntities;
private final Queue<Runnable> z; private final Long2ByteMap z;
private final Queue<Runnable> A; private final Queue<Runnable> getUnloadQueueTasks() { return this.A; } // Paper - OBFHELPER
- private int viewDistance; - private int viewDistance;
+ int viewDistance; // Paper - private -> package private + int viewDistance; // Paper - private -> package private
+ public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper + public final com.destroystokyo.paper.util.PlayerMobDistanceMap playerMobDistanceMap; // Paper
@ -658,7 +632,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final CallbackExecutor callbackExecutor = new CallbackExecutor(); public final CallbackExecutor callbackExecutor = new CallbackExecutor();
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.l = supplier; this.l = supplier;
this.m = new VillagePlace(new File(this.w, "poi"), datafixer, this.world); // Paper this.m = new VillagePlace(new File(this.w, "poi"), datafixer, flag, this.world); // Paper
this.setViewDistance(i); this.setViewDistance(i);
+ this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper + this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper
+ } + }
@ -685,117 +659,167 @@ diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java --- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java +++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -0,0 +0,0 @@ package net.minecraft.server;
import java.util.List;
import java.util.Objects;
import java.util.Random;
+import java.util.function.Consumer; // Paper
import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -0,0 +0,0 @@ public final class SpawnerCreature { @@ -0,0 +0,0 @@ public final class SpawnerCreature {
});
private static final Logger LOGGER = LogManager.getLogger(); public static SpawnerCreature.d a(int i, Iterable<Entity> iterable, SpawnerCreature.b spawnercreature_b) {
+ // Paper start - add countMobs parameter
+ // Paper start - add maxSpawns parameter and return spawned mobs + return countMobs(i, iterable, spawnercreature_b, false);
public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, BlockPosition blockposition) {
+ spawnMobs(enumcreaturetype, worldserver, chunk, blockposition, Integer.MAX_VALUE, null);
+ } + }
+ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, BlockPosition blockposition, int maxSpawns, Consumer<Entity> trackEntity) { + public static SpawnerCreature.d countMobs(int i, Iterable<Entity> iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) {
+ // Paper end + // Paper end - add countMobs parameter
ChunkGenerator<?> chunkgenerator = worldserver.getChunkProvider().getChunkGenerator(); SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities();
- int i = 0; Object2IntOpenHashMap<EnumCreatureType> object2intopenhashmap = new Object2IntOpenHashMap();
+ int i = 0; // Paper - force diff on name change Iterator iterator = iterable.iterator();
BlockPosition blockposition1 = getRandomPosition(worldserver, chunk);
int j = blockposition1.getX();
int k = blockposition1.getY();
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
);
if (!event.callEvent()) {
if (event.shouldAbortSpawn()) {
- return;
+ return i; // Paper
}
++i2;
continue;
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
} catch (Exception exception) {
SpawnerCreature.LOGGER.warn("Failed to create mob", exception);
ServerInternalException.reportInternalException(exception); // Paper
- return;
+ return i; // Paper
}
entityinsentient.setPositionRotation((double) f, (double) k, (double) f1, worldserver.random.nextFloat() * 360.0F, 0.0F);
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
groupdataentity = entityinsentient.prepare(worldserver, worldserver.getDamageScaler(new BlockPosition(entityinsentient)), EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null);
// CraftBukkit start
if (worldserver.addEntity(entityinsentient, SpawnReason.NATURAL)) {
- ++i;
+ ++i; // Paper - force diff on name change
++i2;
+ if (trackEntity != null) {
+ trackEntity.accept(entityinsentient); // Paper
+ }
}
+ if (i >= maxSpawns) { return i; } // Paper
// CraftBukkit end
if (i >= entityinsentient.getMaxSpawnGroup()) {
- return;
+ return i; // Paper
}
if (entityinsentient.c(i2)) {
@@ -0,0 +0,0 @@ public final class SpawnerCreature { @@ -0,0 +0,0 @@ public final class SpawnerCreature {
}
object2intopenhashmap.addTo(enumcreaturetype, 1);
+ // Paper start
+ if (countMobs) {
+ ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity);
+ }
+ // Paper end
});
} }
} }
+ return i; // Paper @@ -0,0 +0,0 @@ public final class SpawnerCreature {
} continue;
}
@Nullable + // Paper start - only allow spawns upto the limit per chunk and update count afterwards
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java + int currEntityCount = spawnercreature_d.getEntityCountsByType().getInt(enumcreaturetype);
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 + int k1 = limit * spawnercreature_d.getSpawnerChunks() / SpawnerCreature.b;
--- a/src/main/java/net/minecraft/server/WorldServer.java + int difference = k1 - currEntityCount;
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World {
}
public Object2IntMap<EnumCreatureType> l() {
- Object2IntMap<EnumCreatureType> object2intmap = new Object2IntOpenHashMap();
+ // Paper start
+ int[] values = this.countMobs(false);
+ EnumCreatureType[] byId = EnumCreatureType.values();
+ Object2IntMap<EnumCreatureType> ret = new Object2IntOpenHashMap<>();
+ +
+ for (int i = 0, len = values.length; i < len; ++i) { + if (worldserver.paperConfig.perPlayerMobSpawns) {
+ ret.put(byId[i], values[i]); + int minDiff = Integer.MAX_VALUE;
+ } + for (EntityPlayer entityplayer : worldserver.getChunkProvider().playerChunkMap.playerMobDistanceMap.getPlayersInRange(chunk.getPos())) {
+ + minDiff = Math.min(limit - worldserver.getChunkProvider().playerChunkMap.getMobCountNear(entityplayer, enumcreaturetype), minDiff);
+ return ret;
+ }
+ public int[] countMobs(boolean updatePlayerCounts) {
+ int[] ret = new int[EntityPlayer.ENUMCREATURETYPE_TOTAL_ENUMS];
+ // Paper end
ObjectIterator objectiterator = this.entitiesById.values().iterator();
while (objectiterator.hasNext()) {
@@ -0,0 +0,0 @@ public class WorldServer extends World {
continue;
}
// Paper end
- object2intmap.mergeInt(enumcreaturetype, 1, Integer::sum);
+ // Paper start - rework mob spawning
+ if (updatePlayerCounts) {
+ this.getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity);
+ } + }
+ ++ret[enumcreaturetype.ordinal()]; + difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
+ // Paper end + }
+ // Paper end
+
+ if (difference > 0) { // Paper
if ((flag || !enumcreaturetype.d()) && (flag1 || enumcreaturetype.d()) && (flag2 || !enumcreaturetype.e()) && spawnercreature_d.a(enumcreaturetype, limit)) {
// CraftBukkit end
- a(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> {
+ int spawnCount = spawnMobs(enumcreaturetype, worldserver, chunk, (entitytypes, blockposition, ichunkaccess) -> {
return spawnercreature_d.a(entitytypes, blockposition, ichunkaccess);
}, (entityinsentient, ichunkaccess) -> {
spawnercreature_d.a(entityinsentient, ichunkaccess);
+ },
+ limit, worldserver.paperConfig.perPlayerMobSpawns ? worldserver.getChunkProvider().playerChunkMap::updatePlayerMobTypeMap : null);
+ spawnercreature_d.getEntityCountsByType().mergeInt(enumcreaturetype, 0, (keyInMap, valueInMap) -> {
+ return Integer.valueOf(spawnCount + valueInMap.intValue());
});
+ } // Paper
} }
} }
- return object2intmap; @@ -0,0 +0,0 @@ public final class SpawnerCreature {
+ return ret;
} }
@Override public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) {
+ // Paper start - add parameters and int ret type
+ spawnMobs(enumcreaturetype, worldserver, chunk, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null);
+ }
+ public static int spawnMobs(EnumCreatureType enumcreaturetype, WorldServer worldserver, Chunk chunk, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer<Entity> trackEntity) {
+ // Paper end - add parameters and int ret type
BlockPosition blockposition = getRandomPosition(worldserver, chunk);
if (blockposition.getY() >= 1) {
- a(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a);
+ return spawnMobsInternal(enumcreaturetype, worldserver, (IChunkAccess) chunk, blockposition, spawnercreature_c, spawnercreature_a, maxSpawns, trackEntity);
}
+ return 0; // Paper
}
public static void a(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a) {
+ // Paper start - add maxSpawns parameter and return spawned mobs
+ spawnMobsInternal(enumcreaturetype, worldserver, ichunkaccess, blockposition, spawnercreature_c, spawnercreature_a, Integer.MAX_VALUE, null);
+ }
+ public static int spawnMobsInternal(EnumCreatureType enumcreaturetype, WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition blockposition, SpawnerCreature.c spawnercreature_c, SpawnerCreature.a spawnercreature_a, int maxSpawns, Consumer<Entity> trackEntity) {
+ // Paper end - add maxSpawns parameter and return spawned mobs
StructureManager structuremanager = worldserver.getStructureManager();
ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator();
int i = blockposition.getY();
IBlockData iblockdata = worldserver.getTypeIfLoadedAndInBounds(blockposition); // Paper - don't load chunks for mob spawn
+ int j = 0; // Paper - moved up
if (iblockdata != null && !iblockdata.isOccluding(ichunkaccess, blockposition)) { // Paper - don't load chunks for mob spawn
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
- int j = 0;
+ // Paper - moved up
int k = 0;
while (k < 3) {
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
// Paper start
Boolean doSpawning = a(worldserver, enumcreaturetype, structuremanager, chunkgenerator, biomebase_biomemeta, blockposition_mutableblockposition, d2);
if (doSpawning == null) {
- return;
+ return j; // Paper
}
if (doSpawning.booleanValue() && spawnercreature_c.test(biomebase_biomemeta.c, blockposition_mutableblockposition, ichunkaccess)) { // Paper end
EntityInsentient entityinsentient = a(worldserver, biomebase_biomemeta.c);
if (entityinsentient == null) {
- return;
+ return j; // Paper
}
entityinsentient.setPositionRotation(d0, (double) i, d1, worldserver.random.nextFloat() * 360.0F, 0.0F);
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
groupdataentity = entityinsentient.prepare(worldserver, worldserver.getDamageScaler(entityinsentient.getChunkCoordinates()), EnumMobSpawn.NATURAL, groupdataentity, (NBTTagCompound) null);
// CraftBukkit start
if (worldserver.addEntity(entityinsentient, SpawnReason.NATURAL)) {
- ++j;
+ ++j; // Paper - force diff on name change - we expect this to be the total amount spawned
++k1;
spawnercreature_a.run(entityinsentient, ichunkaccess);
+ // Paper start
+ if (trackEntity != null) {
+ trackEntity.accept(entityinsentient);
+ }
+ // Paper end
}
// CraftBukkit end
- if (j >= entityinsentient.getMaxSpawnGroup()) {
- return;
+ if (j >= entityinsentient.getMaxSpawnGroup() || j >= maxSpawns) { // Paper
+ return j; // Paper
}
if (entityinsentient.c(k1)) {
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
}
}
+ return j; // Paper
}
private static boolean a(WorldServer worldserver, IChunkAccess ichunkaccess, BlockPosition.MutableBlockPosition blockposition_mutableblockposition, double d0) {
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
public static class d {
- private final int a;
+ private final int a; final int getSpawnerChunks() { return this.a; } // Paper - OBFHELPER
private final Object2IntOpenHashMap<EnumCreatureType> b;
private final SpawnerCreatureProbabilities c;
- private final Object2IntMap<EnumCreatureType> d;
+ private final Object2IntMap<EnumCreatureType> d; final Object2IntMap<EnumCreatureType> getEntityCountsByType() { return this.d; } // Paper - OBFHELPER
@Nullable
private BlockPosition e;
@Nullable
@@ -0,0 +0,0 @@ public final class SpawnerCreature {
// CraftBukkit start
private boolean a(EnumCreatureType enumcreaturetype, int limit) {
- int i = limit * this.a / SpawnerCreature.b;
+ int i = limit * this.a / SpawnerCreature.b; // Paper - diff on change, needed in the spawn method
// CraftBukkit end
return this.b.getInt(enumcreaturetype) < i;

View file

@ -0,0 +1,319 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 9 Jun 2019 03:53:22 +0100
Subject: [PATCH] incremental chunk saving
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -0,0 +0,0 @@ public class PaperWorldConfig {
keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16);
log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16));
}
+
+ public int autoSavePeriod = -1;
+ private void autoSavePeriod() {
+ autoSavePeriod = getInt("auto-save-interval", -1);
+ if (autoSavePeriod > 0) {
+ log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)");
+ } else if (autoSavePeriod < 0) {
+ autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod;
+ }
+ }
+
+ public int maxAutoSaveChunksPerTick = 24;
+ private void maxAutoSaveChunksPerTick() {
+ maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24);
+ }
}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
private TickList<Block> o;
private TickList<FluidType> p;
private boolean q;
- private long lastSaved;
+ public long lastSaved; // Paper
private volatile boolean s;
private long inhabitedTime;
@Nullable
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -0,0 +0,0 @@ public class ChunkProviderServer extends IChunkProvider {
} // Paper - Timings
}
+ // Paper start - duplicate save, but call incremental
+ public void saveIncrementally() {
+ this.tickDistanceManager();
+ try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings
+ this.playerChunkMap.saveIncrementally();
+ } // Paper - Timings
+ }
+ // Paper end
+
@Override
public void close() throws IOException {
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
public static int currentTick = 0; // Paper - Further improve tick loop
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
public int autosavePeriod;
+ public boolean serverAutoSave = false; // Paper
public File bukkitDataPackFolder;
public CommandDispatcher vanillaCommandDispatcher;
private boolean forceTicks;
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
this.serverPing.b().a(agameprofile);
}
- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit
- MinecraftServer.LOGGER.debug("Autosave started");
+ //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down
+ //MinecraftServer.LOGGER.debug("Autosave started"); // Paper
+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper
this.methodProfiler.enter("save");
+ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper
this.playerList.savePlayers();
- this.saveChunks(true, false, false);
+ }// Paper
+ // Paper start
+ for (WorldServer world : getWorlds()) {
+ if (world.paperConfig.autoSavePeriod > 0) {
+ try {
+ world.saveIncrementally(serverAutoSave);
+ } catch (ExceptionWorldConflict exceptionWorldConflict) {
+ MinecraftServer.LOGGER.warn(exceptionWorldConflict.getMessage());
+ }
+ }
+ }
+ // Paper end
+
this.methodProfiler.exit();
- MinecraftServer.LOGGER.debug("Autosave finished");
- }
+ //MinecraftServer.LOGGER.debug("Autosave finished"); // Paper
+ //} // Paper
this.methodProfiler.enter("snooper");
if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -0,0 +0,0 @@ public class PlayerChunk {
private final PlayerChunkMap chunkMap; // Paper
+ long lastAutoSaveTime; // Paper - incremental autosave
+ long inactiveTimeStart; // Paper - incremental autosave
+
public PlayerChunk(ChunkCoordIntPair chunkcoordintpair, int i, LightEngine lightengine, PlayerChunk.c playerchunk_c, PlayerChunk.d playerchunk_d) {
this.statusFutures = new AtomicReferenceArray(PlayerChunk.CHUNK_STATUSES.size());
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
@@ -0,0 +0,0 @@ public class PlayerChunk {
boolean flag2 = playerchunk_state.isAtLeast(PlayerChunk.State.BORDER);
boolean flag3 = playerchunk_state1.isAtLeast(PlayerChunk.State.BORDER);
+ boolean prevHasBeenLoaded = this.hasBeenLoaded; // Paper
this.hasBeenLoaded |= flag3;
+ // Paper start - incremental autosave
+ if (this.hasBeenLoaded & !prevHasBeenLoaded) {
+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime;
+ if (timeSinceAutoSave < 0) {
+ // safest bet is to assume autosave is needed here
+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod;
+ }
+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave;
+ this.chunkMap.autoSaveQueue.add(this);
+ }
+ // Paper end
if (!flag2 && flag3) {
// Paper start - cache ticking ready status
int expectCreateCount = ++this.fullChunkCreateCount;
@@ -0,0 +0,0 @@ public class PlayerChunk {
}
public void m() {
+ boolean prev = this.hasBeenLoaded; // Paper
+ this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER);
+ // Paper start - incremental autosave
+ if (prev != this.hasBeenLoaded) {
+ if (this.hasBeenLoaded) {
+ long timeSinceAutoSave = this.inactiveTimeStart - this.lastAutoSaveTime;
+ if (timeSinceAutoSave < 0) {
+ // safest bet is to assume autosave is needed here
+ timeSinceAutoSave = this.chunkMap.world.paperConfig.autoSavePeriod;
+ }
+ this.lastAutoSaveTime = this.chunkMap.world.getTime() - timeSinceAutoSave;
+ this.chunkMap.autoSaveQueue.add(this);
+ } else {
+ this.inactiveTimeStart = this.chunkMap.world.getTime();
+ this.chunkMap.autoSaveQueue.remove(this);
+ }
+ }
+ // Paper end
+ }
+
+ // Paper start - incremental autosave
+ public boolean setHasBeenLoaded() {
this.hasBeenLoaded = getChunkState(this.ticketLevel).isAtLeast(PlayerChunk.State.BORDER);
+ return this.hasBeenLoaded;
}
+ // Paper end
public void a(ProtoChunkExtension protochunkextension) {
for (int i = 0; i < this.statusFutures.length(); ++i) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
+ // Paper start - incremental autosave
+ final it.unimi.dsi.fastutil.objects.ObjectRBTreeSet<PlayerChunk> autoSaveQueue = new it.unimi.dsi.fastutil.objects.ObjectRBTreeSet<>((playerchunk1, playerchunk2) -> {
+ int timeCompare = Long.compare(playerchunk1.lastAutoSaveTime, playerchunk2.lastAutoSaveTime);
+ if (timeCompare != 0) {
+ return timeCompare;
+ }
+
+ return Long.compare(MCUtil.getCoordinateKey(playerchunk1.location), MCUtil.getCoordinateKey(playerchunk2.location));
+ });
+
+ protected void saveIncrementally() {
+ int savedThisTick = 0;
+ // optimized since we search far less chunks to hit ones that need to be saved
+ List<PlayerChunk> reschedule = new java.util.ArrayList<>(this.world.paperConfig.maxAutoSaveChunksPerTick);
+ long currentTick = this.world.getTime();
+ long maxSaveTime = currentTick - this.world.paperConfig.autoSavePeriod;
+
+ for (Iterator<PlayerChunk> iterator = this.autoSaveQueue.iterator(); iterator.hasNext();) {
+ PlayerChunk playerchunk = iterator.next();
+ if (playerchunk.lastAutoSaveTime > maxSaveTime) {
+ break;
+ }
+
+ iterator.remove();
+
+ IChunkAccess ichunkaccess = playerchunk.getChunkSave().getNow(null);
+ if (ichunkaccess instanceof Chunk) {
+ boolean shouldSave = ((Chunk)ichunkaccess).lastSaved <= maxSaveTime;
+
+ if (shouldSave && this.saveChunk(ichunkaccess)) {
+ ++savedThisTick;
+
+ if (!playerchunk.setHasBeenLoaded()) {
+ // do not fall through to reschedule logic
+ playerchunk.inactiveTimeStart = currentTick;
+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) {
+ break;
+ }
+ continue;
+ }
+ }
+ }
+
+ reschedule.add(playerchunk);
+
+ if (savedThisTick >= this.world.paperConfig.maxAutoSaveChunksPerTick) {
+ break;
+ }
+ }
+
+ for (int i = 0, len = reschedule.size(); i < len; ++i) {
+ PlayerChunk playerchunk = reschedule.get(i);
+ playerchunk.lastAutoSaveTime = this.world.getTime();
+ this.autoSaveQueue.add(playerchunk);
+ }
+ }
+ // Paper end
+
protected void save(boolean flag) {
if (flag) {
List<PlayerChunk> list = (List) this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).peek(PlayerChunk::m).collect(Collectors.toList());
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.world.unloadChunk(chunk);
}
+ this.autoSaveQueue.remove(playerchunk); // Paper
this.lightEngine.a(ichunkaccess.getPos());
this.lightEngine.queueUpdate();
@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
playerchunk.a(new ProtoChunkExtension(chunk));
}
+ chunk.setLastSaved(this.world.getTime() - 1); // Paper - avoid autosaving newly generated/loaded chunks
+
chunk.a(() -> {
return PlayerChunk.getChunkState(playerchunk.getTicketLevel());
});
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
return !this.server.a(this, blockposition, entityhuman) && this.getWorldBorder().a(blockposition);
}
+ // Paper start - derived from below
+ public void saveIncrementally(boolean doFull) {
+ ChunkProviderServer chunkproviderserver = this.getChunkProvider();
+
+ if (doFull) {
+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld()));
+ }
+
+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) {
+ if (doFull) {
+ this.saveData();
+ }
+
+ timings.worldSaveChunks.startTiming(); // Paper
+ if (!this.isSavingDisabled()) chunkproviderserver.saveIncrementally();
+ timings.worldSaveChunks.stopTiming(); // Paper
+
+
+ // Copied from save()
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
+ if (doFull) { // Paper
+ WorldServer worldserver1 = this;
+
+ worldDataServer.a(worldserver1.getWorldBorder().t());
+ worldDataServer.setCustomBossEvents(this.server.getBossBattleCustomData().save());
+ convertable.a(this.server.f, this.worldDataServer, this.server.getPlayerList().save());
+ }
+ // CraftBukkit end
+ }
+ }
+ // Paper end
+
public void save(@Nullable IProgressUpdate iprogressupdate, boolean flag, boolean flag1) {
ChunkProviderServer chunkproviderserver = this.getChunkProvider();
if (!flag1) {
- org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
+ if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit // Paper
try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper
if (iprogressupdate != null) {
iprogressupdate.a(new ChatMessage("menu.savingLevel"));
@@ -0,0 +0,0 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit end
}
+ private void saveData() { this.ag(); } // Paper - OBFHELPER
private void ag() {
if (this.dragonBattle != null) {
this.server.getSaveData().a(this.dragonBattle.a());

View file

@ -94,7 +94,7 @@ done
# import FileName # import FileName
import VoxelShapeSpliterator
######################################################## ########################################################
######################################################## ########################################################