From c063f92ff104fc4f05585b6fcc871ed63f960d93 Mon Sep 17 00:00:00 2001 From: Sotr Date: Tue, 28 Aug 2018 23:46:03 +0800 Subject: [PATCH] Minecraft 1.13.1 --- sources/pom.xml | 112 +++--- .../paper/antixray/ChunkPacketInfo.java | 82 +++++ .../paper/antixray/DataBitsReader.java | 62 ++++ .../paper/antixray/DataBitsWriter.java | 94 +++++ .../server/core/AkarinSlackScheduler.java | 2 +- .../mixin/core/MixinMinecraftServer.java | 23 +- .../mixin/cps/MixinChunkProviderServer.java | 89 ----- .../server/mixin/cps/MixinCraftWorld.java | 39 -- .../nsc/NonblockingServerConnection.java | 2 +- .../mixin/nsc/OptimisticNetworkManager.java | 61 ++++ .../MixinPersistentCollection.java | 48 --- .../minecraft/server/ChunkProviderServer.java | 336 ++++++++---------- .../java/net/minecraft/server/Entity.java | 200 +++++------ .../net/minecraft/server/EntityPlayer.java | 272 +++++++------- .../net/minecraft/server/ItemEnderEye.java | 10 +- .../net/minecraft/server/NetworkManager.java | 41 ++- .../server/PacketPlayOutMapChunk.java | 56 ++- .../minecraft/server/PlayerConnection.java | 72 ++-- .../net/minecraft/server/TileEntitySkull.java | 8 +- .../net/minecraft/server/WorldServer.java | 213 +++++------ .../org/bukkit/craftbukkit/CraftServer.java | 67 ++-- .../craftbukkit/entity/CraftPlayer.java | 12 +- .../java/org/bukkit/plugin/EventExecutor.java | 105 ------ .../main/resources/mixins.akarin.core.json | 1 + .../mixins.akarin.optimization.chunk.json | 11 - work/Paper | 2 +- 26 files changed, 1059 insertions(+), 961 deletions(-) create mode 100644 sources/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java create mode 100644 sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java create mode 100644 sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/cps/MixinCraftWorld.java create mode 100644 sources/src/main/java/io/akarin/server/mixin/nsc/OptimisticNetworkManager.java delete mode 100644 sources/src/main/java/io/akarin/server/mixin/optimization/MixinPersistentCollection.java delete mode 100644 sources/src/main/java/org/bukkit/plugin/EventExecutor.java delete mode 100644 sources/src/main/resources/mixins.akarin.optimization.chunk.json diff --git a/sources/pom.xml b/sources/pom.xml index 94a15ae9e..95dd3a78c 100644 --- a/sources/pom.xml +++ b/sources/pom.xml @@ -3,15 +3,15 @@ 4.0.0 akarin jar - 1.13-R0.1-SNAPSHOT + 1.13.1-R0.1-SNAPSHOT Akarin https://github.com/Akarin-project/Akarin UTF-8 - 1.13-R0.1-SNAPSHOT - 1.13 - 1_13_R1 + 1.13.1-R0.1-SNAPSHOT + 1.13.1 + 1_13_R2 git-Bukkit- yyyyMMdd-HHmm @@ -44,6 +44,59 @@ ${minecraft.version}-SNAPSHOT compile + + net.minecrell + terminalconsoleappender + 1.1.1 + + + net.java.dev.jna + jna + 4.5.2 + runtime + + + + org.apache.logging.log4j + log4j-core + 2.8.1 + compile + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.8.1 + runtime + + + org.apache.logging.log4j + log4j-iostreams + 2.8.1 + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.8.1 + runtime + + + org.apache.logging.log4j + log4j-iostreams + 2.8.1 + + + + com.lmax + disruptor + 3.4.2 + runtime + org.ow2.asm asm @@ -68,53 +121,6 @@ 3.0.3 compile - - - net.minecrell - terminalconsoleappender - 1.1.1 - - - net.java.dev.jna - jna - 4.5.2 - runtime - - - - - org.apache.logging.log4j - log4j-core - 2.8.1 - compile - - - - - org.apache.logging.log4j - log4j-slf4j-impl - 2.8.1 - runtime - - - org.apache.logging.log4j - log4j-iostreams - 2.8.1 - - - - - com.lmax - disruptor - 3.4.2 - runtime - - junit @@ -128,12 +134,11 @@ 1.3 test - io.akarin legacylauncher - 2.0 + 2.1 org.spongepowered @@ -210,6 +215,7 @@ net.minecraft.launchwrapper.Launch CraftBukkit + ${describe} ${maven.build.timestamp} Bukkit diff --git a/sources/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java b/sources/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java new file mode 100644 index 000000000..599ea3267 --- /dev/null +++ b/sources/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketInfo.java @@ -0,0 +1,82 @@ +package com.destroystokyo.paper.antixray; + +import io.netty.buffer.ByteBuf; +import net.minecraft.server.Chunk; +import net.minecraft.server.DataPalette; +import net.minecraft.server.PacketPlayOutMapChunk; + +public class ChunkPacketInfo { + + private final PacketPlayOutMapChunk packetPlayOutMapChunk; + private final Chunk chunk; + private final int chunkSectionSelector; + private ByteBuf data; // Akarin + private final int[] bitsPerObject = new int[16]; + private final Object[] dataPalettes = new Object[16]; + private final int[] dataBitsIndexes = new int[16]; + private final Object[][] predefinedObjects = new Object[16][]; + + public ChunkPacketInfo(PacketPlayOutMapChunk packetPlayOutMapChunk, Chunk chunk, int chunkSectionSelector) { + this.packetPlayOutMapChunk = packetPlayOutMapChunk; + this.chunk = chunk; + this.chunkSectionSelector = chunkSectionSelector; + } + + public PacketPlayOutMapChunk getPacketPlayOutMapChunk() { + return packetPlayOutMapChunk; + } + + public Chunk getChunk() { + return chunk; + } + + public int getChunkSectionSelector() { + return chunkSectionSelector; + } + + public ByteBuf getData() { // Akarin + return data; + } + + public void setData(ByteBuf data) { // Akarin + this.data = data; + } + + public int getBitsPerObject(int chunkSectionIndex) { + return bitsPerObject[chunkSectionIndex]; + } + + public void setBitsPerObject(int chunkSectionIndex, int bitsPerObject) { + this.bitsPerObject[chunkSectionIndex] = bitsPerObject; + } + + @SuppressWarnings("unchecked") + public DataPalette getDataPalette(int chunkSectionIndex) { + return (DataPalette) dataPalettes[chunkSectionIndex]; + } + + public void setDataPalette(int chunkSectionIndex, DataPalette dataPalette) { + dataPalettes[chunkSectionIndex] = dataPalette; + } + + public int getDataBitsIndex(int chunkSectionIndex) { + return dataBitsIndexes[chunkSectionIndex]; + } + + public void setDataBitsIndex(int chunkSectionIndex, int dataBitsIndex) { + dataBitsIndexes[chunkSectionIndex] = dataBitsIndex; + } + + @SuppressWarnings("unchecked") + public T[] getPredefinedObjects(int chunkSectionIndex) { + return (T[]) predefinedObjects[chunkSectionIndex]; + } + + public void setPredefinedObjects(int chunkSectionIndex, T[] predefinedObjects) { + this.predefinedObjects[chunkSectionIndex] = predefinedObjects; + } + + public boolean isWritten(int chunkSectionIndex) { + return bitsPerObject[chunkSectionIndex] != 0; + } +} diff --git a/sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java b/sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java new file mode 100644 index 000000000..49178aad1 --- /dev/null +++ b/sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsReader.java @@ -0,0 +1,62 @@ +package com.destroystokyo.paper.antixray; + +import io.netty.buffer.ByteBuf; + +public class DataBitsReader { + + private ByteBuf dataBits; // Akarin + private int bitsPerObject; + private int mask; + private int longInDataBitsIndex; + private int bitInLongIndex; + private long current; + + public void setDataBits(ByteBuf dataBits) { // Akarin + this.dataBits = dataBits; + } + + public void setBitsPerObject(int bitsPerObject) { + this.bitsPerObject = bitsPerObject; + mask = (1 << bitsPerObject) - 1; + } + + public void setIndex(int index) { + this.longInDataBitsIndex = index; + bitInLongIndex = 0; + init(); + } + + private void init() { + if (dataBits.capacity() > longInDataBitsIndex + 7) { // Akarin + // Akarin start + dataBits.getLong(longInDataBitsIndex); + /* + current = ((((long) dataBits[longInDataBitsIndex]) << 56) + | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) + | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) + | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) + | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) + | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) + | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) + | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); + */ // Akarin end + } + } + + public int read() { + int value = (int) (current >>> bitInLongIndex) & mask; + bitInLongIndex += bitsPerObject; + + if (bitInLongIndex > 63) { + bitInLongIndex -= 64; + longInDataBitsIndex += 8; + init(); + + if (bitInLongIndex > 0) { + value |= current << bitsPerObject - bitInLongIndex & mask; + } + } + + return value; + } +} diff --git a/sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java b/sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java new file mode 100644 index 000000000..481669677 --- /dev/null +++ b/sources/src/main/java/com/destroystokyo/paper/antixray/DataBitsWriter.java @@ -0,0 +1,94 @@ +package com.destroystokyo.paper.antixray; + +import io.netty.buffer.ByteBuf; + +public class DataBitsWriter { + + private ByteBuf dataBits; // Akarin + private int bitsPerObject; + private long mask; + private int longInDataBitsIndex; + private int bitInLongIndex; + private long current; + private boolean dirty; + + public void setDataBits(ByteBuf dataBits) { // Akarin + this.dataBits = dataBits; + } + + public void setBitsPerObject(int bitsPerObject) { + this.bitsPerObject = bitsPerObject; + mask = (1 << bitsPerObject) - 1; + } + + public void setIndex(int index) { + this.longInDataBitsIndex = index; + bitInLongIndex = 0; + init(); + } + + private void init() { + if (dataBits.capacity() > longInDataBitsIndex + 7) { // Akarin + // Akarin start + current = dataBits.getLong(longInDataBitsIndex); + /* + current = ((((long) dataBits[longInDataBitsIndex]) << 56) + | (((long) dataBits[longInDataBitsIndex + 1] & 0xff) << 48) + | (((long) dataBits[longInDataBitsIndex + 2] & 0xff) << 40) + | (((long) dataBits[longInDataBitsIndex + 3] & 0xff) << 32) + | (((long) dataBits[longInDataBitsIndex + 4] & 0xff) << 24) + | (((long) dataBits[longInDataBitsIndex + 5] & 0xff) << 16) + | (((long) dataBits[longInDataBitsIndex + 6] & 0xff) << 8) + | (((long) dataBits[longInDataBitsIndex + 7] & 0xff))); + */ // Akarin end + } + + dirty = false; + } + + public void finish() { + if (dirty && dataBits.capacity() > longInDataBitsIndex + 7) { // Akarin + // Akarin start + dataBits.setLong(longInDataBitsIndex, current); + /* + dataBits[longInDataBitsIndex] = (byte) (current >> 56 & 0xff); + dataBits[longInDataBitsIndex + 1] = (byte) (current >> 48 & 0xff); + dataBits[longInDataBitsIndex + 2] = (byte) (current >> 40 & 0xff); + dataBits[longInDataBitsIndex + 3] = (byte) (current >> 32 & 0xff); + dataBits[longInDataBitsIndex + 4] = (byte) (current >> 24 & 0xff); + dataBits[longInDataBitsIndex + 5] = (byte) (current >> 16 & 0xff); + dataBits[longInDataBitsIndex + 6] = (byte) (current >> 8 & 0xff); + dataBits[longInDataBitsIndex + 7] = (byte) (current & 0xff); + */ // Akarin end + } + } + + public void write(int value) { + current = current & ~(mask << bitInLongIndex) | (value & mask) << bitInLongIndex; + dirty = true; + bitInLongIndex += bitsPerObject; + + if (bitInLongIndex > 63) { + finish(); + bitInLongIndex -= 64; + longInDataBitsIndex += 8; + init(); + + if (bitInLongIndex > 0) { + current = current & ~(mask >>> bitsPerObject - bitInLongIndex) | (value & mask) >>> bitsPerObject - bitInLongIndex; + dirty = true; + } + } + } + + public void skip() { + bitInLongIndex += bitsPerObject; + + if (bitInLongIndex > 63) { + finish(); + bitInLongIndex -= 64; + longInDataBitsIndex += 8; + init(); + } + } +} diff --git a/sources/src/main/java/io/akarin/server/core/AkarinSlackScheduler.java b/sources/src/main/java/io/akarin/server/core/AkarinSlackScheduler.java index 5549afd10..57baf007b 100644 --- a/sources/src/main/java/io/akarin/server/core/AkarinSlackScheduler.java +++ b/sources/src/main/java/io/akarin/server/core/AkarinSlackScheduler.java @@ -77,7 +77,7 @@ public class AkarinSlackScheduler extends Thread { // Force hardcore difficulty, from WorldServer#doTick if (AkarinGlobalConfig.forceHardcoreDifficulty) - for (WorldServer world : server.worlds) { + for (WorldServer world : server.getWorlds()) { if (world.getWorldData().isHardcore() && world.getDifficulty() != EnumDifficulty.HARD) { world.getWorldData().setDifficulty(EnumDifficulty.HARD); } diff --git a/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java b/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java index a29789cc8..6b8aa2363 100644 --- a/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java +++ b/sources/src/main/java/io/akarin/server/mixin/core/MixinMinecraftServer.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Queue; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; +import java.util.function.BooleanSupplier; import javax.activation.FileDataSource; @@ -80,11 +81,11 @@ public abstract class MixinMinecraftServer { * Parallel world ticking */ @Shadow public CraftServer server; - @Shadow @Mutable protected Queue> g; + @Shadow @Mutable protected Queue> f; @Shadow public Queue processQueue; @Shadow private int ticks; @Shadow public List worlds; - @Shadow(aliases = "l") @Final private List tickables; + @Shadow(aliases = "k") @Final private List tickables; @Shadow public abstract CustomFunctionData getFunctionData(); @Shadow public abstract ServerConnection getServerConnection(); @@ -109,10 +110,10 @@ public abstract class MixinMinecraftServer { return true; } - private void tickWorld(WorldServer world) { + private void tickWorld(WorldServer world, BooleanSupplier supplier) { try { world.timings.doTick.startTiming(); - world.doTick(); + world.doTick(supplier); world.timings.doTick.stopTiming(); } catch (Throwable throwable) { CrashReport crashreport; @@ -127,7 +128,7 @@ public abstract class MixinMinecraftServer { } @Overwrite - public void w() throws InterruptedException, ExecutionException { + public void b(BooleanSupplier supplier) throws InterruptedException, ExecutionException { Runnable runnable; MinecraftTimings.bukkitSchedulerTimer.startTiming(); this.server.getScheduler().mainThreadHeartbeat(this.ticks); @@ -135,8 +136,8 @@ public abstract class MixinMinecraftServer { MinecraftTimings.minecraftSchedulerTimer.startTiming(); FutureTask task; - int count = g.size(); - while (count-- > 0 && (task = g.poll()) != null) { + int count = f.size(); + while (count-- > 0 && (task = f.poll()) != null) { SystemUtils.a(task, MinecraftServer.LOGGER); } MinecraftTimings.minecraftSchedulerTimer.stopTiming(); @@ -176,7 +177,7 @@ public abstract class MixinMinecraftServer { Akari.STAGE_TICK.submit(() -> { WorldServer world = worlds.get(fi); synchronized (((IMixinWorldServer) world).tickLock()) { - tickWorld(world); + tickWorld(world, supplier); } }, null); } @@ -187,7 +188,7 @@ public abstract class MixinMinecraftServer { for (int i = 0; i < cachedWorldSize; i++) { WorldServer world = worlds.get(i); synchronized (((IMixinWorldServer) world).tickLock()) { - tickWorld(world); + tickWorld(world, supplier); } } }, null); @@ -218,7 +219,7 @@ public abstract class MixinMinecraftServer { for (int i = 0; i < cachedWorldSize; ++i) { WorldServer world = worlds.get(i); synchronized (((IMixinWorldServer) world).tickLock()) { - tickWorld(world); + tickWorld(world, supplier); } } }, null); @@ -229,7 +230,7 @@ public abstract class MixinMinecraftServer { case -1: for (int i = 0; i < cachedWorldSize; ++i) { WorldServer world = worlds.get(i); - tickWorld(world); + tickWorld(world, supplier); tickEntities(world); } break; diff --git a/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java b/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java deleted file mode 100644 index 43ec58823..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/cps/MixinChunkProviderServer.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.akarin.server.mixin.cps; - -import org.spigotmc.SlackActivityAccountant; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectIterator; -import net.minecraft.server.Chunk; -import net.minecraft.server.ChunkProviderServer; -import net.minecraft.server.ChunkTaskScheduler; -import net.minecraft.server.IChunkLoader; -import net.minecraft.server.WorldServer; - -@Mixin(value = ChunkProviderServer.class, remap = false) -public abstract class MixinChunkProviderServer { - @Shadow @Final public WorldServer world; - @Shadow public Long2ObjectMap chunks; - @Shadow(aliases = "f") @Final private ChunkTaskScheduler scheduler; - - public void unload(Chunk chunk) { - if (this.world.worldProvider.a(chunk.locX, chunk.locZ)) { - // Akarin - avoid using the queue and simply check the unloaded flag during unloads - // this.unloadQueue.add(Long.valueOf(ChunkCoordIntPair.a(chunk.locX, chunk.locZ))); - chunk.setShouldUnload(true); - } - } - - @Shadow public abstract boolean unloadChunk(Chunk chunk, boolean save); - @Shadow @Final private IChunkLoader chunkLoader; - @Shadow @Final private static double UNLOAD_QUEUE_RESIZE_FACTOR; - - @Overwrite - public boolean unloadChunks() { - if (!this.world.savingDisabled) { - long now = System.currentTimeMillis(); - long unloadAfter = world.paperConfig.delayChunkUnloadsBy; - SlackActivityAccountant activityAccountant = world.getMinecraftServer().slackActivityAccountant; - activityAccountant.startActivity(0.5); - - ObjectIterator> it = chunks.long2ObjectEntrySet().iterator(); - int remainingChunks = chunks.size(); - int targetSize = Math.min(remainingChunks - 100, (int) (remainingChunks * UNLOAD_QUEUE_RESIZE_FACTOR)); // Paper - Make more aggressive - - while (it.hasNext()) { - Entry entry = it.next(); - Chunk chunk = entry.getValue(); - - if (chunk != null && chunk.isUnloading()) { - if (chunk.scheduledForUnload != null) { - if (now - chunk.scheduledForUnload <= unloadAfter) continue; - } - - if (unloadChunk(chunk, true)) { - it.remove(); - } - chunk.setShouldUnload(false); - chunk.scheduledForUnload = null; - - if (--remainingChunks <= targetSize && activityAccountant.activityTimeIsExhausted()) break; - } - } - activityAccountant.endActivity(); - - this.scheduler.a(); - this.chunkLoader.b(); // OBFHELPER: chunkTick - } - return false; - } - - @Redirect(method = "unloadChunk", at = @At( - value = "INVOKE", - target = "it/unimi/dsi/fastutil/longs/Long2ObjectMap.remove(J)Ljava/lang/Object;" - )) - private Object remove(Long2ObjectOpenHashMap chunks, long chunkHash) { - return null; - } - - @Overwrite - public String getName() { - return "ServerChunkCache: " + chunks.size(); - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/cps/MixinCraftWorld.java b/sources/src/main/java/io/akarin/server/mixin/cps/MixinCraftWorld.java deleted file mode 100644 index 0415e3d76..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/cps/MixinCraftWorld.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.akarin.server.mixin.cps; - -import java.util.Set; - -import org.bukkit.craftbukkit.CraftWorld; -import org.spongepowered.asm.lib.Opcodes; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import net.minecraft.server.Chunk; -import net.minecraft.server.WorldServer; - -@Mixin(value = CraftWorld.class, remap = false) -public abstract class MixinCraftWorld { - @Shadow @Final private WorldServer world; - - @Redirect(method = "processChunkGC()V", at = @At( - value = "INVOKE", - target = "it/unimi/dsi/fastutil/longs/LongSet.contains(J)Z", - opcode = Opcodes.INVOKEINTERFACE - )) - public boolean checkUnloading(Set set, Object chunkHash) { - return false; - } - - @Redirect(method = "regenerateChunk", at = @At( - value = "INVOKE", - target = "it/unimi/dsi/fastutil/longs/LongSet.remove(J)Z", - opcode = Opcodes.INVOKEINTERFACE - )) - public boolean regenChunk(Set set, Object chunkHash) { - Chunk chunk = world.getChunkProviderServer().chunks.get(chunkHash); - if (chunk != null) chunk.setShouldUnload(false); - return true; - } -} diff --git a/sources/src/main/java/io/akarin/server/mixin/nsc/NonblockingServerConnection.java b/sources/src/main/java/io/akarin/server/mixin/nsc/NonblockingServerConnection.java index 66e1d00e2..1f10fdc48 100644 --- a/sources/src/main/java/io/akarin/server/mixin/nsc/NonblockingServerConnection.java +++ b/sources/src/main/java/io/akarin/server/mixin/nsc/NonblockingServerConnection.java @@ -75,7 +75,7 @@ public abstract class NonblockingServerConnection { Class channelClass; EventLoopGroup loopGroup; - if (Epoll.isAvailable() && this.server.X()) { // OBFHELPER: MinecraftServer::useNativeTransport + if (Epoll.isAvailable() && this.server.V()) { // OBFHELPER: MinecraftServer::useNativeTransport channelClass = EpollServerSocketChannel.class; loopGroup = ServerConnection.b.a(); logger.info("Using epoll channel type"); diff --git a/sources/src/main/java/io/akarin/server/mixin/nsc/OptimisticNetworkManager.java b/sources/src/main/java/io/akarin/server/mixin/nsc/OptimisticNetworkManager.java new file mode 100644 index 000000000..b0a3f2c59 --- /dev/null +++ b/sources/src/main/java/io/akarin/server/mixin/nsc/OptimisticNetworkManager.java @@ -0,0 +1,61 @@ +package io.akarin.server.mixin.nsc; + +import java.util.Queue; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import com.googlecode.concurentlocks.ReentrantReadWriteUpdateLock; + +import io.akarin.api.internal.utils.CheckedConcurrentLinkedQueue; +import io.netty.channel.Channel; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; +import net.minecraft.server.NetworkManager; +import net.minecraft.server.NetworkManager.QueuedPacket; +import net.minecraft.server.Packet; +import net.minecraft.server.PacketPlayOutMapChunk; + +@Mixin(value = NetworkManager.class, remap = false) +public abstract class OptimisticNetworkManager { + @Shadow public Channel channel; + @Shadow(aliases = "i") @Final private Queue packets; + @Shadow(aliases = "j") @Final private ReentrantReadWriteUpdateLock queueLock; + + @Shadow public abstract Queue getPacketQueue(); + @Shadow public abstract void dispatchPacket(Packet packet, GenericFutureListener> genericFutureListener); + + private static final QueuedPacket SIGNAL_PACKET = new QueuedPacket(null, null); + + @Overwrite // OBFHELPER: trySendQueue + private boolean o() { + if (this.channel != null && this.channel.isOpen()) { + if (this.packets.isEmpty()) { // return if the packet queue is empty so that the write lock by Anti-Xray doesn't affect the vanilla performance at all + return true; + } + + this.queueLock.updateLock().lock(); + try { + while (!this.packets.isEmpty()) { + NetworkManager.QueuedPacket packet = ((CheckedConcurrentLinkedQueue) getPacketQueue()).poll(item -> { + return item.getPacket() instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) item.getPacket()).isReady(); + }, SIGNAL_PACKET); + + if (packet != null) { // Fix NPE (Spigot bug caused by handleDisconnection()) + if (packet == SIGNAL_PACKET) { + return false; // Return false if the peeked packet is a chunk packet which is not ready + } else { + dispatchPacket(packet.getPacket(), packet.getGenericFutureListener()); // dispatch the packet + } + } + } + } finally { + this.queueLock.updateLock().unlock(); + } + + } + return true; // Return true if all packets were dispatched + } + +} diff --git a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinPersistentCollection.java b/sources/src/main/java/io/akarin/server/mixin/optimization/MixinPersistentCollection.java deleted file mode 100644 index bedd37b97..000000000 --- a/sources/src/main/java/io/akarin/server/mixin/optimization/MixinPersistentCollection.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.akarin.server.mixin.optimization; - -import java.io.File; -import java.io.FileOutputStream; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import com.destroystokyo.paper.exception.ServerInternalException; - -import net.minecraft.server.IDataManager; -import net.minecraft.server.MCUtil; -import net.minecraft.server.NBTCompressedStreamTools; -import net.minecraft.server.NBTTagCompound; -import net.minecraft.server.PersistentBase; -import net.minecraft.server.PersistentCollection; - -@Mixin(value = PersistentCollection.class, remap = false) -public abstract class MixinPersistentCollection { - @Shadow(aliases = "c") @Final private IDataManager dataManager; - - @Overwrite - private void a(PersistentBase persistentbase) { - if (this.dataManager == null) return; - - File file = this.dataManager.getDataFile(persistentbase.getId()); - if (file == null) return; - - NBTTagCompound nbttagcompound = new NBTTagCompound(); - nbttagcompound.set("data", persistentbase.b(new NBTTagCompound())); - - // Akarin start - MCUtil.scheduleAsyncTask(() -> { - try { - nbttagcompound.setInt("DataVersion", 1519); - FileOutputStream fileoutputstream = new FileOutputStream(file); - - NBTCompressedStreamTools.a(nbttagcompound, fileoutputstream); - fileoutputstream.close(); - } catch (Exception exception) { - exception.printStackTrace(); - ServerInternalException.reportInternalException(exception); // Paper - } - }); - // Akarin end - } -} diff --git a/sources/src/main/java/net/minecraft/server/ChunkProviderServer.java b/sources/src/main/java/net/minecraft/server/ChunkProviderServer.java index 7c3d918f2..32ddfb6fd 100644 --- a/sources/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/sources/src/main/java/net/minecraft/server/ChunkProviderServer.java @@ -1,8 +1,5 @@ package net.minecraft.server; -import com.google.common.collect.Lists; - -import io.akarin.api.internal.Akari; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; import it.unimi.dsi.fastutil.longs.LongIterator; @@ -10,15 +7,17 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.objects.ObjectIterator; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; import javax.annotation.Nullable; import com.destroystokyo.paper.exception.ServerInternalException; + +import io.akarin.api.internal.Akari; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -35,22 +34,28 @@ public class ChunkProviderServer implements IChunkProvider { public final LongSet unloadQueue = new LongOpenHashSet(); public final ChunkGenerator chunkGenerator; private final IChunkLoader chunkLoader; - public final Long2ObjectMap chunks = Long2ObjectMaps.synchronize(new ChunkMap(8192)); - private final ChunkTaskScheduler f; - private final SchedulerBatch g; // Paper start - chunk save stats private long lastQueuedSaves = 0L; // Paper private long lastProcessedSaves = 0L; // Paper private long lastSaveStatPrinted = System.currentTimeMillis(); + public boolean isChunkGenerated(int x, int z) { + return this.chunks.containsKey(ChunkCoordIntPair.asLong(x, z)) || ((ChunkRegionLoader) this.chunkLoader).chunkExists(x, z); + } // Paper end + public final Long2ObjectMap chunks = Long2ObjectMaps.synchronize(new ChunkMap(8192)); + private Chunk lastChunk; + private final ChunkTaskScheduler chunkScheduler; + private final SchedulerBatch batchScheduler; public final WorldServer world; + private final IAsyncTaskHandler asyncTaskHandler; public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, ChunkGenerator chunkgenerator, IAsyncTaskHandler iasynctaskhandler) { this.world = worldserver; this.chunkLoader = ichunkloader; this.chunkGenerator = chunkgenerator; - this.f = new ChunkTaskScheduler(0, worldserver, chunkgenerator, ichunkloader, iasynctaskhandler); // CraftBukkit - very buggy, broken in lots of __subtle__ ways. Same goes for async chunk loading. Also Bukkit API / plugins can't handle async events at all anyway. - this.g = new SchedulerBatch(this.f); + this.asyncTaskHandler = iasynctaskhandler; + this.chunkScheduler = new ChunkTaskScheduler(0, worldserver, chunkgenerator, ichunkloader, iasynctaskhandler); // CraftBukkit - very buggy, broken in lots of __subtle__ ways. Same goes for async chunk loading. Also Bukkit API / plugins can't handle async events at all anyway. + this.batchScheduler = new SchedulerBatch(this.chunkScheduler); } public Collection a() { @@ -60,7 +65,6 @@ public class ChunkProviderServer implements IChunkProvider { public void unload(Chunk chunk) { if (this.world.worldProvider.a(chunk.locX, chunk.locZ)) { this.unloadQueue.add(ChunkCoordIntPair.a(chunk.locX, chunk.locZ)); - chunk.d = true; } } @@ -76,119 +80,99 @@ public class ChunkProviderServer implements IChunkProvider { } - @Nullable - public Chunk getLoadedChunkAt(int i, int j) { - long k = ChunkCoordIntPair.a(i, j); - Chunk chunk = (Chunk) this.chunks.get(k); - - if (chunk != null) { - chunk.d = false; - } - - return chunk; + public void a(int i, int j) { + this.unloadQueue.remove(ChunkCoordIntPair.a(i, j)); } @Nullable - private Chunk loadChunkAt(int i, int j) { - try { - // CraftBukkit - decompile error - Chunk chunk = this.chunkLoader.a(this.world, i, j, (chunk1) -> { - chunk1.setLastSaved(this.world.getTime()); - this.chunks.put(ChunkCoordIntPair.a(i, j), chunk1); - }); + public Chunk getChunkAt(int i, int j, boolean flag, boolean flag1) { + IChunkLoader ichunkloader = this.chunkLoader; + Chunk chunk; + synchronized (this.chunkLoader) { + // Paper start - remove vanilla lastChunk, we do it more accurately + /* if (this.lastChunk != null && this.lastChunk.locX == i && this.lastChunk.locZ == j) { + return this.lastChunk; + }*/ // Paper end + + long k = ChunkCoordIntPair.a(i, j); + + chunk = (Chunk) this.chunks.get(k); if (chunk != null) { - chunk.addEntities(); + //this.lastChunk = chunk; // Paper remove vanilla lastChunk + return chunk; } + if (flag) { + try (co.aikar.timings.Timing timing = world.timings.syncChunkLoadTimer.startTiming()) { // Paper + // CraftBukkit - decompile error + chunk = this.chunkLoader.a(this.world, i, j, (chunk1) -> { + chunk1.setLastSaved(this.world.getTime()); + this.chunks.put(ChunkCoordIntPair.a(i, j), chunk1); + }); + } catch (Exception exception) { + ChunkProviderServer.a.error("Couldn\'t load chunk", exception); + } + } + } + + if (chunk != null) { + this.asyncTaskHandler.postToMainThread(chunk::addEntities); return chunk; - } catch (Exception exception) { - ChunkProviderServer.a.error("Couldn\'t load chunk", exception); + } else if (flag1) { + try (co.aikar.timings.Timing timing = world.timings.chunkGeneration.startTiming()) { // Paper + this.batchScheduler.b(); + this.batchScheduler.a(new ChunkCoordIntPair(i, j)); + CompletableFuture completablefuture = this.batchScheduler.c(); // CraftBukkit - decompile error + + return (Chunk) completablefuture.thenApply(this::a).join(); + } catch (RuntimeException runtimeexception) { + throw this.a(i, j, (Throwable) runtimeexception); + } + // finally { world.timings.syncChunkLoadTimer.stopTiming(); } // Spigot // Paper + } else { return null; } } - @Nullable - public Chunk getOrLoadChunkAt(int i, int j) { - Long2ObjectMap long2objectmap = this.chunks; - - Akari.eventLock.lock(); // Akarin - try { // Akarin - synchronized (this.chunks) { - Chunk chunk = world.paperConfig.allowPermaChunkLoaders ? getLoadedChunkAt(i, j) : getChunkIfLoaded(i, j); // Paper - Configurable perma chunk loaders - - return chunk != null ? chunk : this.loadChunkAt(i, j); - } - } finally { Akari.eventLock.unlock(); } // Akarin - } - // CraftBukkit start - public Chunk getChunkIfLoaded(int x, int z) { - return chunks.get(ChunkCoordIntPair.a(x, z)); + public Chunk generateChunk(int x, int z) { + try { + this.batchScheduler.b(); + ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); + this.chunkScheduler.forcePolluteCache(pos); + this.batchScheduler.a(pos); + CompletableFuture completablefuture = this.batchScheduler.c(); + + return (Chunk) completablefuture.thenApply(this::a).join(); + } catch (RuntimeException runtimeexception) { + throw this.a(x, z, (Throwable) runtimeexception); + } } // CraftBukkit end - public Chunk getChunkAt(int i, int j) { - Chunk chunk = this.getOrLoadChunkAt(i, j); + public IChunkAccess a(int i, int j, boolean flag) { + Chunk chunk = this.getChunkAt(i, j, true, false); - if (chunk != null) { - return chunk; - } else { - try (co.aikar.timings.Timing timing = world.timings.chunkGeneration.startTiming()) { - ; // Spigot - chunk = (Chunk) this.generateChunk(i, j).get(); - return chunk; - } catch (ExecutionException | InterruptedException interruptedexception) { - throw this.a(i, j, (Throwable) interruptedexception); - } - } - } - - public IChunkAccess d(int i, int j) { - Long2ObjectMap long2objectmap = this.chunks; - - synchronized (this.chunks) { - IChunkAccess ichunkaccess = (IChunkAccess) this.chunks.get(ChunkCoordIntPair.a(i, j)); - - return ichunkaccess != null ? ichunkaccess : (IChunkAccess) this.f.c((new ChunkCoordIntPair(i, j))); // CraftBukkit - decompile error - } + return (IChunkAccess) (chunk != null ? chunk : (IChunkAccess) this.chunkScheduler.b(new ChunkCoordIntPair(i, j), flag)); } public CompletableFuture a(Iterable iterable, Consumer consumer) { - this.g.b(); + this.batchScheduler.b(); Iterator iterator = iterable.iterator(); while (iterator.hasNext()) { ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) iterator.next(); - Chunk chunk = this.getOrLoadChunkAt(chunkcoordintpair.x, chunkcoordintpair.z); + Chunk chunk = this.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, true, false); if (chunk != null) { consumer.accept(chunk); } else { - this.g.a(chunkcoordintpair).thenApply(this::a).thenAccept(consumer); + this.batchScheduler.a(chunkcoordintpair).thenApply(this::a).thenAccept(consumer); } } - return this.g.c(); - } - - // CraftBukkit start - public CompletableFuture generateChunk(int i, int j) { - return this.generateChunk(i, j, false); - } - - public CompletableFuture generateChunk(int i, int j, boolean force) { - this.g.b(); - - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j); - if (force) { - this.f.forcePolluteCache(chunkcoordintpair); - } - this.g.a(chunkcoordintpair); - // CraftBukkit end - CompletableFuture completablefuture = this.g.c(); // CraftBukkit - decompile error - - return completablefuture.thenApply(this::a); + return this.batchScheduler.c(); } private ReportedException a(int i, int j, Throwable throwable) { @@ -229,26 +213,14 @@ public class ChunkProviderServer implements IChunkProvider { } this.chunks.put(k, chunk); + //this.lastChunk = chunk; // Paper } } finally { Akari.eventLock.unlock(); } // Akarin - chunk.addEntities(); + this.asyncTaskHandler.postToMainThread(chunk::addEntities); return chunk; } - public void saveChunkNOP(Chunk chunk) { - try { - // this.chunkLoader.a(this.world, chunk); // Spigot - } catch (Exception exception) { - // Paper start - String msg = "Couldn\'t save entities"; - ChunkProviderServer.a.error(msg, exception); - ServerInternalException.reportInternalException(exception); - // Paper end - } - - } - public void saveChunk(IChunkAccess ichunkaccess, boolean unloaded) { // Spigot try (co.aikar.timings.Timing timed = world.timings.chunkSaveData.startTiming()) { // Paper - Timings ichunkaccess.setLastSaved(this.world.getTime()); @@ -269,65 +241,64 @@ public class ChunkProviderServer implements IChunkProvider { public boolean a(boolean flag) { int i = 0; - this.f.a(); - ArrayList arraylist = Lists.newArrayList(this.chunks.values()); - Iterator iterator = arraylist.iterator(); + this.chunkScheduler.a(() -> { + return true; + }); + IChunkLoader ichunkloader = this.chunkLoader; - // Paper start - final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProviderServer().chunkLoader; - final int queueSize = chunkLoader.getQueueSize(); + synchronized (this.chunkLoader) { + ObjectIterator objectiterator = this.chunks.values().iterator(); - final long now = System.currentTimeMillis(); - final long timeSince = (now - lastSaveStatPrinted) / 1000; - final Integer printRateSecs = Integer.getInteger("printSaveStats"); - if (printRateSecs != null && timeSince >= printRateSecs) { - final String timeStr = "/" + timeSince +"s"; - final long queuedSaves = chunkLoader.getQueuedSaves(); - long queuedDiff = queuedSaves - lastQueuedSaves; - lastQueuedSaves = queuedSaves; + // Paper start + final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProviderServer().chunkLoader; + final int queueSize = chunkLoader.getQueueSize(); - final long processedSaves = chunkLoader.getProcessedSaves(); - long processedDiff = processedSaves - lastProcessedSaves; - lastProcessedSaves = processedSaves; + final long now = System.currentTimeMillis(); + final long timeSince = (now - lastSaveStatPrinted) / 1000; + final Integer printRateSecs = Integer.getInteger("printSaveStats"); + if (printRateSecs != null && timeSince >= printRateSecs) { + final String timeStr = "/" + timeSince +"s"; + final long queuedSaves = chunkLoader.getQueuedSaves(); + long queuedDiff = queuedSaves - lastQueuedSaves; + lastQueuedSaves = queuedSaves; - lastSaveStatPrinted = now; - if (processedDiff > 0 || queueSize > 0 || queuedDiff > 0) { - System.out.println("[Chunk Save Stats] " + world.worldData.getName() + - " - Current: " + queueSize + - " - Queued: " + queuedDiff + timeStr + - " - Processed: " +processedDiff + timeStr - ); - } - } + final long processedSaves = chunkLoader.getProcessedSaves(); + long processedDiff = processedSaves - lastProcessedSaves; + lastProcessedSaves = processedSaves; - if (queueSize > world.paperConfig.queueSizeAutoSaveThreshold){ - return false; - } - final int autoSaveLimit = world.paperConfig.maxAutoSaveChunksPerTick; - // Paper end - while (iterator.hasNext()) { - Chunk chunk = (Chunk) iterator.next(); - - if (flag) { - this.saveChunkNOP(chunk); - } - - if (chunk.c(flag)) { - this.saveChunk(chunk, false); // Spigot - chunk.a(false); - ++i; - if (!flag && i >= autoSaveLimit) { // Spigot - // Paper - Incremental Auto Save - cap max per tick - return false; + lastSaveStatPrinted = now; + if (processedDiff > 0 || queueSize > 0 || queuedDiff > 0) { + System.out.println("[Chunk Save Stats] " + world.worldData.getName() + + " - Current: " + queueSize + + " - Queued: " + queuedDiff + timeStr + + " - Processed: " +processedDiff + timeStr + ); } } - } + if (queueSize > world.paperConfig.queueSizeAutoSaveThreshold){ + return false; + } + // Paper end + while (objectiterator.hasNext()) { + Chunk chunk = (Chunk) objectiterator.next(); - return true; + if (chunk.c(flag)) { + this.saveChunk(chunk, false); // Spigot + chunk.a(false); + ++i; + if (!flag && i >= world.paperConfig.maxAutoSaveChunksPerTick) { // Spigot - // Paper - Incremental Auto Save - cap max + return false; + } + } + } + + return true; + } } public void close() { try { - this.g.a(); + this.batchScheduler.a(); } catch (InterruptedException interruptedexception) { ChunkProviderServer.a.error("Couldn\'t stop taskManager", interruptedexception); } @@ -335,12 +306,16 @@ public class ChunkProviderServer implements IChunkProvider { } public void c() { - this.chunkLoader.c(); + IChunkLoader ichunkloader = this.chunkLoader; + + synchronized (this.chunkLoader) { + this.chunkLoader.b(); + } } - private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; + private static final double UNLOAD_QUEUE_RESIZE_FACTOR = 0.96; // Spigot - public boolean unloadChunks() { + public boolean unloadChunks(BooleanSupplier booleansupplier) { if (!this.world.savingDisabled) { if (!this.unloadQueue.isEmpty()) { // Spigot start @@ -354,24 +329,26 @@ public class ChunkProviderServer implements IChunkProvider { while (longiterator.hasNext()) { // Spigot Long olong = (Long) longiterator.next(); longiterator.remove(); // Spigot - Chunk chunk = (Chunk) this.chunks.get(olong); + IChunkLoader ichunkloader = this.chunkLoader; - if (chunk != null && chunk.d) { - // CraftBukkit start - move unload logic to own method - chunk.setShouldUnload(false); // Paper - if (!unloadChunk(chunk, true)) { - continue; - } - // CraftBukkit end + synchronized (this.chunkLoader) { + Chunk chunk = (Chunk) this.chunks.get(olong); - // Spigot start - if (this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { - break; + if (chunk != null) { + // CraftBukkit start - move unload logic to own method + if (!unloadChunk(chunk, true)) { + continue; + } + // CraftBukkit end + + // Spigot start + if (!booleansupplier.getAsBoolean() && this.unloadQueue.size() <= targetSize && activityAccountant.activityTimeIsExhausted()) { + break; + } + // Spigot end } - // Spigot end } } - activityAccountant.endActivity(); // Spigot } // Paper start - delayed chunk unloads @@ -388,8 +365,7 @@ public class ChunkProviderServer implements IChunkProvider { } // Paper end - this.f.a(); - this.chunkLoader.b(); + this.chunkScheduler.a(booleansupplier); } return false; @@ -412,7 +388,7 @@ public class ChunkProviderServer implements IChunkProvider { continue; } - Chunk neighbor = this.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z); + Chunk neighbor = this.getChunkAt(chunk.locX + x, chunk.locZ + z, false, false); if (neighbor != null) { neighbor.setNeighborUnloaded(-x, -z); chunk.setNeighborUnloaded(x, z); @@ -423,14 +399,14 @@ public class ChunkProviderServer implements IChunkProvider { chunk.removeEntities(); if (save) { this.saveChunk(chunk, true); // Spigot - this.saveChunkNOP(chunk); } this.chunks.remove(chunk.chunkKey); + //this.lastChunk = null; // Paper return true; } // CraftBukkit end - public boolean e() { + public boolean d() { return !this.world.savingDisabled; } @@ -447,23 +423,19 @@ public class ChunkProviderServer implements IChunkProvider { } @Nullable - public BlockPosition a(World world, String s, BlockPosition blockposition, int i) { - return this.chunkGenerator.findNearestMapFeature(world, s, blockposition, i); + public BlockPosition a(World world, String s, BlockPosition blockposition, int i, boolean flag) { + return this.chunkGenerator.findNearestMapFeature(world, s, blockposition, i, flag); } public ChunkGenerator getChunkGenerator() { return this.chunkGenerator; } - public int h() { + public int g() { return this.chunks.size(); } public boolean isLoaded(int i, int j) { return this.chunks.containsKey(ChunkCoordIntPair.a(i, j)); } - - public boolean f(int i, int j) { - return this.chunks.containsKey(ChunkCoordIntPair.a(i, j)) || this.chunkLoader.chunkExists(i, j); - } } diff --git a/sources/src/main/java/net/minecraft/server/Entity.java b/sources/src/main/java/net/minecraft/server/Entity.java index 480a28664..3177aab41 100644 --- a/sources/src/main/java/net/minecraft/server/Entity.java +++ b/sources/src/main/java/net/minecraft/server/Entity.java @@ -57,7 +57,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke // CraftBukkit start private static final int CURRENT_LEVEL = 2; // Paper start - public static Random SHARED_RANDOM = new java.util.Random() { + public static Random SHARED_RANDOM = new Random() { private boolean locked = false; @Override public synchronized void setSeed(long seed) { @@ -69,12 +69,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } } }; - Object entitySlice = null; + List entitySlice = null; // Paper end static boolean isLevelAtLeast(NBTTagCompound tag, int level) { return tag.hasKey("Bukkit.updateLevel") && tag.getInt("Bukkit.updateLevel") >= level; } + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper protected CraftEntity bukkitEntity; EntityTrackerEntry tracker; // Paper @@ -102,7 +103,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke public boolean j; public boolean blocksEntitySpawning() { return j; } // Paper - OBFHELPER public final List passengers; protected int k; - private Entity ax; + private Entity vehicle; public boolean attachedToPlayer; public World world; public double lastX; @@ -168,7 +169,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke public int portalCooldown; protected boolean an; public boolean inPortal() { return an; } // Paper - OBFHELPER protected int ao; - public int dimension; + public DimensionManager dimension; protected BlockPosition aq; protected Vec3D ar; protected EnumDirection as; @@ -221,7 +222,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.world = world; this.setPosition(0.0D, 0.0D, 0.0D); if (world != null) { - this.dimension = world.worldProvider.getDimensionManager().getDimensionID(); + this.dimension = world.worldProvider.getDimensionManager(); // Spigot start this.defaultActivationState = org.spigotmc.ActivationRange.initializeEntityActivationState(this, world.spigotConfig); } else { @@ -247,7 +248,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke return this.id; } - public void f(int i) { + public void e(int i) { this.id = i; } @@ -376,15 +377,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke if (this.ao++ >= i) { this.ao = i; this.portalCooldown = this.aQ(); - byte b0; + DimensionManager dimensionmanager; - if (this.world.worldProvider.getDimensionManager().getDimensionID() == -1) { - b0 = 0; + if (this.world.worldProvider.getDimensionManager() == DimensionManager.NETHER) { + dimensionmanager = DimensionManager.OVERWORLD; } else { - b0 = -1; + dimensionmanager = DimensionManager.NETHER; } - this.d(b0); + this.a(dimensionmanager); } } @@ -436,15 +437,15 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke if (this.ao++ >= i) { this.ao = i; this.portalCooldown = this.aQ(); - byte b0; + DimensionManager dimensionmanager; - if (this.world.worldProvider.getDimensionManager().getDimensionID() == -1) { - b0 = 0; + if (this.world.worldProvider.getDimensionManager() == DimensionManager.NETHER) { + dimensionmanager = DimensionManager.OVERWORLD; } else { - b0 = -1; + dimensionmanager = DimensionManager.NETHER; } - this.d(b0); + this.a(dimensionmanager); } } @@ -528,29 +529,24 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke protected void burnFromLava() { if (!this.fireProof) { - this.damageEntity(DamageSource.LAVA, 4.0F); - // CraftBukkit start - Fallen in lava TODO: this event spams! - if (this instanceof EntityLiving) { - if (fireTicks <= 0) { - // not on fire yet - // TODO: shouldn't be sending null for the block - org.bukkit.block.Block damager = null; // ((WorldServer) this.l).getWorld().getBlockAt(i, j, k); - org.bukkit.entity.Entity damagee = this.getBukkitEntity(); - EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15); - this.world.getServer().getPluginManager().callEvent(combustEvent); + if (this instanceof EntityLiving && fireTicks <= 0) { + // not on fire yet + // TODO: shouldn't be sending null for the block + org.bukkit.block.Block damager = null; // ((WorldServer) this.l).getWorld().getBlockAt(i, j, k); + org.bukkit.entity.Entity damagee = this.getBukkitEntity(); + EntityCombustEvent combustEvent = new org.bukkit.event.entity.EntityCombustByBlockEvent(damager, damagee, 15); + this.world.getServer().getPluginManager().callEvent(combustEvent); - if (!combustEvent.isCancelled()) { - this.setOnFire(combustEvent.getDuration()); - } - } else { - // This will be called every single tick the entity is in lava, so don't throw an event - this.setOnFire(15); + if (!combustEvent.isCancelled()) { + this.setOnFire(combustEvent.getDuration()); } - return; + } else { + // This will be called every single tick the entity is in lava, so don't throw an event + this.setOnFire(15); } // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls - this.setOnFire(15); + this.damageEntity(DamageSource.LAVA, 4.0F); } } @@ -694,22 +690,22 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke AxisAlignedBB axisalignedbb = this.getBoundingBox(); if (d0 != 0.0D || d1 != 0.0D || d2 != 0.0D) { - VoxelShape voxelshape = this.world.a(this, this.getBoundingBox(), d0, d1, d2); + StreamAccumulator streamaccumulator = new StreamAccumulator(this.world.a(this, this.getBoundingBox(), d0, d1, d2)); if (d1 != 0.0D) { - d1 = VoxelShapes.a(EnumDirection.EnumAxis.Y, this.getBoundingBox(), voxelshape, d1); + d1 = VoxelShapes.a(EnumDirection.EnumAxis.Y, this.getBoundingBox(), streamaccumulator.a(), d1); this.a(this.getBoundingBox().d(0.0D, d1, 0.0D)); } if (d0 != 0.0D) { - d0 = VoxelShapes.a(EnumDirection.EnumAxis.X, this.getBoundingBox(), voxelshape, d0); + d0 = VoxelShapes.a(EnumDirection.EnumAxis.X, this.getBoundingBox(), streamaccumulator.a(), d0); if (d0 != 0.0D) { this.a(this.getBoundingBox().d(d0, 0.0D, 0.0D)); } } if (d2 != 0.0D) { - d2 = VoxelShapes.a(EnumDirection.EnumAxis.Z, this.getBoundingBox(), voxelshape, d2); + d2 = VoxelShapes.a(EnumDirection.EnumAxis.Z, this.getBoundingBox(), streamaccumulator.a(), d2); if (d2 != 0.0D) { this.a(this.getBoundingBox().d(0.0D, 0.0D, d2)); } @@ -730,41 +726,41 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke d1 = (double) this.Q; d2 = d9; if (d7 != 0.0D || d1 != 0.0D || d9 != 0.0D) { - VoxelShape voxelshape1 = this.world.a(this, this.getBoundingBox(), d7, d1, d9); + StreamAccumulator streamaccumulator1 = new StreamAccumulator(this.world.a(this, this.getBoundingBox(), d7, d1, d9)); AxisAlignedBB axisalignedbb2 = this.getBoundingBox(); AxisAlignedBB axisalignedbb3 = axisalignedbb2.b(d7, 0.0D, d9); - d11 = VoxelShapes.a(EnumDirection.EnumAxis.Y, axisalignedbb3, voxelshape1, d1); + d11 = VoxelShapes.a(EnumDirection.EnumAxis.Y, axisalignedbb3, streamaccumulator1.a(), d1); if (d11 != 0.0D) { axisalignedbb2 = axisalignedbb2.d(0.0D, d11, 0.0D); } - double d15 = VoxelShapes.a(EnumDirection.EnumAxis.X, axisalignedbb2, voxelshape1, d7); + double d15 = VoxelShapes.a(EnumDirection.EnumAxis.X, axisalignedbb2, streamaccumulator1.a(), d7); if (d15 != 0.0D) { axisalignedbb2 = axisalignedbb2.d(d15, 0.0D, 0.0D); } - double d16 = VoxelShapes.a(EnumDirection.EnumAxis.Z, axisalignedbb2, voxelshape1, d9); + double d16 = VoxelShapes.a(EnumDirection.EnumAxis.Z, axisalignedbb2, streamaccumulator1.a(), d9); if (d16 != 0.0D) { axisalignedbb2 = axisalignedbb2.d(0.0D, 0.0D, d16); } AxisAlignedBB axisalignedbb4 = this.getBoundingBox(); - double d17 = VoxelShapes.a(EnumDirection.EnumAxis.Y, axisalignedbb4, voxelshape1, d1); + double d17 = VoxelShapes.a(EnumDirection.EnumAxis.Y, axisalignedbb4, streamaccumulator1.a(), d1); if (d17 != 0.0D) { axisalignedbb4 = axisalignedbb4.d(0.0D, d17, 0.0D); } - double d18 = VoxelShapes.a(EnumDirection.EnumAxis.X, axisalignedbb4, voxelshape1, d7); + double d18 = VoxelShapes.a(EnumDirection.EnumAxis.X, axisalignedbb4, streamaccumulator1.a(), d7); if (d18 != 0.0D) { axisalignedbb4 = axisalignedbb4.d(d18, 0.0D, 0.0D); } - double d19 = VoxelShapes.a(EnumDirection.EnumAxis.Z, axisalignedbb4, voxelshape1, d9); + double d19 = VoxelShapes.a(EnumDirection.EnumAxis.Z, axisalignedbb4, streamaccumulator1.a(), d9); if (d19 != 0.0D) { axisalignedbb4 = axisalignedbb4.d(0.0D, 0.0D, d19); @@ -785,7 +781,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.a(axisalignedbb4); } - d1 = VoxelShapes.a(EnumDirection.EnumAxis.Y, this.getBoundingBox(), voxelshape1, d1); + d1 = VoxelShapes.a(EnumDirection.EnumAxis.Y, this.getBoundingBox(), streamaccumulator1.a(), d1); if (d1 != 0.0D) { this.a(this.getBoundingBox().d(0.0D, d1, 0.0D)); } @@ -908,7 +904,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke boolean flag1 = this.ap(); if (this.world.b(this.getBoundingBox().shrink(0.001D))) { - this.burn(1); if (!flag1) { ++this.fireTicks; if (this.fireTicks == 0) { @@ -922,6 +917,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke // CraftBukkit end } } + + this.burn(1); } else if (this.fireTicks <= 0) { this.fireTicks = -this.getMaxFireTicks(); } @@ -1217,7 +1214,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke public boolean at() { if (this.getVehicle() instanceof EntityBoat) { this.inWater = false; - } else if (this.b(TagsFluid.a)) { + } else if (this.b(TagsFluid.WATER)) { if (!this.inWater && !this.justCreated) { this.au(); } @@ -1233,7 +1230,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } private void s() { - this.X = this.a(TagsFluid.a); + this.X = this.a(TagsFluid.WATER); } protected void au() { @@ -1590,7 +1587,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke nbttagcompound.setShort("Fire", (short) this.fireTicks); nbttagcompound.setShort("Air", (short) this.getAirTicks()); nbttagcompound.setBoolean("OnGround", this.onGround); - nbttagcompound.setInt("Dimension", this.dimension); + nbttagcompound.setInt("Dimension", this.dimension.getDimensionID()); nbttagcompound.setBoolean("Invulnerable", this.invulnerable); nbttagcompound.setInt("PortalCooldown", this.portalCooldown); nbttagcompound.a("UUID", this.getUniqueID()); @@ -1721,7 +1718,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.setAirTicks(nbttagcompound.getShort("Air")); this.onGround = nbttagcompound.getBoolean("OnGround"); if (nbttagcompound.hasKey("Dimension")) { - this.dimension = nbttagcompound.getInt("Dimension"); + this.dimension = DimensionManager.a(nbttagcompound.getInt("Dimension")); } this.invulnerable = nbttagcompound.getBoolean("Invulnerable"); @@ -1801,8 +1798,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } if (bworld == null) { - EntityPlayer entityPlayer = (EntityPlayer) this; - bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(entityPlayer.dimension).getWorld(); + bworld = ((org.bukkit.craftbukkit.CraftServer) server).getServer().getWorldServer(DimensionManager.OVERWORLD).getWorld(); } spawnIn(bworld == null? null : ((CraftWorld) bworld).getHandle()); @@ -2056,8 +2052,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } public boolean a(Entity entity, boolean flag) { - for (Entity entity1 = entity; entity1.ax != null; entity1 = entity1.ax) { - if (entity1.ax == this) { + for (Entity entity1 = entity; entity1.vehicle != null; entity1 = entity1.vehicle) { + if (entity1.vehicle == this) { return false; } } @@ -2069,8 +2065,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.stopRiding(); } - this.ax = entity; - this.ax.o(this); + this.vehicle = entity; + this.vehicle.o(this); return true; } } @@ -2087,11 +2083,11 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } public void stopRiding() { - if (this.ax != null) { - Entity entity = this.ax; + if (this.vehicle != null) { + Entity entity = this.vehicle; - this.ax = null; - if (!entity.p(this)) this.ax = entity; // CraftBukkit + this.vehicle = null; + if (!entity.removePassenger(this)) this.vehicle = entity; // CraftBukkit } } @@ -2135,7 +2131,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } } - protected boolean p(Entity entity) { // CraftBukkit + protected boolean removePassenger(Entity entity) { // CraftBukkit if (entity.getVehicle() == this) { throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); } else { @@ -2342,11 +2338,24 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } public void onLightningStrike(EntityLightning entitylightning) { + ++this.fireTicks; // CraftBukkit start final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); final org.bukkit.entity.Entity stormBukkitEntity = entitylightning.getBukkitEntity(); final PluginManager pluginManager = Bukkit.getPluginManager(); + // CraftBukkit end + if (this.fireTicks == 0) { + // CraftBukkit start - Call a combust event when lightning strikes + EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); + pluginManager.callEvent(entityCombustEvent); + if (!entityCombustEvent.isCancelled()) { + this.setOnFire(entityCombustEvent.getDuration()); + } + // CraftBukkit end + } + + // CraftBukkit start if (thisBukkitEntity instanceof Hanging) { HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity); pluginManager.callEvent(hangingEvent); @@ -2365,17 +2374,6 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke return; } // CraftBukkit end - ++this.fireTicks; - if (this.fireTicks == 0) { - // CraftBukkit start - Call a combust event when lightning strikes - EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); - pluginManager.callEvent(entityCombustEvent); - if (!entityCombustEvent.isCancelled()) { - this.setOnFire(entityCombustEvent.getDuration()); - } - // CraftBukkit end - } - } public void j(boolean flag) { @@ -2472,12 +2470,12 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke IChatBaseComponent ichatbasecomponent = this.getCustomName(); if (ichatbasecomponent != null) { - IChatBaseComponent ichatbasecomponent1 = ichatbasecomponent.e(); + IChatBaseComponent ichatbasecomponent1 = ichatbasecomponent.h(); c(ichatbasecomponent1); return ichatbasecomponent1; } else { - return new ChatMessage(this.g.d(), new Object[0]); + return this.g.e(); } } @@ -2538,22 +2536,17 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke } @Nullable - public Entity d(int i) { + public Entity a(DimensionManager dimensionmanager) { if (!this.world.isClientSide && !this.dead) { this.world.methodProfiler.a("changeDimension"); MinecraftServer minecraftserver = this.bK(); // CraftBukkit start - Move logic into new function "teleportTo(Location,boolean)" - // int j = this.dimension; - // WorldServer worldserver = minecraftserver.getWorldServer(j); - // WorldServer worldserver1 = minecraftserver.getWorldServer(i); + // DimensionManager dimensionmanager1 = this.dimension; + // WorldServer worldserver = minecraftserver.getWorldServer(dimensionmanager1); + // WorldServer worldserver1 = minecraftserver.getWorldServer(dimensionmanager); WorldServer exitWorld = null; - if (this.dimension < CraftWorld.CUSTOM_DIMENSION_OFFSET) { // Plugins must specify exit from custom Bukkit worlds - // Only target existing worlds (compensate for allow-nether/allow-end as false) - for (WorldServer world : minecraftserver.worlds) { - if (world.dimension == i) { - exitWorld = world; - } - } + if (this.dimension.getDimensionID() < CraftWorld.CUSTOM_DIMENSION_OFFSET) { // Plugins must specify exit from custom Bukkit worlds + exitWorld = minecraftserver.getWorldServer(dimensionmanager); } BlockPosition blockposition = null; // PAIL: CHECK @@ -2563,13 +2556,13 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke if (blockposition != null) { exit = new Location(exitWorld.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ()); } else { - exit = minecraftserver.getPlayerList().calculateTarget(enter, minecraftserver.getWorldServer(i)); + exit = minecraftserver.getPlayerList().calculateTarget(enter, exitWorld); } } else { exit = null; } - boolean useTravelAgent = exitWorld != null && !(this.dimension == 1 && exitWorld.dimension == 1); // don't use agent for custom worlds or return from THE_END + boolean useTravelAgent = exitWorld != null && !(this.dimension == DimensionManager.THE_END && exitWorld.dimension == DimensionManager.THE_END); // don't use agent for custom worlds or return from THE_END TravelAgent agent = exit != null ? (TravelAgent) ((CraftWorld) exit.getWorld()).getHandle().getTravelAgent() : org.bukkit.craftbukkit.CraftTravelAgent.DEFAULT; // return arbitrary TA to compensate for implementation dependent plugins boolean oldCanCreate = agent.getCanCreatePortal(); @@ -2589,22 +2582,23 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke Entity entity = this.teleportTo(exit, true); this.world.methodProfiler.e(); return entity; + } else { + return null; } - return null; } public Entity teleportTo(Location exit, boolean portal) { if (!this.dead) { // Paper WorldServer worldserver = ((CraftWorld) getBukkitEntity().getLocation().getWorld()).getHandle(); WorldServer worldserver1 = ((CraftWorld) exit.getWorld()).getHandle(); - int i = worldserver1.dimension; + DimensionManager dimensionmanager = worldserver1.dimension; // CraftBukkit end - this.dimension = i; + this.dimension = dimensionmanager; /* CraftBukkit start - TODO: Check if we need this - if (j == 1 && i == 1) { - worldserver1 = minecraftserver.a(DimensionManager.OVERWORLD); - this.dimension = 0; + if (dimensionmanager1 == DimensionManager.THE_END && dimensionmanager == DimensionManager.THE_END) { + worldserver1 = minecraftserver.getWorldServer(DimensionManager.OVERWORLD); + this.dimension = DimensionManager.OVERWORLD; } // CraftBukkit end */ @@ -2614,17 +2608,17 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke /* CraftBukkit start - Handled in calculateTarget BlockPosition blockposition; - if (i == 1) { + if (dimensionmanager == DimensionManager.THE_END) { blockposition = worldserver1.getDimensionSpawn(); } else { double d0 = this.locX; double d1 = this.locZ; double d2 = 8.0D; - if (i == -1) { + if (dimensionmanager == DimensionManager.NETHER) { d0 = MathHelper.a(d0 / 8.0D, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D); d1 = MathHelper.a(d1 / 8.0D, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D); - } else if (i == 0) { + } else if (dimensionmanager == DimensionManager.OVERWORLD) { d0 = MathHelper.a(d0 * 8.0D, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D); d1 = MathHelper.a(d1 * 8.0D, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D); } @@ -2652,7 +2646,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke if (entity != null) { entity.v(this); /* CraftBukkit start - We need to do this... - if (j == 1 && i == 1) { + if (dimensionmanager1 == DimensionManager.THE_END && dimensionmanager == DimensionManager.THE_END) { BlockPosition blockposition1 = worldserver1.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver1.getSpawn()); entity.setPositionRotation(blockposition1, entity.yaw, entity.pitch); @@ -2679,8 +2673,8 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke this.dead = true; this.world.methodProfiler.e(); - worldserver.q_(); - worldserver1.q_(); + worldserver.p(); + worldserver1.p(); // this.world.methodProfiler.e(); // CraftBukkit: Moved up to keep balanced return entity; } else { @@ -2801,7 +2795,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke return EnumDirection.fromAngle((double) this.yaw); } - public EnumDirection bB() { + public EnumDirection getAdjustedDirection() { return this.getDirection(); } @@ -3063,7 +3057,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @Nullable public Entity getVehicle() { - return this.ax; + return this.vehicle; } public EnumPistonReaction getPushReaction() { @@ -3086,7 +3080,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke return 0; } - public boolean k(int i) { + public boolean j(int i) { return this.y() >= i; } diff --git a/sources/src/main/java/net/minecraft/server/EntityPlayer.java b/sources/src/main/java/net/minecraft/server/EntityPlayer.java index f09710bc7..b422dc793 100644 --- a/sources/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/sources/src/main/java/net/minecraft/server/EntityPlayer.java @@ -5,12 +5,16 @@ import com.mojang.authlib.GameProfile; import io.akarin.api.internal.mixin.IMixinWorldServer; import io.netty.buffer.Unpooled; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; import java.util.ArrayDeque; // Paper import java.util.ArrayList; import java.util.Collection; import java.util.Deque; // Paper import java.util.Iterator; +import java.util.List; import java.util.Random; +import java.util.function.Consumer; import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -35,12 +39,11 @@ import org.bukkit.inventory.MainHand; /** * Akarin Changes Note - * 2) Add lock to player track (safety issue) + * 1) Add lock to player track (safety issue) */ public class EntityPlayer extends EntityHuman implements ICrafting { private static final Logger cc = LogManager.getLogger(); - private static final IChatBaseComponent cd = (new ChatMessage("multiplayer.message_not_delivered", new Object[0])).a(EnumChatFormat.RED); public String locale = null; // CraftBukkit - lowercase // Paper - default to null public long lastSave = MinecraftServer.currentTick; // Paper public PlayerConnection playerConnection; @@ -49,30 +52,30 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public double d; public double e; public final Deque removeQueue = new ArrayDeque<>(); // Paper - private final AdvancementDataPlayer cg; - private final ServerStatisticManager ch; - private float ci = Float.MIN_VALUE; + private final AdvancementDataPlayer cf; + private final ServerStatisticManager cg; + private float ch = Float.MIN_VALUE; + private int ci = Integer.MIN_VALUE; private int cj = Integer.MIN_VALUE; private int ck = Integer.MIN_VALUE; private int cl = Integer.MIN_VALUE; private int cm = Integer.MIN_VALUE; - private int cn = Integer.MIN_VALUE; private float lastHealthSent = -1.0E8F; - private int cp = -99999999; - private boolean cq = true; + private int co = -99999999; + private boolean cp = true; public int lastSentExp = -99999999; public int invulnerableTicks = 60; - private EntityHuman.EnumChatVisibility ct; - private boolean cu = true; - private long cv = SystemUtils.b(); - private Entity cw; + private EntityHuman.EnumChatVisibility cs; + private boolean ct = true; + private long cu = SystemUtils.b(); + private Entity cv; public boolean worldChangeInvuln; - private boolean cy; private void setHasSeenCredits(boolean has) { this.cy = has; } // Paper - OBFHELPER - private final RecipeBookServer cz; - private Vec3D cA; - private int cB; - private boolean cC; - private Vec3D cD; + private boolean cx; private void setHasSeenCredits(boolean has) { this.cx = has; } // Paper - OBFHELPER + private final RecipeBookServer cy; + private Vec3D cz; + private int cA; + private boolean cB; + private Vec3D cC; private int containerCounter; public boolean f; public int ping; @@ -106,9 +109,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting { playerinteractmanager.player = this; this.playerInteractManager = playerinteractmanager; this.server = minecraftserver; - this.cz = new RecipeBookServer(minecraftserver.getCraftingManager()); - this.ch = minecraftserver.getPlayerList().getStatisticManager(this); - this.cg = minecraftserver.getPlayerList().h(this); + this.cy = new RecipeBookServer(minecraftserver.getCraftingManager()); + this.cg = minecraftserver.getPlayerList().getStatisticManager(this); + this.cf = minecraftserver.getPlayerList().h(this); this.Q = 1.0F; this.a(worldserver); @@ -136,7 +139,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } int k = (i * 2 + 1) * (i * 2 + 1); - int l = this.s(k); + int l = this.r(k); int i1 = (new Random()).nextInt(k); for (int j1 = 0; j1 < k; ++j1) { @@ -171,7 +174,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } int k = (i * 2 + 1) * (i * 2 + 1); - int l = this.s(k); + int l = this.r(k); int i1 = (new Random()).nextInt(k); for (int j1 = 0; j1 < k; ++j1) { @@ -197,7 +200,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } - private int s(int i) { + private int r(int i) { return i <= 16 ? i - 1 : 17; } @@ -215,12 +218,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (nbttagcompound.hasKeyOfType("enteredNetherPosition", 10)) { NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("enteredNetherPosition"); - this.cD = new Vec3D(nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("y"), nbttagcompound1.getDouble("z")); + this.cC = new Vec3D(nbttagcompound1.getDouble("x"), nbttagcompound1.getDouble("y"), nbttagcompound1.getDouble("z")); } - this.cy = nbttagcompound.getBoolean("seenCredits"); + this.cx = nbttagcompound.getBoolean("seenCredits"); if (nbttagcompound.hasKeyOfType("recipeBook", 10)) { - this.cz.a(nbttagcompound.getCompound("recipeBook")); + this.cy.a(nbttagcompound.getCompound("recipeBook")); } this.getBukkitEntity().readExtraData(nbttagcompound); // CraftBukkit @@ -229,13 +232,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void b(NBTTagCompound nbttagcompound) { super.b(nbttagcompound); nbttagcompound.setInt("playerGameType", this.playerInteractManager.getGameMode().getId()); - nbttagcompound.setBoolean("seenCredits", this.cy); - if (this.cD != null) { + nbttagcompound.setBoolean("seenCredits", this.cx); + if (this.cC != null) { NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - nbttagcompound1.setDouble("x", this.cD.x); - nbttagcompound1.setDouble("y", this.cD.y); - nbttagcompound1.setDouble("z", this.cD.z); + nbttagcompound1.setDouble("x", this.cC.x); + nbttagcompound1.setDouble("y", this.cC.y); + nbttagcompound1.setDouble("z", this.cC.z); nbttagcompound.set("enteredNetherPosition", nbttagcompound1); } @@ -265,7 +268,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { nbttagcompound.set("RootVehicle", nbttagcompound2); } - nbttagcompound.set("recipeBook", this.cz.e()); + nbttagcompound.set("recipeBook", this.cy.e()); this.getBukkitEntity().setExtraData(nbttagcompound); // CraftBukkit } @@ -365,7 +368,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { while (!this.removeQueue.isEmpty()) { int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE); int[] aint = new int[i]; - Iterator iterator = this.removeQueue.iterator(); + //Iterator iterator = this.removeQueue.iterator(); // Paper int j = 0; // Paper start @@ -398,11 +401,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } CriterionTriggers.w.a(this); - if (this.cA != null) { - CriterionTriggers.u.a(this, this.cA, this.ticksLived - this.cB); + if (this.cz != null) { + CriterionTriggers.u.a(this, this.cz, this.ticksLived - this.cA); } - this.cg.b(this); + this.cf.b(this); } public void playerTick() { @@ -421,36 +424,36 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } } - if (this.getHealth() != this.lastHealthSent || this.cp != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.cq) { + if (this.getHealth() != this.lastHealthSent || this.co != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.cp) { this.playerConnection.sendPacket(new PacketPlayOutUpdateHealth(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit this.lastHealthSent = this.getHealth(); - this.cp = this.foodData.getFoodLevel(); - this.cq = this.foodData.getSaturationLevel() == 0.0F; + this.co = this.foodData.getFoodLevel(); + this.cp = this.foodData.getSaturationLevel() == 0.0F; } - if (this.getHealth() + this.getAbsorptionHearts() != this.ci) { - this.ci = this.getHealth() + this.getAbsorptionHearts(); - this.a(IScoreboardCriteria.g, MathHelper.f(this.ci)); + if (this.getHealth() + this.getAbsorptionHearts() != this.ch) { + this.ch = this.getHealth() + this.getAbsorptionHearts(); + this.a(IScoreboardCriteria.g, MathHelper.f(this.ch)); } - if (this.foodData.getFoodLevel() != this.cj) { - this.cj = this.foodData.getFoodLevel(); - this.a(IScoreboardCriteria.h, MathHelper.f((float) this.cj)); + if (this.foodData.getFoodLevel() != this.ci) { + this.ci = this.foodData.getFoodLevel(); + this.a(IScoreboardCriteria.h, MathHelper.f((float) this.ci)); } - if (this.getAirTicks() != this.ck) { - this.ck = this.getAirTicks(); - this.a(IScoreboardCriteria.i, MathHelper.f((float) this.ck)); + if (this.getAirTicks() != this.cj) { + this.cj = this.getAirTicks(); + this.a(IScoreboardCriteria.i, MathHelper.f((float) this.cj)); } - if (this.getArmorStrength() != this.cl) { - this.cl = this.getArmorStrength(); - this.a(IScoreboardCriteria.j, MathHelper.f((float) this.cl)); + if (this.getArmorStrength() != this.ck) { + this.ck = this.getArmorStrength(); + this.a(IScoreboardCriteria.j, MathHelper.f((float) this.ck)); } - if (this.expTotal != this.cn) { - this.cn = this.expTotal; - this.a(IScoreboardCriteria.k, MathHelper.f((float) this.cn)); + if (this.expTotal != this.cm) { + this.cm = this.expTotal; + this.a(IScoreboardCriteria.k, MathHelper.f((float) this.cm)); } // CraftBukkit start - Force max health updates @@ -459,9 +462,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } // CraftBukkit end - if (this.expLevel != this.cm) { - this.cm = this.expLevel; - this.a(IScoreboardCriteria.l, MathHelper.f((float) this.cm)); + if (this.expLevel != this.cl) { + this.cl = this.expLevel; + this.a(IScoreboardCriteria.l, MathHelper.f((float) this.cl)); } if (this.expTotal != this.lastSentExp) { @@ -501,8 +504,6 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void die(DamageSource damagesource) { boolean flag = this.world.getGameRules().getBoolean("showDeathMessages"); - - this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, flag)); // CraftBukkit start - fire PlayerDeathEvent if (this.dead) { return; @@ -518,29 +519,46 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } } - IChatBaseComponent chatmessage = this.getCombatTracker().getDeathMessage(); + IChatBaseComponent defaultMessage = this.getCombatTracker().getDeathMessage(); - String deathmessage = chatmessage.getString(); + String deathmessage = defaultMessage.getString(); org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory); String deathMessage = event.getDeathMessage(); if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override? + IChatBaseComponent ichatbasecomponent; if (deathMessage.equals(deathmessage)) { - ScoreboardTeamBase scoreboardteambase = this.be(); + ichatbasecomponent = this.getCombatTracker().getDeathMessage(); + } else { + ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage); + } - if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS) { - if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OTHER_TEAMS) { - this.server.getPlayerList().a((EntityHuman) this, chatmessage); - } else if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OWN_TEAM) { - this.server.getPlayerList().b((EntityHuman) this, chatmessage); - } - } else { - this.server.getPlayerList().sendMessage(chatmessage); + this.playerConnection.a((Packet) (new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent)), (future) -> { + if (!future.isSuccess()) { + String s = ichatbasecomponent.a(256); + ChatMessage chatmessage = new ChatMessage("death.attack.message_too_long", new Object[] { (new ChatComponentText(s)).a(EnumChatFormat.YELLOW)}); + IChatBaseComponent ichatbasecomponent1 = (new ChatMessage("death.attack.even_more_magic", new Object[] { this.getScoreboardDisplayName()})).a((chatmodifier) -> { + chatmodifier.setChatHoverable(new ChatHoverable(ChatHoverable.EnumHoverAction.SHOW_TEXT, chatmessage)); + }); + + this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, ichatbasecomponent1)); + } + + }); + ScoreboardTeamBase scoreboardteambase = this.be(); + + if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS) { + if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OTHER_TEAMS) { + this.server.getPlayerList().a((EntityHuman) this, ichatbasecomponent); + } else if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OWN_TEAM) { + this.server.getPlayerList().b((EntityHuman) this, ichatbasecomponent); } } else { - this.server.getPlayerList().sendMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromString(deathMessage)); + this.server.getPlayerList().sendMessage(ichatbasecomponent); } + } else { + this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED)); } this.releaseShoulderEntities(); @@ -555,7 +573,6 @@ public class EntityPlayer extends EntityHuman implements ICrafting { // CraftBukkit - Get our scores instead this.world.getServer().getScoreboardManager().getScoreboardScores(IScoreboardCriteria.d, this.getName(), ScoreboardScore::incrementScore); - EntityLiving entityliving = this.cv(); if (entityliving != null) { @@ -565,7 +582,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.a(StatisticList.DEATHS); this.a(StatisticList.CUSTOM.b(StatisticList.TIME_SINCE_DEATH)); - this.a(StatisticList.CUSTOM.b(StatisticList.n)); + this.a(StatisticList.CUSTOM.b(StatisticList.TIME_SINCE_REST)); this.extinguish(); this.setFlag(0, false); this.getCombatTracker().g(); @@ -612,7 +629,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (this.isInvulnerable(damagesource)) { return false; } else { - boolean flag = this.server.S() && this.canPvP() && "fall".equals(damagesource.translationIndex); + boolean flag = this.server.Q() && this.canPvP() && "fall".equals(damagesource.translationIndex); if (!flag && this.invulnerableTicks > 0 && damagesource != DamageSource.OUT_OF_WORLD) { return false; @@ -626,8 +643,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting { if (entity instanceof EntityArrow) { EntityArrow entityarrow = (EntityArrow) entity; + Entity entity1 = entityarrow.getShooter(); - if (entityarrow.shooter instanceof EntityHuman && !this.a((EntityHuman) entityarrow.shooter)) { + if (entity1 instanceof EntityHuman && !this.a((EntityHuman) entity1)) { return false; } } @@ -648,39 +666,39 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } @Nullable - public Entity d(int i) { + public Entity a(DimensionManager dimensionmanager) { if (this.isSleeping()) return this; // CraftBukkit - SPIGOT-3154 // this.worldChangeInvuln = true; // CraftBukkit - Moved down and into PlayerList#changeDimension - if (this.dimension == 0 && i == -1) { - this.cD = new Vec3D(this.locX, this.locY, this.locZ); - } else if (this.dimension != -1 && i != 0) { - this.cD = null; + if (this.dimension == DimensionManager.OVERWORLD && dimensionmanager == DimensionManager.NETHER) { + this.cC = new Vec3D(this.locX, this.locY, this.locZ); + } else if (this.dimension != DimensionManager.NETHER && dimensionmanager != DimensionManager.OVERWORLD) { + this.cC = null; } - if (this.dimension == 1 && i == 1) { + if (this.dimension == DimensionManager.THE_END && dimensionmanager == DimensionManager.THE_END) { this.worldChangeInvuln = true; // CraftBukkit - Moved down from above this.world.kill(this); if (!this.viewingCredits) { this.viewingCredits = true; if (world.paperConfig.disableEndCredits) this.setHasSeenCredits(true); // Paper - Toggle to always disable end credits - this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(4, this.cy ? 0.0F : 1.0F)); - this.cy = true; + this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(4, this.cx ? 0.0F : 1.0F)); + this.cx = true; } return this; } else { - if (this.dimension == 0 && i == 1) { - i = 1; + if (this.dimension == DimensionManager.OVERWORLD && dimensionmanager == DimensionManager.THE_END) { + dimensionmanager = DimensionManager.THE_END; } // CraftBukkit start - TeleportCause cause = (this.dimension == 1 || i == 1) ? TeleportCause.END_PORTAL : TeleportCause.NETHER_PORTAL; - this.server.getPlayerList().changeDimension(this, i, cause); // PAIL: check all this + TeleportCause cause = (this.dimension == DimensionManager.THE_END || i == DimensionManager.THE_END) ? TeleportCause.END_PORTAL : TeleportCause.NETHER_PORTAL; + this.server.getPlayerList().changeDimension(this, dimensionmanager, cause); // PAIL: check all this // CraftBukkit end this.playerConnection.sendPacket(new PacketPlayOutWorldEvent(1032, BlockPosition.ZERO, 0, false)); this.lastSentExp = -1; this.lastHealthSent = -1.0F; - this.cp = -1; + this.co = -1; return this; } } @@ -766,7 +784,6 @@ public class EntityPlayer extends EntityHuman implements ICrafting { synchronized (((IMixinWorldServer) worldServer).trackLock()) { // Akarin worldServer.tracker.track(this); } - worldServer.tracker.track(this); } // Paper end @@ -818,10 +835,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void openTileEntity(ITileEntityContainer itileentitycontainer) { // CraftBukkit start - Inventory open hook - if (false && itileentitycontainer instanceof ILootable && ((ILootable) itileentitycontainer).Q_() != null && this.isSpectator()) { + if (false && itileentitycontainer instanceof ILootable && ((ILootable) itileentitycontainer).getLootTable() != null && this.isSpectator()) { this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).a(EnumChatFormat.RED), true); } else { - boolean cancelled = itileentitycontainer instanceof ILootable && ((ILootable) itileentitycontainer).Q_() != null && this.isSpectator(); + boolean cancelled = itileentitycontainer instanceof ILootable && ((ILootable) itileentitycontainer).getLootTable()!= null && this.isSpectator(); Container container = CraftEventFactory.callInventoryOpenEvent(this, itileentitycontainer.createContainer(this.inventory, this), cancelled); if (container == null) { return; @@ -860,7 +877,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } // CraftBukkit end - if (iinventory instanceof ILootable && ((ILootable) iinventory).Q_() != null && this.isSpectator()) { + if (iinventory instanceof ILootable && ((ILootable) iinventory).getLootTable() != null && this.isSpectator()) { this.a((new ChatMessage("container.spectatorCantOpen", new Object[0])).a(EnumChatFormat.RED), true); } else { if (this.activeContainer != this.defaultContainer) { @@ -1033,19 +1050,19 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public void a(Statistic statistic, int i) { - this.ch.b(this, statistic, i); + this.cg.b(this, statistic, i); this.world.getServer().getScoreboardManager().getScoreboardScores(statistic, this.getName(), (scoreboardscore) -> { // CraftBukkit - Get our scores instead scoreboardscore.addScore(i); }); } public void a(Statistic statistic) { - this.ch.setStatistic(this, statistic, 0); + this.cg.setStatistic(this, statistic, 0); this.world.getServer().getScoreboardManager().getScoreboardScores(statistic, this.getName(), ScoreboardScore::c); // CraftBukkit - Get our scores instead } public int a(Collection collection) { - return this.cz.a(collection, this); + return this.cy.a(collection, this); } public void a(MinecraftKey[] aminecraftkey) { @@ -1066,7 +1083,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public int b(Collection collection) { - return this.cz.b(collection, this); + return this.cy.b(collection, this); } public void giveExp(int i) { @@ -1075,7 +1092,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public void n() { - this.cC = true; + this.cB = true; this.ejectPassengers(); if (this.sleeping) { this.a(true, false, false); @@ -1084,7 +1101,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public boolean o() { - return this.cC; + return this.cB; } public void triggerHealthUpdate() { @@ -1149,15 +1166,18 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.getDataWatcher().set(EntityPlayer.bx, entityplayer.getDataWatcher().get(EntityPlayer.bx)); this.lastSentExp = -1; this.lastHealthSent = -1.0F; - this.cp = -1; - // this.cz.a((RecipeBook) entityplayer.cz); // CraftBukkit - // Paper start - Optimize remove queue + this.co = -1; + // this.cy.a((RecipeBook) entityplayer.cy); // CraftBukkit + // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only + // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting" + // type logic so it does need to be called, maybe? This is silly. //this.removeQueue.addAll(entityplayer.removeQueue); if (this.removeQueue != entityplayer.removeQueue) { this.removeQueue.addAll(entityplayer.removeQueue); } - this.cy = entityplayer.cy; - this.cD = entityplayer.cD; + // Paper end + this.cx = entityplayer.cx; + this.cC = entityplayer.cC; this.setShoulderEntityLeft(entityplayer.getShoulderEntityLeft()); this.setShoulderEntityRight(entityplayer.getShoulderEntityRight()); } @@ -1166,8 +1186,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting { super.a(mobeffect); this.playerConnection.sendPacket(new PacketPlayOutEntityEffect(this.getId(), mobeffect)); if (mobeffect.getMobEffect() == MobEffects.LEVITATION) { - this.cB = this.ticksLived; - this.cA = new Vec3D(this.locX, this.locY, this.locZ); + this.cA = this.ticksLived; + this.cz = new Vec3D(this.locX, this.locY, this.locZ); } CriterionTriggers.A.a(this); @@ -1183,7 +1203,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { super.b(mobeffect); this.playerConnection.sendPacket(new PacketPlayOutRemoveEntityEffect(this.getId(), mobeffect.getMobEffect())); if (mobeffect.getMobEffect() == MobEffects.LEVITATION) { - this.cA = null; + this.cz = null; } CriterionTriggers.A.a(this); @@ -1253,7 +1273,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void a(IChatBaseComponent ichatbasecomponent, ChatMessageType chatmessagetype) { this.playerConnection.a((Packet) (new PacketPlayOutChat(ichatbasecomponent, chatmessagetype)), (future) -> { if (!future.isSuccess() && (chatmessagetype == ChatMessageType.GAME_INFO || chatmessagetype == ChatMessageType.SYSTEM)) { - this.playerConnection.sendPacket(new PacketPlayOutChat(EntityPlayer.cd, ChatMessageType.SYSTEM)); + boolean flag = true; + String s = ichatbasecomponent.a(256); + IChatBaseComponent ichatbasecomponent1 = (new ChatComponentText(s)).a(EnumChatFormat.YELLOW); + + this.playerConnection.sendPacket(new PacketPlayOutChat((new ChatMessage("multiplayer.message_not_delivered", new Object[] { ichatbasecomponent1})).a(EnumChatFormat.RED), ChatMessageType.SYSTEM)); } }); @@ -1273,7 +1297,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT); this.server.server.getPluginManager().callEvent(event); } - if (this.locale == null || !this.locale.equals(packetplayinsettings.b())) { // Paper - fix bug and check for null + if (this.locale == null || !this.locale.equals(packetplayinsettings.b())) { // Paper - check for null PlayerLocaleChangeEvent event = new PlayerLocaleChangeEvent(getBukkitEntity(), packetplayinsettings.b()); this.server.server.getPluginManager().callEvent(event); } @@ -1286,14 +1310,14 @@ public class EntityPlayer extends EntityHuman implements ICrafting { new com.destroystokyo.paper.event.player.PlayerLocaleChangeEvent(this.getBukkitEntity(), oldLocale, this.locale).callEvent(); } // Paper end - this.ct = packetplayinsettings.d(); - this.cu = packetplayinsettings.e(); + this.cs = packetplayinsettings.d(); + this.ct = packetplayinsettings.e(); this.getDataWatcher().set(EntityPlayer.bx, Byte.valueOf((byte) packetplayinsettings.f())); this.getDataWatcher().set(EntityPlayer.by, Byte.valueOf((byte) (packetplayinsettings.getMainHand() == EnumMainHand.LEFT ? 0 : 1))); } public EntityHuman.EnumChatVisibility getChatFlags() { - return this.ct; + return this.cs; } public void setResourcePack(String s, String s1) { @@ -1305,15 +1329,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public void resetIdleTimer() { - this.cv = SystemUtils.b(); + this.cu = SystemUtils.b(); } public ServerStatisticManager getStatisticManager() { - return this.ch; + return this.cg; } public RecipeBookServer B() { - return this.cz; + return this.cy; } public void c(Entity entity) { @@ -1341,16 +1365,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public Entity getSpecatorTarget() { - return (Entity) (this.cw == null ? this : this.cw); + return (Entity) (this.cv == null ? this : this.cv); } public void setSpectatorTarget(Entity entity) { Entity entity1 = this.getSpecatorTarget(); - this.cw = (Entity) (entity == null ? this : entity); - if (entity1 != this.cw) { - this.playerConnection.sendPacket(new PacketPlayOutCamera(this.cw)); - this.playerConnection.a(this.cw.locX, this.cw.locY, this.cw.locZ, this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit + this.cv = (Entity) (entity == null ? this : entity); + if (entity1 != this.cv) { + this.playerConnection.sendPacket(new PacketPlayOutCamera(this.cv)); + this.playerConnection.a(this.cv.locX, this.cv.locY, this.cv.locZ, this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit } } @@ -1372,7 +1396,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public long F() { - return this.cv; + return this.cu; } @Nullable @@ -1408,12 +1432,12 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } public AdvancementDataPlayer getAdvancementData() { - return this.cg; + return this.cf; } @Nullable public Vec3D M() { - return this.cD; + return this.cC; } // CraftBukkit start @@ -1431,7 +1455,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } else { WorldServer worldserver1 = this.getWorldServer(); - this.dimension = worldserver.worldProvider.getDimensionManager().getDimensionID(); + this.dimension = worldserver.worldProvider.getDimensionManager(); this.playerConnection.sendPacket(new PacketPlayOutRespawn(this.dimension, worldserver1.getDifficulty(), worldserver1.getWorldData().getType(), this.playerInteractManager.getGameMode())); this.server.getPlayerList().f(this); worldserver1.removeEntity(this); diff --git a/sources/src/main/java/net/minecraft/server/ItemEnderEye.java b/sources/src/main/java/net/minecraft/server/ItemEnderEye.java index 0a382120a..2b5ebd6c1 100644 --- a/sources/src/main/java/net/minecraft/server/ItemEnderEye.java +++ b/sources/src/main/java/net/minecraft/server/ItemEnderEye.java @@ -23,15 +23,15 @@ public class ItemEnderEye extends Item { } else { IBlockData iblockdata1 = (IBlockData) iblockdata.set(BlockEnderPortalFrame.EYE, Boolean.valueOf(true)); - Block.a(iblockdata, iblockdata1, (GeneratorAccess) world, blockposition); + Block.a(iblockdata, iblockdata1, world, blockposition); world.setTypeAndData(blockposition, iblockdata1, 2); world.updateAdjacentComparators(blockposition, Blocks.END_PORTAL_FRAME); itemactioncontext.getItemStack().subtract(1); for (int i = 0; i < 16; ++i) { - double d0 = (double) ((float) blockposition.getX() + (5.0F + ItemEnderEye.k.nextFloat() * 6.0F) / 16.0F); + double d0 = (double) ((float) blockposition.getX() + (5.0F + ItemEnderEye.i.nextFloat() * 6.0F) / 16.0F); double d1 = (double) ((float) blockposition.getY() + 0.8125F); - double d2 = (double) ((float) blockposition.getZ() + (5.0F + ItemEnderEye.k.nextFloat() * 6.0F) / 16.0F); + double d2 = (double) ((float) blockposition.getZ() + (5.0F + ItemEnderEye.i.nextFloat() * 6.0F) / 16.0F); double d3 = 0.0D; double d4 = 0.0D; double d5 = 0.0D; @@ -71,7 +71,7 @@ public class ItemEnderEye extends Item { } else { entityhuman.c(enumhand); if (!world.isClientSide) { - BlockPosition blockposition = ((WorldServer) world).getChunkProviderServer().a(world, "Stronghold", new BlockPosition(entityhuman), 100); + BlockPosition blockposition = ((WorldServer) world).getChunkProviderServer().a(world, "Stronghold", new BlockPosition(entityhuman), 100, false); if (blockposition != null) { EntityEnderSignal entityendersignal = new EntityEnderSignal(world, entityhuman.locX, entityhuman.locY + (double) (entityhuman.length / 2.0F), entityhuman.locZ); @@ -82,7 +82,7 @@ public class ItemEnderEye extends Item { CriterionTriggers.m.a((EntityPlayer) entityhuman, blockposition); } - world.a((EntityHuman) null, entityhuman.locX, entityhuman.locY, entityhuman.locZ, SoundEffects.ENTITY_ENDER_EYE_LAUNCH, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderEye.k.nextFloat() * 0.4F + 0.8F)); + world.a((EntityHuman) null, entityhuman.locX, entityhuman.locY, entityhuman.locZ, SoundEffects.ENTITY_ENDER_EYE_LAUNCH, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemEnderEye.i.nextFloat() * 0.4F + 0.8F)); world.a((EntityHuman) null, 1003, new BlockPosition(entityhuman), 0); if (!entityhuman.abilities.canInstantlyBuild) { itemstack.subtract(1); diff --git a/sources/src/main/java/net/minecraft/server/NetworkManager.java b/sources/src/main/java/net/minecraft/server/NetworkManager.java index 30520ad98..57da82f5a 100644 --- a/sources/src/main/java/net/minecraft/server/NetworkManager.java +++ b/sources/src/main/java/net/minecraft/server/NetworkManager.java @@ -20,6 +20,8 @@ import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import java.net.SocketAddress; import java.util.Queue; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Supplier; import javax.annotation.Nullable; import javax.crypto.SecretKey; import org.apache.commons.lang3.Validate; @@ -48,7 +50,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { return new DefaultEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build()); }); private final EnumProtocolDirection h; - private final Queue i = Queues.newConcurrentLinkedQueue(); + private final Queue i = Queues.newConcurrentLinkedQueue(); private final Queue getPacketQueue() { return this.i; } // Paper - OBFHELPER private final ReentrantReadWriteUpdateLock j = new ReentrantReadWriteUpdateLock(); // Akarin - use update lock public Channel channel; // Spigot Start // PAIL @@ -162,8 +164,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - if (this.isConnected()) { - this.o(); + if (this.isConnected() && this.sendPacketQueue() && !(packet instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) packet).isReady())) { // Paper - Async-Anti-Xray - Add chunk packets which are not ready or all packets if the packet queue contains chunk packets which are not ready to the packet queue and send the packets later in the right order + //this.o(); // Paper - Async-Anti-Xray - Move to if statement (this.sendPacketQueue()) this.b(packet, genericfuturelistener); } else { this.j.writeLock().lock(); @@ -177,6 +179,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } + private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { EnumProtocol enumprotocol = EnumProtocol.a(packet); EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); @@ -217,22 +220,38 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } - private void o() { + // Paper start - Async-Anti-Xray - Stop dispatching further packets and return false if the peeked packet is a chunk packet which is not ready + private boolean sendPacketQueue() { return this.o(); } // OBFHELPER // void -> boolean + private boolean o() { // void -> boolean if (this.channel != null && this.channel.isOpen()) { - this.j.updateLock().lock(); // Akarin + if (this.i.isEmpty()) { // return if the packet queue is empty so that the write lock by Anti-Xray doesn't affect the vanilla performance at all + return true; + } + + this.j.writeLock().lock(); // readLock -> writeLock (because of race condition between peek and poll) try { while (!this.i.isEmpty()) { - NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.i.poll(); + NetworkManager.QueuedPacket networkmanager_queuedpacket = (NetworkManager.QueuedPacket) this.getPacketQueue().peek(); // poll -> peek - this.b(networkmanager_queuedpacket.a, networkmanager_queuedpacket.b); + if (networkmanager_queuedpacket != null) { // Fix NPE (Spigot bug caused by handleDisconnection()) + if (networkmanager_queuedpacket.getPacket() instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) networkmanager_queuedpacket.getPacket()).isReady()) { // Check if the peeked packet is a chunk packet which is not ready + return false; // Return false if the peeked packet is a chunk packet which is not ready + } else { + this.getPacketQueue().poll(); // poll here + this.dispatchPacket(networkmanager_queuedpacket.getPacket(), networkmanager_queuedpacket.getGenericFutureListener()); // dispatch the packet + } + } } } finally { - this.j.updateLock().unlock(); // Akarin + this.j.writeLock().unlock(); // readLock -> writeLock (because of race condition between peek and poll) } } + + return true; // Return true if all packets were dispatched } + // Paper end public void a() { this.o(); @@ -345,11 +364,11 @@ public class NetworkManager extends SimpleChannelInboundHandler> { this.a(channelhandlercontext, (Packet) object); } - static class QueuedPacket { + public static class QueuedPacket { // Akarin - private final Packet a; + private final Packet a; public final Packet getPacket() { return this.a; } // Paper - OBFHELPER // Akarin @Nullable - private final GenericFutureListener> b; + private final GenericFutureListener> b; public final GenericFutureListener> getGenericFutureListener() { return this.b; } // Paper - OBFHELPER // Akarin public QueuedPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { this.a = packet; diff --git a/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java index 30fdc2f22..63cdcdac0 100644 --- a/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +++ b/sources/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java @@ -1,9 +1,11 @@ package net.minecraft.server; +import com.destroystokyo.paper.antixray.ChunkPacketInfo; // Paper - Anti-Xray import com.google.common.collect.Lists; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import java.io.IOException; +import java.security.KeyStore.PrivateKeyEntry; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; @@ -17,20 +19,33 @@ public class PacketPlayOutMapChunk implements Packet { private int a; private int b; private int c; - private ByteBuf d; // Akarin - byte[] -> ByteBuf + private ByteBuf d; private ByteBuf getData() { return this.d; } // Paper - OBFHELPER // Akarin - byte[] -> ByteBuf private List e; private boolean f; + private volatile boolean ready = false; // Paper - Async-Anti-Xray - Ready flag for the network manager - public PacketPlayOutMapChunk() {} + // Paper start - Async-Anti-Xray - Set the ready flag to true + public PacketPlayOutMapChunk() { + this.ready = true; + } + // Paper end public PacketPlayOutMapChunk(Chunk chunk, int i) { + ChunkPacketInfo chunkPacketInfo = chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i); // Paper - Anti-Xray - Add chunk packet info this.a = chunk.locX; this.b = chunk.locZ; this.f = i == '\uffff'; boolean flag = chunk.getWorld().worldProvider.g(); this.d = allocateBuffer(this.a(chunk, flag, i)); // Akarin - this.c = this.a(new PacketDataSerializer(this.d), chunk, flag, i); // Akarin + + // Paper start - Anti-Xray - Add chunk packet info + if (chunkPacketInfo != null) { + chunkPacketInfo.setData(this.getData()); + } + // Paper end + + this.c = this.writeChunk(new PacketDataSerializer(this.getData()), chunk, flag, i, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info // Akarin this.e = Lists.newArrayList(); Iterator iterator = chunk.getTileEntities().entrySet().iterator(); @@ -48,8 +63,19 @@ public class PacketPlayOutMapChunk implements Packet { } } + chunk.world.chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks } + // Paper start - Async-Anti-Xray - Getter and Setter for the ready flag + public boolean isReady() { + return this.ready; + } + + public void setReady(boolean ready) { + this.ready = ready; + } + // Paper end + public void a(PacketDataSerializer packetdataserializer) throws IOException { this.a = packetdataserializer.readInt(); this.b = packetdataserializer.readInt(); @@ -78,8 +104,8 @@ public class PacketPlayOutMapChunk implements Packet { packetdataserializer.writeInt(this.b); packetdataserializer.writeBoolean(this.f); packetdataserializer.d(this.c); - packetdataserializer.d(this.d.array().length); // Akarin - packetdataserializer.writeBytes(this.d.array()); // Akarin + packetdataserializer.d(this.getData().capacity()); // Akarin + packetdataserializer.writeBytes(this.getData().array()); // Akarin packetdataserializer.d(this.e.size()); Iterator iterator = this.e.iterator(); @@ -95,15 +121,23 @@ public class PacketPlayOutMapChunk implements Packet { packetlistenerplayout.a(this); } - private ByteBuf allocateBuffer(int expectedCapacity) { return h(expectedCapacity); } // Akarin - OBFHELPER - private ByteBuf h(int expectedCapacity) { // Akarin - added argument - ByteBuf bytebuf = Unpooled.buffer(expectedCapacity); // Akarin + private ByteBuf h() { return allocateBuffer(-1); } // Akarin + private ByteBuf allocateBuffer(int expectedCapacity) { // Akarin - added argument + ByteBuf bytebuf = expectedCapacity == -1 ? Unpooled.buffer() : Unpooled.buffer(expectedCapacity); // Akarin bytebuf.writerIndex(0); return bytebuf; } + // Paper start - Anti-Xray - Support default methods + public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, boolean writeSkyLightArray, int chunkSectionSelector) { return this.a(packetDataSerializer, chunk, writeSkyLightArray, chunkSectionSelector); } public int a(PacketDataSerializer packetdataserializer, Chunk chunk, boolean flag, int i) { + return this.a(packetdataserializer, chunk, flag, i, null); + } + // Paper end + + public int writeChunk(PacketDataSerializer packetDataSerializer, Chunk chunk, boolean writeSkyLightArray, int chunkSectionSelector, ChunkPacketInfo chunkPacketInfo) { return this.a(packetDataSerializer, chunk, writeSkyLightArray, chunkSectionSelector, chunkPacketInfo); } // Paper - OBFHELPER // Paper - Anti-Xray - Add chunk packet info + public int a(PacketDataSerializer packetdataserializer, Chunk chunk, boolean flag, int i, ChunkPacketInfo chunkPacketInfo) { // Paper - Anti-Xray - Add chunk packet info int j = 0; ChunkSection[] achunksection = chunk.getSections(); int k = 0; @@ -115,7 +149,7 @@ public class PacketPlayOutMapChunk implements Packet { if (chunksection != Chunk.a && (!this.f() || !chunksection.a()) && (i & 1 << k) != 0) { j |= 1 << k; - chunksection.getBlocks().b(packetdataserializer); + chunksection.getBlocks().writeDataPaletteBlock(packetdataserializer, chunkPacketInfo, k); // Paper - Anti-Xray - Add chunk packet info packetdataserializer.writeBytes(chunksection.getEmittedLightArray().asBytes()); if (flag) { packetdataserializer.writeBytes(chunksection.getSkyLightArray().asBytes()); @@ -127,7 +161,7 @@ public class PacketPlayOutMapChunk implements Packet { BiomeBase[] abiomebase = chunk.getBiomeIndex(); for (l = 0; l < abiomebase.length; ++l) { - packetdataserializer.writeInt(BiomeBase.REGISTRY_ID.a((BiomeBase) abiomebase[l])); + packetdataserializer.writeInt(IRegistry.BIOME.a(abiomebase[l])); // Paper - decompile fix } } @@ -161,4 +195,4 @@ public class PacketPlayOutMapChunk implements Packet { public boolean f() { return this.f; } -} \ No newline at end of file +} diff --git a/sources/src/main/java/net/minecraft/server/PlayerConnection.java b/sources/src/main/java/net/minecraft/server/PlayerConnection.java index ae78daf0b..70cc49d82 100644 --- a/sources/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/sources/src/main/java/net/minecraft/server/PlayerConnection.java @@ -2,7 +2,9 @@ package net.minecraft.server; import com.google.common.primitives.Doubles; import com.google.common.primitives.Floats; +import com.google.common.util.concurrent.Futures; import com.mojang.brigadier.ParseResults; +import com.mojang.brigadier.StringReader; import com.mojang.brigadier.suggestion.Suggestions; import io.akarin.api.internal.Akari; @@ -10,16 +12,18 @@ import io.akarin.server.core.AkarinGlobalConfig; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import java.util.Collections; +import java.util.Iterator; import java.util.Set; +import java.util.function.Consumer; import javax.annotation.Nullable; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +// CraftBukkit start +import java.util.HashSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.event.CraftEventFactory; @@ -58,6 +62,7 @@ import org.bukkit.inventory.CraftingInventory; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.InventoryView; import org.bukkit.util.NumberConversions; +import com.destroystokyo.paper.event.player.IllegalPacketEvent; // Paper import com.destroystokyo.paper.event.player.PlayerJumpEvent; // Paper import co.aikar.timings.MinecraftTimings; // Paper // CraftBukkit end @@ -109,7 +114,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { private int E; private int receivedMovePackets; private int processedMovePackets; - private static final long KEEPALIVE_LIMIT = /*Long.getLong("paper.playerconnection.keepalive", 30)*/ AkarinGlobalConfig.keepAliveTimeout * 1000; // Paper - provide property to set keepalive limit // Akarin - more accessible - keep changes + private static final long KEEPALIVE_LIMIT = /*Long.getLong("paper.playerconnection.keepalive", 30)*/ AkarinGlobalConfig.keepAliveTimeout * 1000; // Paper - provide property to set keepalive limit // Akarin - more accessible public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { this.minecraftServer = minecraftserver; @@ -351,7 +356,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } speed *= 2f; // TODO: Get the speed of the vehicle instead of the player - if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && (!this.minecraftServer.J() || !this.minecraftServer.I().equals(entity.getDisplayName().getString()))) { + if (d10 - d9 > Math.max(100.0D, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && (!this.minecraftServer.H() || !this.minecraftServer.G().equals(entity.getDisplayName().getString()))) { // CraftBukkit end PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", entity.getDisplayName().getString(), this.player.getDisplayName().getString(), Double.valueOf(d6), Double.valueOf(d7), Double.valueOf(d8)); this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity)); @@ -473,10 +478,10 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { PlayerConnectionUtils.ensureMainThread(packetplayinteleportaccept, this, this.player.getWorldServer()); if (packetplayinteleportaccept.b() == this.teleportAwait && this.teleportPos != null) { // CraftBukkit this.player.setLocation(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch); + this.o = this.teleportPos.x; + this.p = this.teleportPos.y; + this.q = this.teleportPos.z; if (this.player.H()) { - this.o = this.teleportPos.x; - this.p = this.teleportPos.y; - this.q = this.teleportPos.z; this.player.I(); } @@ -523,6 +528,13 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { minecraftServer.postToMainThread(() -> this.disconnect(new ChatMessage("disconnect.spam", new Object[0]))); // Paper return; } + // CraftBukkit end + StringReader stringreader = new StringReader(packetplayintabcomplete.c()); + + if (stringreader.canRead() && stringreader.peek() == 47) { + stringreader.skip(); + } + // Paper start com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event; java.util.List completions = new java.util.ArrayList<>(); @@ -770,12 +782,13 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { return; } this.lastBookTick = MinecraftServer.currentTick; + EnumItemSlot enumitemslot = packetplayinbedit.d() == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND; // CraftBukkit end ItemStack itemstack = packetplayinbedit.b(); if (!itemstack.isEmpty()) { if (ItemBookAndQuill.b(itemstack.getTag())) { - ItemStack itemstack1 = this.player.getItemInMainHand(); + ItemStack itemstack1 = this.player.b(packetplayinbedit.d()); if (!itemstack1.isEmpty()) { if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack1.getItem() == Items.WRITABLE_BOOK) { @@ -795,10 +808,13 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { } itemstack2.a("pages", (NBTBase) nbttaglist); - CraftEventFactory.handleEditBookEvent(player, itemstack2); // CraftBukkit + // EnumItemSlot enumitemslot = packetplayinbedit.d() == EnumHand.MAIN_HAND ? EnumItemSlot.MAINHAND : EnumItemSlot.OFFHAND; // CraftBukkit - Moved up + + this.player.setSlot(enumitemslot, CraftEventFactory.handleEditBookEvent(player, enumitemslot, itemstack1, itemstack2)); // CraftBukkit } else { + ItemStack old = itemstack1.cloneItemStack(); // CraftBukkit itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); - CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit + CraftEventFactory.handleEditBookEvent(player, enumitemslot, old, itemstack1); // CraftBukkit } } @@ -809,7 +825,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { public void a(PacketPlayInEntityNBTQuery packetplayinentitynbtquery) { PlayerConnectionUtils.ensureMainThread(packetplayinentitynbtquery, this, this.player.getWorldServer()); - if (this.player.k(2)) { + if (this.player.j(2)) { Entity entity = this.player.getWorldServer().getEntity(packetplayinentitynbtquery.c()); if (entity != null) { @@ -823,7 +839,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { public void a(PacketPlayInTileNBTQuery packetplayintilenbtquery) { PlayerConnectionUtils.ensureMainThread(packetplayintilenbtquery, this, this.player.getWorldServer()); - if (this.player.k(2)) { + if (this.player.j(2)) { TileEntity tileentity = this.player.getWorldServer().getTileEntity(packetplayintilenbtquery.c()); NBTTagCompound nbttagcompound = tileentity != null ? tileentity.save(new NBTTagCompound()) : null; @@ -912,7 +928,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { if (!this.player.H() && (!this.player.getWorldServer().getGameRules().getBoolean("disableElytraMovementCheck") || !this.player.dc())) { float f2 = this.player.dc() ? 300.0F : 100.0F; - if (d11 - d10 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && (!this.minecraftServer.J() || !this.minecraftServer.I().equals(this.player.getProfile().getName()))) { + if (d11 - d10 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && (!this.minecraftServer.H() || !this.minecraftServer.G().equals(this.player.getProfile().getName()))) { // CraftBukkit end PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getDisplayName().getString(), Double.valueOf(d7), Double.valueOf(d8), Double.valueOf(d9)); this.a(this.player.locX, this.player.locY, this.player.locZ, this.player.yaw, this.player.pitch); @@ -1158,6 +1174,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.A = this.e; this.player.setLocation(d0, d1, d2, f, f1); this.player.playerConnection.sendPacket(new PacketPlayOutPosition(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.teleportAwait)); + this.minecraftServer.getPlayerList().d(this.player); // CraftBukkit } public void a(PacketPlayInBlockDig packetplayinblockdig) { @@ -1384,17 +1401,14 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { PlayerConnectionUtils.ensureMainThread(packetplayinspectate, this, this.player.getWorldServer()); if (this.player.isSpectator()) { Entity entity = null; - WorldServer[] aworldserver = this.minecraftServer.worldServer; - int i = aworldserver.length; + Iterator iterator = this.minecraftServer.getWorlds().iterator(); - // CraftBukkit - use the worlds array list - for (WorldServer worldserver : minecraftServer.worlds) { + while (iterator.hasNext()) { + WorldServer worldserver = (WorldServer) iterator.next(); - if (worldserver != null) { - entity = packetplayinspectate.a(worldserver); - if (entity != null) { - break; - } + entity = packetplayinspectate.a(worldserver); + if (entity != null) { + break; } } @@ -1433,7 +1447,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { PlayerConnection.LOGGER.info("{} lost connection: {}", this.player.getDisplayName().getString(), ichatbasecomponent.getString()); // CraftBukkit start - Replace vanilla quit message handling with our own. /* - this.minecraftServer.av(); + this.minecraftServer.at(); this.minecraftServer.getPlayerList().sendMessage((new ChatMessage("multiplayer.player.left", new Object[] { this.player.getScoreboardDisplayName()})).a(EnumChatFormat.YELLOW)); */ @@ -1443,7 +1457,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.minecraftServer.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage)); } // CraftBukkit end - if (this.minecraftServer.J() && this.player.getDisplayName().getString().equals(this.minecraftServer.I())) { + if (this.minecraftServer.H() && this.player.getDisplayName().getString().equals(this.minecraftServer.G())) { PlayerConnection.LOGGER.info("Stopping singleplayer server as player logged out"); this.minecraftServer.safeShutdown(); } @@ -2030,15 +2044,15 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { case PERFORM_RESPAWN: if (this.player.viewingCredits) { this.player.viewingCredits = false; - // this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, true); - this.minecraftServer.getPlayerList().changeDimension(this.player, 0, PlayerTeleportEvent.TeleportCause.END_PORTAL); // CraftBukkit - reroute logic through custom portal management + // this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, DimensionManager.OVERWORLD, true); + this.minecraftServer.getPlayerList().changeDimension(this.player, DimensionManager.OVERWORLD, PlayerTeleportEvent.TeleportCause.END_PORTAL); // CraftBukkit - reroute logic through custom portal management CriterionTriggers.v.a(this.player, DimensionManager.THE_END, DimensionManager.OVERWORLD); } else { if (this.player.getHealth() > 0.0F) { return; } - this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, 0, false); + this.player = this.minecraftServer.getPlayerList().moveToWorld(this.player, DimensionManager.OVERWORLD, false); if (this.minecraftServer.isHardcore()) { this.player.a(EnumGamemode.SPECTATOR); this.player.getWorldServer().getGameRules().set("spectatorsGenerateChunks", "false", this.minecraftServer); @@ -2544,10 +2558,10 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { this.player.ping = (this.player.ping * 3 + i) / 4; this.g = false; - } else if (!this.player.getDisplayName().getString().equals(this.minecraftServer.I())) { + } else if (!this.player.getDisplayName().getString().equals(this.minecraftServer.G())) { // Paper start - This needs to be handled on the main thread for plugins minecraftServer.postToMainThread(() -> { - this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); + this.disconnect(new ChatMessage("disconnect.timeout", new Object[0])); }); // Paper end } diff --git a/sources/src/main/java/net/minecraft/server/TileEntitySkull.java b/sources/src/main/java/net/minecraft/server/TileEntitySkull.java index faa5471b0..372b0d540 100644 --- a/sources/src/main/java/net/minecraft/server/TileEntitySkull.java +++ b/sources/src/main/java/net/minecraft/server/TileEntitySkull.java @@ -87,7 +87,7 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa // Spigot end public TileEntitySkull() { - super(TileEntityTypes.p); + super(TileEntityTypes.SKULL); } public static void a(UserCache usercache) { @@ -113,12 +113,12 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa public void load(NBTTagCompound nbttagcompound) { super.load(nbttagcompound); if (nbttagcompound.hasKeyOfType("Owner", 10)) { - this.a = GameProfileSerializer.deserialize(nbttagcompound.getCompound("Owner")); + this.setGameProfile(GameProfileSerializer.deserialize(nbttagcompound.getCompound("Owner"))); } else if (nbttagcompound.hasKeyOfType("ExtraType", 8)) { String s = nbttagcompound.getString("ExtraType"); if (!UtilColor.b(s)) { - this.a = new GameProfile((UUID) null, s); + this.setGameProfile(new GameProfile((UUID) null, s)); this.f(); } } @@ -143,7 +143,7 @@ public class TileEntitySkull extends TileEntity /*implements ITickable*/ { // Pa public GameProfile getGameProfile() { return this.a; } - + // Paper start static NBTTagCompound sanitizeTileEntityUUID(NBTTagCompound cmp) { NBTTagCompound owner = cmp.getCompound("Owner"); diff --git a/sources/src/main/java/net/minecraft/server/WorldServer.java b/sources/src/main/java/net/minecraft/server/WorldServer.java index ded33901b..59abde338 100644 --- a/sources/src/main/java/net/minecraft/server/WorldServer.java +++ b/sources/src/main/java/net/minecraft/server/WorldServer.java @@ -1,19 +1,22 @@ package net.minecraft.server; +import co.aikar.timings.Timings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.util.concurrent.ListenableFuture; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.logging.log4j.LogManager; @@ -23,6 +26,10 @@ import org.apache.logging.log4j.Logger; import java.util.logging.Level; import org.bukkit.WeatherType; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.util.HashTreeSet; + +import org.bukkit.event.block.BlockFormEvent; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.weather.LightningStrikeEvent; // CraftBukkit end @@ -41,7 +48,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { public final PlayerChunkMap manager; // Akarin - private -> public public final Map entitiesByUUID = Maps.newHashMap(); // Paper public boolean savingDisabled; - private boolean K; + private boolean J; private int emptyTime; private final PortalTravelAgent portalTravelAgent; private final SpawnerCreature spawnerCreature = new SpawnerCreature(); @@ -49,74 +56,73 @@ public class WorldServer extends World implements IAsyncTaskHandler { private final TickListServer nextTickListFluid; protected final VillageSiege siegeManager; ObjectLinkedOpenHashSet d; - private boolean Q; + private boolean P; // CraftBukkit start + public final DimensionManager dimension; private static final boolean DEBUG_ENTITIES = Boolean.getBoolean("debug.entities"); // Paper private static Throwable getAddToWorldStackTrace(Entity entity) { return new Throwable(entity + " Added to world at " + new java.util.Date()); } - public final int dimension; // Add env and gen to constructor - public WorldServer(MinecraftServer minecraftserver, IDataManager idatamanager, WorldData worlddata, int i, MethodProfiler methodprofiler, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { - super(idatamanager, worlddata, DimensionManager.a(env.getId()).d(), methodprofiler, false, gen, env); - this.dimension = i; + public WorldServer(MinecraftServer minecraftserver, IDataManager idatamanager, PersistentCollection persistentcollection, WorldData worlddata, DimensionManager dimensionmanager, MethodProfiler methodprofiler, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { + super(idatamanager, persistentcollection, worlddata, DimensionManager.a(env.getId()).e(), methodprofiler, false, gen, env); + this.dimension = dimensionmanager; this.pvpMode = minecraftserver.getPVP(); worlddata.world = this; // CraftBukkit end Predicate predicate = (block) -> { // CraftBukkit - decompile error return block == null || block.getBlockData().isAir(); }; - RegistryBlocks registryblocks = Block.REGISTRY; + IRegistry iregistry = IRegistry.BLOCK; - Block.REGISTRY.getClass(); - Function function = registryblocks::b; - RegistryBlocks registryblocks1 = Block.REGISTRY; // CraftBukkit - decompile error + IRegistry.BLOCK.getClass(); + Function function = iregistry::getKey; + IRegistry iregistry1 = IRegistry.BLOCK; // CraftBukkit - decompile error - Block.REGISTRY.getClass(); - this.nextTickListBlock = new TickListServer<>(this, predicate, function, key -> registryblocks1.get((MinecraftKey) key), e -> b((NextTickListEntry) e), "Blocks"); // CraftBukkit - decompile error // Paper - Timings v2 // Akarin - decompile error - Predicate predicate2 = (fluidtype) -> { + IRegistry.BLOCK.getClass(); + this.nextTickListBlock = new TickListServer<>(this, predicate, function, iregistry1::getOrDefault, this::b, "Blocks"); // CraftBukkit - decompile error // Paper - Timings v2 + Predicate predicate2 = (fluidtype) -> { // CraftBukkit - decompile error return fluidtype == null || fluidtype == FluidTypes.a; }; - registryblocks = FluidType.c; - FluidType.c.getClass(); - function = registryblocks::b; - RegistryBlocks registryblocks2 = FluidType.c; // CraftBukkit - decompile error - FluidType.c.getClass(); - this.nextTickListFluid = new TickListServer<>(this, predicate2, function, registryblocks2::get, e -> a((NextTickListEntry) e), "Fluids"); // CraftBukkit - decompile error // Paper - Timings v2 // Akarin - decompile error + iregistry = IRegistry.FLUID; + IRegistry.FLUID.getClass(); + function = iregistry::getKey; + IRegistry iregistry2 = IRegistry.FLUID; // CraftBukkit - decompile error + IRegistry.FLUID.getClass(); + this.nextTickListFluid = new TickListServer<>(this, predicate2, function, iregistry2::getOrDefault, this::a, "Fluids"); // CraftBukkit - decompile error // Paper - Timings v2 this.siegeManager = new VillageSiege(this); this.d = new ObjectLinkedOpenHashSet(); this.server = minecraftserver; this.tracker = new EntityTracker(this); this.manager = new PlayerChunkMap(this); this.worldProvider.a((World) this); - this.chunkProvider = this.q(); + this.chunkProvider = this.r(); this.portalTravelAgent = new org.bukkit.craftbukkit.CraftTravelAgent(this); // CraftBukkit - this.O(); this.P(); - this.getWorldBorder().a(minecraftserver.aw()); + this.Q(); + this.getWorldBorder().a(minecraftserver.au()); } - public GeneratorAccess b() { - this.worldMaps = new PersistentCollection(this.dataManager); + public WorldServer i_() { String s = PersistentVillage.a(this.worldProvider); - PersistentVillage persistentvillage = (PersistentVillage) this.worldMaps.get(PersistentVillage::new, s); + PersistentVillage persistentvillage = (PersistentVillage) this.a(DimensionManager.OVERWORLD, PersistentVillage::new, s); if (persistentvillage == null) { this.villages = new PersistentVillage(this); - this.worldMaps.a(s, this.villages); + this.a(DimensionManager.OVERWORLD, s, (PersistentBase) this.villages); } else { this.villages = persistentvillage; this.villages.a((World) this); } if (getServer().getScoreboardManager() == null) { // CraftBukkit - PersistentScoreboard persistentscoreboard = (PersistentScoreboard) this.worldMaps.get(PersistentScoreboard::new, "scoreboard"); + PersistentScoreboard persistentscoreboard = (PersistentScoreboard) this.a(DimensionManager.OVERWORLD, PersistentScoreboard::new, "scoreboard"); if (persistentscoreboard == null) { persistentscoreboard = new PersistentScoreboard(); - this.worldMaps.a("scoreboard", persistentscoreboard); + this.a(DimensionManager.OVERWORLD, "scoreboard", (PersistentBase) persistentscoreboard); } persistentscoreboard.a((Scoreboard) this.server.getScoreboard()); @@ -264,9 +270,9 @@ public class WorldServer extends World implements IAsyncTaskHandler { } // CraftBukkit end - public void doTick() { - this.Q = true; - super.doTick(); + public void doTick(BooleanSupplier booleansupplier) { + this.P = true; + super.doTick(booleansupplier); // Akarin start - goes to slack service /* if (this.getWorldData().isHardcore() && this.getDifficulty() != EnumDifficulty.HARD) { @@ -283,7 +289,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.worldData.setDayTime(i - i % 24000L); } - this.h(); + this.i(); } this.methodProfiler.a("spawner"); @@ -299,7 +305,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { timings.doChunkUnload.startTiming(); // Spigot this.methodProfiler.c("chunkSource"); - this.chunkProvider.unloadChunks(); + this.chunkProvider.unloadChunks(booleansupplier); int j = this.a(1.0F); if (j != this.c()) { @@ -314,11 +320,11 @@ public class WorldServer extends World implements IAsyncTaskHandler { timings.doChunkUnload.stopTiming(); // Spigot this.methodProfiler.c("tickPending"); timings.scheduledBlocks.startTiming(); // Paper - this.p(); + this.q(); timings.scheduledBlocks.stopTiming(); // Paper this.methodProfiler.c("tickBlocks"); timings.chunkTicks.startTiming(); // Paper - this.l(); + this.n_(); timings.chunkTicks.stopTiming(); // Paper this.methodProfiler.c("chunkMap"); timings.doChunkMap.startTiming(); // Spigot @@ -335,9 +341,9 @@ public class WorldServer extends World implements IAsyncTaskHandler { timings.doPortalForcer.stopTiming(); // Spigot this.methodProfiler.e(); timings.doSounds.startTiming(); // Spigot - this.am(); + this.an(); timings.doSounds.stopTiming(); // Spigot - this.Q = false; + this.P = false; timings.doChunkGC.startTiming();// Spigot this.getWorld().processChunkGC(); // CraftBukkit @@ -345,7 +351,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } public boolean j_() { - return this.Q; + return this.P; } @Nullable @@ -362,7 +368,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } public void everyoneSleeping() { - this.K = false; + this.J = false; if (!this.players.isEmpty()) { int i = 0; int j = 0; @@ -378,7 +384,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } } - this.K = j > 0 && j >= this.players.size() - i; + this.J = j > 0 && j >= this.players.size() - i; } } @@ -387,8 +393,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { return this.server.getScoreboard(); } - protected void h() { - this.K = false; + protected void i() { + this.J = false; List list = (List) this.players.stream().filter(EntityHuman::isSleeping).collect(Collectors.toList()); Iterator iterator = list.iterator(); @@ -399,12 +405,12 @@ public class WorldServer extends World implements IAsyncTaskHandler { } if (this.getGameRules().getBoolean("doWeatherCycle")) { - this.ai(); + this.b(); } } - private void ai() { + private void b() { // CraftBukkit start this.worldData.setStorm(false); // If we stop due to everyone sleeping we should reset the weather duration to some other random value. @@ -424,7 +430,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } public boolean everyoneDeeplySleeping() { - if (this.K && !this.isClientSide) { + if (this.J && !this.isClientSide) { Iterator iterator = this.players.iterator(); // CraftBukkit - This allows us to assume that some people are in bed but not really, allowing time to pass in spite of AFKers @@ -460,7 +466,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { return this.getChunkProviderServer().isLoaded(i, j); } - protected void n_() { + protected void l() { this.methodProfiler.a("playerCheckLight"); if (spigotConfig.randomLightUpdates && !this.players.isEmpty()) { // Spigot int i = this.random.nextInt(this.players.size()); @@ -475,8 +481,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.methodProfiler.e(); } - protected void l() { - this.n_(); + protected void n_() { + this.l(); if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { Iterator iterator = this.manager.b(); @@ -487,7 +493,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } else { int i = this.getGameRules().c("randomTickSpeed"); boolean flag = this.isRaining(); - boolean flag1 = this.X(); + boolean flag1 = this.Y(); this.methodProfiler.a("pollingChunks"); @@ -512,18 +518,18 @@ public class WorldServer extends World implements IAsyncTaskHandler { blockposition = this.a(new BlockPosition(j + (l & 15), 0, k + (l >> 8 & 15))); if (this.isRainingAt(blockposition)) { DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition); + boolean flag2 = this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper - if (this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance) { + if (flag2) { EntityHorseSkeleton entityhorseskeleton = new EntityHorseSkeleton(this); entityhorseskeleton.s(true); entityhorseskeleton.setAgeRaw(0); entityhorseskeleton.setPosition((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); this.addEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit - this.strikeLightning(new EntityLightning(this, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), true)); - } else { - this.strikeLightning(new EntityLightning(this, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), false)); } + + this.strikeLightning(new EntityLightning(this, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, flag2)); } } @@ -611,7 +617,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { return; } } else { - this.q_(); + this.p(); } this.worldProvider.l(); @@ -667,11 +673,11 @@ public class WorldServer extends World implements IAsyncTaskHandler { } - public void q_() { + public void p() { this.emptyTime = 0; } - public void p() { + public void q() { if (this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES) { this.nextTickListBlock.a(); this.nextTickListFluid.a(); @@ -719,7 +725,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { return this.server.getSpawnAnimals(); } - protected IChunkProvider q() { + protected IChunkProvider r() { IChunkLoader ichunkloader = this.dataManager.createChunkLoader(this.worldProvider); // CraftBukkit start @@ -735,7 +741,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { gen = new org.bukkit.craftbukkit.generator.NormalChunkGenerator(this, this.getSeed()); } - return new ChunkProviderServer(this, ichunkloader, new co.aikar.timings.TimedChunkGenerator(this, gen), this.server); // Paper + return new ChunkProviderServer(this, ichunkloader, gen, this.server); // CraftBukkit end } @@ -748,7 +754,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { try { this.b(worldsettings); if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) { - this.al(); + this.am(); } super.a(worldsettings); @@ -769,7 +775,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } - private void al() { + private void am() { this.worldData.f(false); this.worldData.c(true); this.worldData.setStorm(false); @@ -816,7 +822,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { } boolean flag = false; - Iterator iterator = TagsBlock.I.a().iterator(); + Iterator iterator = TagsBlock.VALID_SPAWN.a().iterator(); while (iterator.hasNext()) { Block block = (Block) iterator.next(); @@ -856,13 +862,13 @@ public class WorldServer extends World implements IAsyncTaskHandler { } if (worldsettings.c()) { - this.r(); + this.s(); } } } - protected void r() { + protected void s() { WorldGenBonusChest worldgenbonuschest = new WorldGenBonusChest(); for (int i = 0; i < 10; ++i) { @@ -885,7 +891,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { public void save(boolean flag, @Nullable IProgressUpdate iprogressupdate) throws ExceptionWorldConflict { ChunkProviderServer chunkproviderserver = this.getChunkProviderServer(); - if (chunkproviderserver.e()) { + if (chunkproviderserver.d()) { if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit // Paper - Incremental Auto Saving - Only fire event on full save timings.worldSave.startTiming(); // Paper if (flag || server.serverAutoSave) { // Paper @@ -903,7 +909,8 @@ public class WorldServer extends World implements IAsyncTaskHandler { chunkproviderserver.a(flag); timings.worldSaveChunks.stopTiming(); // Paper // CraftBukkit - ArrayList -> Collection - /* //Paper start Collection arraylist = chunkproviderserver.a(); + /* //Paper start - disable vanilla chunk GC + java.util.Collection arraylist = chunkproviderserver.a(); Iterator iterator = arraylist.iterator(); while (iterator.hasNext()) { @@ -921,7 +928,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { public void flushSave() { ChunkProviderServer chunkproviderserver = this.getChunkProviderServer(); - if (chunkproviderserver.e()) { + if (chunkproviderserver.d()) { chunkproviderserver.c(); } } @@ -929,11 +936,10 @@ public class WorldServer extends World implements IAsyncTaskHandler { protected void a() throws ExceptionWorldConflict { timings.worldSaveLevel.startTiming(); // Paper this.checkSession(); - WorldServer[] aworldserver = this.server.worldServer; - int i = aworldserver.length; + Iterator iterator = this.server.getWorlds().iterator(); - for (int j = 0; j < i; ++j) { - WorldServer worldserver = aworldserver[j]; + while (iterator.hasNext()) { + WorldServer worldserver = (WorldServer) iterator.next(); if (worldserver instanceof SecondaryWorldServer) { ((SecondaryWorldServer) worldserver).t_(); @@ -955,9 +961,9 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.worldData.i(this.getWorldBorder().getWarningTime()); this.worldData.b(this.getWorldBorder().j()); this.worldData.c(this.getWorldBorder().i()); - this.worldData.c(this.server.aR().c()); + this.worldData.c(this.server.aP().c()); this.dataManager.saveWorldData(this.worldData, this.server.getPlayerList().t()); - this.worldMaps.a(); + this.h().a(); timings.worldSaveLevel.stopTiming(); // Paper } @@ -969,19 +975,14 @@ public class WorldServer extends World implements IAsyncTaskHandler { } // CraftBukkit end - public void a(Collection collection) { - ArrayList arraylist = Lists.newArrayList(collection); - Iterator iterator = arraylist.iterator(); - - while (iterator.hasNext()) { - Entity entity = (Entity) iterator.next(); - + public void a(Stream stream) { + stream.forEach((entity) -> { if (this.j(entity)) { this.entityList.add(entity); this.b(entity); } - } + }); } private boolean j(Entity entity) { @@ -1145,7 +1146,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { this.d.add(new BlockActionData(blockposition, block, i, j)); } - private void am() { + private void an() { while (!this.d.isEmpty()) { BlockActionData blockactiondata = (BlockActionData) this.d.removeFirst(); @@ -1168,17 +1169,17 @@ public class WorldServer extends World implements IAsyncTaskHandler { super.close(); } - protected void v() { + protected void w() { boolean flag = this.isRaining(); - super.v(); + super.w(); /* CraftBukkit start if (this.o != this.p) { - this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(7, this.p)), this.worldProvider.getDimensionManager().getDimensionID()); + this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(7, this.p)), this.worldProvider.getDimensionManager()); } if (this.q != this.r) { - this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(8, this.r)), this.worldProvider.getDimensionManager().getDimensionID()); + this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(8, this.r)), this.worldProvider.getDimensionManager()); } if (flag != this.isRaining()) { @@ -1209,11 +1210,11 @@ public class WorldServer extends World implements IAsyncTaskHandler { } - public TickListServer w() { + public TickListServer x() { return this.nextTickListBlock; } - public TickListServer x() { + public TickListServer y() { return this.nextTickListFluid; } @@ -1234,30 +1235,30 @@ public class WorldServer extends World implements IAsyncTaskHandler { return this.portalTravelAgent; } - public DefinedStructureManager C() { + public DefinedStructureManager D() { return this.dataManager.h(); } public int a(T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { // CraftBukkit - visibility api support - return sendParticles(null, t0, d0, d1, d2, i, d3, d4, d5, d6); - } - // Paper start - Particle API Expansion - public int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { - return sendParticles(this.players, sender, t0, false, d0, d1, d2, i, d3, d5, d5, d6); + return sendParticles(null, t0, d0, d1, d2, i, d3, d4, d5, d6, false); } - public int sendParticles(List receivers, EntityPlayer sender, T t0, boolean force, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) { - // CraftBukkit end - PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, (float) d0, (float) d1, (float) d2, (float) d3, (float) d4, (float) d5, (float) d6, i); + public int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { + // Paper start - Particle API Expansion + return sendParticles(players, sender, t0, d0, d1, d2, i, d3, d4, d5, d6, force); + } + public int sendParticles(List receivers, EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { // Paper end + PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, (float) d0, (float) d1, (float) d2, (float) d3, (float) d4, (float) d5, (float) d6, i); + // CraftBukkit end int j = 0; for (EntityHuman entityhuman : receivers) { // Paper - Particle API Expansion EntityPlayer entityplayer = (EntityPlayer) entityhuman; // Paper - Particle API Expansion if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit - if (this.a(entityplayer, false, d0, d1, d2, packetplayoutworldparticles)) { + if (this.a(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit ++j; } } @@ -1301,15 +1302,15 @@ public class WorldServer extends World implements IAsyncTaskHandler { } @Nullable - public BlockPosition a(String s, BlockPosition blockposition, int i) { - return this.getChunkProviderServer().a(this, s, blockposition, i); + public BlockPosition a(String s, BlockPosition blockposition, int i, boolean flag) { + return this.getChunkProviderServer().a(this, s, blockposition, i, flag); } - public CraftingManager D() { + public CraftingManager E() { return this.server.getCraftingManager(); } - public TagRegistry E() { + public TagRegistry F() { return this.server.getTagRegistry(); } @@ -1321,11 +1322,11 @@ public class WorldServer extends World implements IAsyncTaskHandler { return this.getChunkProviderServer(); } - public TickList H() { - return this.x(); + public TickList I() { + return this.y(); } - public TickList I() { - return this.w(); + public TickList J() { + return this.x(); } } diff --git a/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 3304cb586..8ed9c1338 100644 --- a/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/sources/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -20,6 +21,8 @@ import java.util.UUID; import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Pattern; + import javax.imageio.ImageIO; import net.minecraft.server.*; @@ -55,6 +58,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.generator.CraftChunkData; import org.bukkit.craftbukkit.help.SimpleHelpMap; import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe; +import org.bukkit.craftbukkit.inventory.CraftInventoryCustom; import org.bukkit.craftbukkit.inventory.CraftItemFactory; import org.bukkit.craftbukkit.inventory.CraftMerchantCustom; import org.bukkit.craftbukkit.inventory.CraftRecipe; @@ -120,18 +124,22 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.mojang.authlib.GameProfile; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.longs.LongIterator; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Base64; +import java.util.HashMap; import org.bukkit.Keyed; import org.apache.commons.lang.StringUtils; import org.bukkit.NamespacedKey; @@ -746,8 +754,8 @@ public final class CraftServer implements Server { ((DedicatedServer) console).propertyManager = config; boolean animals = config.getBoolean("spawn-animals", console.getSpawnAnimals()); - boolean monsters = config.getBoolean("spawn-monsters", console.worlds.get(0).getDifficulty() != EnumDifficulty.PEACEFUL); - EnumDifficulty difficulty = EnumDifficulty.getById(config.getInt("difficulty", console.worlds.get(0).getDifficulty().ordinal())); + boolean monsters = config.getBoolean("spawn-monsters", console.getWorldServer(DimensionManager.OVERWORLD).getDifficulty() != EnumDifficulty.PEACEFUL); + EnumDifficulty difficulty = EnumDifficulty.getById(config.getInt("difficulty", console.getWorldServer(DimensionManager.OVERWORLD).getDifficulty().ordinal())); online.value = config.getBoolean("online-mode", console.getOnlineMode()); console.setSpawnAnimals(config.getBoolean("spawn-animals", console.getSpawnAnimals())); @@ -778,7 +786,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot com.destroystokyo.paper.PaperConfig.init((File) console.options.valueOf("paper-settings")); // Paper - for (WorldServer world : console.worlds) { + for (WorldServer world : console.getWorlds()) { world.worldData.setDifficulty(difficulty); world.setSpawnFlags(monsters, animals); if (this.getTicksPerAnimalSpawns() < 0) { @@ -954,11 +962,11 @@ public final class CraftServer implements Server { console.convertWorld(name); - int dimension = CraftWorld.CUSTOM_DIMENSION_OFFSET + console.worlds.size(); + int dimension = CraftWorld.CUSTOM_DIMENSION_OFFSET + console.worldServer.size(); boolean used = false; do { - for (WorldServer server : console.worlds) { - used = server.dimension == dimension; + for (WorldServer server : console.getWorlds()) { + used = server.dimension.getDimensionID() == dimension; if (used) { dimension++; break; @@ -968,6 +976,7 @@ public final class CraftServer implements Server { boolean hardcore = false; IDataManager sdm = new ServerNBTManager(getWorldContainer(), name, getServer(), getHandle().getServer().dataConverterManager); + PersistentCollection persistentcollection = new PersistentCollection(sdm); WorldData worlddata = sdm.getWorldData(); WorldSettings worldSettings = null; if (worlddata == null) { @@ -979,7 +988,9 @@ public final class CraftServer implements Server { worlddata = new WorldData(worldSettings, name); } worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) - WorldServer internal = (WorldServer) new WorldServer(console, sdm, worlddata, dimension, console.methodProfiler, creator.environment(), generator).b(); + + DimensionManager internalDimension = new DimensionManager(dimension, name, name, () -> DimensionManager.a(creator.environment().getId()).e()); + WorldServer internal = (WorldServer) new WorldServer(console, sdm, persistentcollection, worlddata, internalDimension, console.methodProfiler, creator.environment(), generator).i_(); if (!(worlds.containsKey(name.toLowerCase(java.util.Locale.ENGLISH)))) { return null; @@ -993,10 +1004,10 @@ public final class CraftServer implements Server { internal.addIWorldAccess(new WorldManager(console, internal)); internal.worldData.setDifficulty(EnumDifficulty.EASY); internal.setSpawnFlags(true, true); - console.worlds.add(internal); + console.worldServer.put(internal.dimension, internal); pluginManager.callEvent(new WorldInitEvent(internal.getWorld())); - System.out.println("Preparing start region for level " + (console.worlds.size() - 1) + " (Seed: " + internal.getSeed() + ")"); + System.out.println("Preparing start region for level " + (console.worldServer.size() - 1) + " (Seed: " + internal.getSeed() + ")"); if (internal.getWorld().getKeepSpawnInMemory()) { short short1 = internal.paperConfig.keepLoadedRange; // Paper @@ -1018,10 +1029,26 @@ public final class CraftServer implements Server { } BlockPosition chunkcoordinates = internal.getSpawn(); - internal.getChunkProviderServer().getChunkAt(chunkcoordinates.getX() + j >> 4, chunkcoordinates.getZ() + k >> 4); + internal.getChunkProviderServer().getChunkAt(chunkcoordinates.getX() + j >> 4, chunkcoordinates.getZ() + k >> 4, true, true); } } } + + DimensionManager dimensionmanager = internalDimension.e().getDimensionManager(); + ForcedChunk forcedchunk = (ForcedChunk) persistentcollection.get(dimensionmanager, ForcedChunk::new, "chunks"); + + if (forcedchunk != null) { + LongIterator longiterator = forcedchunk.a().iterator(); + + while (longiterator.hasNext()) { + System.out.println("Loading forced chunks for dimension " + dimension + ", " + forcedchunk.a().size() * 100 / 625 + "%"); + long k = longiterator.nextLong(); + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k); + + internal.getChunkProviderServer().getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, true, true); + } + } + pluginManager.callEvent(new WorldLoadEvent(internal.getWorld())); return internal.getWorld(); } @@ -1039,11 +1066,11 @@ public final class CraftServer implements Server { WorldServer handle = ((CraftWorld) world).getHandle(); - if (!(console.worlds.contains(handle))) { + if (!(console.worldServer.containsKey(handle.dimension))) { return false; } - if (handle.dimension == 0) { + if (handle.dimension == DimensionManager.OVERWORLD) { return false; } @@ -1068,7 +1095,7 @@ public final class CraftServer implements Server { } worlds.remove(world.getName().toLowerCase(java.util.Locale.ENGLISH)); - console.worlds.remove(console.worlds.indexOf(handle)); + console.worldServer.remove(handle.dimension); File parentFolder = world.getWorldFolder().getAbsoluteFile(); @@ -1312,8 +1339,8 @@ public final class CraftServer implements Server { @Override @Deprecated public CraftMapView getMap(short id) { - PersistentCollection collection = console.worlds.get(0).worldMaps; - WorldMap worldmap = (WorldMap) collection.get(WorldMap::new, "map_" + id); + PersistentCollection collection = console.getWorldServer(DimensionManager.OVERWORLD).worldMaps; + WorldMap worldmap = (WorldMap) collection.get(DimensionManager.OVERWORLD, WorldMap::new, "map_" + id); if (worldmap == null) { return null; } @@ -1513,7 +1540,7 @@ public final class CraftServer implements Server { @Override public GameMode getDefaultGameMode() { - return GameMode.getByValue(console.worlds.get(0).getWorldData().getGameType().getId()); + return GameMode.getByValue(console.getWorldServer(DimensionManager.OVERWORLD).getWorldData().getGameType().getId()); } @Override @@ -1557,7 +1584,7 @@ public final class CraftServer implements Server { @Override public OfflinePlayer[] getOfflinePlayers() { - WorldNBTStorage storage = (WorldNBTStorage) console.worlds.get(0).getDataManager(); + WorldNBTStorage storage = (WorldNBTStorage) console.getWorldServer(DimensionManager.OVERWORLD).getDataManager(); String[] files = storage.getPlayerDir().list(new DatFileFilter()); Set players = new HashSet(); @@ -1820,7 +1847,7 @@ public final class CraftServer implements Server { public Entity getEntity(UUID uuid) { Validate.notNull(uuid, "UUID cannot be null"); - for (WorldServer world : getServer().worlds) { + for (WorldServer world : getServer().getWorlds()) { net.minecraft.server.Entity entity = world.getEntity(uuid); if (entity != null) { return entity.getBukkitEntity(); @@ -1902,8 +1929,8 @@ public final class CraftServer implements Server { public LootTable getLootTable(NamespacedKey key) { Validate.notNull(key, "NamespacedKey cannot be null"); - LootTableRegistry registry = getServer().aP(); // PAIL getLootTableRegistry - return new CraftLootTable(key, registry.a(CraftNamespacedKey.toMinecraft(key))); // PAIL rename getLootTable + LootTableRegistry registry = getServer().getLootTableRegistry(); + return new CraftLootTable(key, registry.getLootTable(CraftNamespacedKey.toMinecraft(key))); } @Deprecated diff --git a/sources/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/sources/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 748bed397..033ca3679 100644 --- a/sources/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/sources/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -247,10 +247,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { - PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); - packet.header = header; - packet.footer = footer; - getHandle().playerConnection.sendPacket(packet); + setPlayerListHeader(header == null ? null : net.md_5.bungee.chat.ComponentSerializer.toString(header)); + setPlayerListFooter(footer == null ? null : net.md_5.bungee.chat.ComponentSerializer.toString(footer)); } @Override @@ -387,8 +385,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (getHandle().playerConnection == null) return; PacketPlayOutPlayerListHeaderFooter packet = new PacketPlayOutPlayerListHeaderFooter(); - packet.a = (this.playerListHeader == null) ? new ChatComponentText("") : this.playerListHeader; - packet.b = (this.playerListFooter == null) ? new ChatComponentText("") : this.playerListFooter; + packet.header = (this.playerListHeader == null) ? new ChatComponentText("") : this.playerListHeader; + packet.footer = (this.playerListFooter == null) ? new ChatComponentText("") : this.playerListFooter; getHandle().playerConnection.sendPacket(packet); } @@ -1937,7 +1935,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { { if ( getHealth() <= 0 && isOnline() ) { - server.getServer().getPlayerList().moveToWorld( getHandle(), 0, false ); + server.getServer().getPlayerList().moveToWorld( getHandle(), net.minecraft.server.DimensionManager.OVERWORLD, false ); } } diff --git a/sources/src/main/java/org/bukkit/plugin/EventExecutor.java b/sources/src/main/java/org/bukkit/plugin/EventExecutor.java deleted file mode 100644 index 97affdf49..000000000 --- a/sources/src/main/java/org/bukkit/plugin/EventExecutor.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.bukkit.plugin; - -import org.bukkit.event.Event; -import org.bukkit.event.EventException; -import org.bukkit.event.Listener; -// Paper start -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.function.Function; - -import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor; -import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor; -import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator; -import com.destroystokyo.paper.event.executor.asm.ClassDefiner; -import com.google.common.base.Preconditions; - -import io.akarin.api.internal.Akari; -// Paper end -import io.akarin.server.core.AkarinGlobalConfig; - -/** - * Akarin Changes Note - * 1) Suspend for event (safety issue) - */ -/** - * Interface which defines the class for event call backs to plugins - */ -public interface EventExecutor { - public void execute(Listener listener, Event event) throws EventException; - - // Paper start - ConcurrentMap> eventExecutorMap = new ConcurrentHashMap>() { - @Override - public Class computeIfAbsent(Method key, Function> mappingFunction) { - Class executorClass = get(key); - if (executorClass != null) - return executorClass; - - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized (key) { - executorClass = get(key); - if (executorClass != null) - return executorClass; - - return super.computeIfAbsent(key, mappingFunction); - } - } - }; - - public static EventExecutor create(Method m, Class eventClass) { - Preconditions.checkNotNull(m, "Null method"); - Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); - Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); - ClassDefiner definer = ClassDefiner.getInstance(); - if (Modifier.isStatic(m.getModifiers())) { - return new StaticMethodHandleEventExecutor(eventClass, m); - } else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { - // get the existing generated EventExecutor class for the Method or generate one - Class executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> { - String name = ASMEventExecutorGenerator.generateName(); - byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name); - return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class); - }); - - try { - EventExecutor asmExecutor = executorClass.newInstance(); - // Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception) - return new EventExecutor() { - @Override - public void execute(Listener listener, Event event) throws EventException { - if (!eventClass.isInstance(event)) return; - try { - // Akarin start - if (false && AkarinGlobalConfig.parallelMode != -1) { - Akari.eventSuspendTiming.startTiming(); - Akari.timingsLock.lock(); - Akari.STAGE_TICK.suspend(); - Akari.eventSuspendTiming.stopTiming(); - } - // Akarin end - asmExecutor.execute(listener, event); - // Akarin start - if (false && AkarinGlobalConfig.parallelMode != -1) { - Akari.eventResumeTiming.startTiming(); - Akari.STAGE_TICK.resume(); - Akari.timingsLock.unlock(); - Akari.eventResumeTiming.stopTiming(); - } - // Akarin end - } catch (Exception e) { - throw new EventException(e); - } - } - }; - } catch (InstantiationException | IllegalAccessException e) { - throw new AssertionError("Unable to initialize generated event executor", e); - } - } else { - return new MethodHandleEventExecutor(eventClass, m); - } - } - // Paper end -} diff --git a/sources/src/main/resources/mixins.akarin.core.json b/sources/src/main/resources/mixins.akarin.core.json index 74a5e81d2..40a75b0aa 100644 --- a/sources/src/main/resources/mixins.akarin.core.json +++ b/sources/src/main/resources/mixins.akarin.core.json @@ -25,6 +25,7 @@ "core.MixinChunkIOExecutor", "core.MixinPlayerConnectionUtils", + "nsc.OptimisticNetworkManager", "nsc.NonblockingServerConnection", "optimization.MixinEntity", diff --git a/sources/src/main/resources/mixins.akarin.optimization.chunk.json b/sources/src/main/resources/mixins.akarin.optimization.chunk.json deleted file mode 100644 index 3e0eb4f29..000000000 --- a/sources/src/main/resources/mixins.akarin.optimization.chunk.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "required": true, - "minVersion": "0.7.10", - "package": "io.akarin.server.mixin", - "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8", - "server": [ - "cps.MixinCraftWorld", - "cps.MixinChunkProviderServer", - ] -} \ No newline at end of file diff --git a/work/Paper b/work/Paper index 83ba855ba..e84839f56 160000 --- a/work/Paper +++ b/work/Paper @@ -1 +1 @@ -Subproject commit 83ba855ba6c1e3838c7eea8aa56f54490578c1c6 +Subproject commit e84839f56de2deeee7689ca6fafc2ef628f1d7b6